|
|
1.1 root 1: /*
2: * Copyright (c) 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: #include <mach/std_types.h>
23: #include <ppc/proc_reg.h>
24: #include <ppc/boot.h>
25: #include <ppc/mem.h>
26:
27: #ifdef XXX_LOADER
28: unsigned int kernel_seg_regs[] = {
29: KERNEL_SEG_REG0_VALUE,
30: KERNEL_SEG_REG1_VALUE,
31: SEG_REG_INVALID, /* 2 */
32: SEG_REG_INVALID, /* 3 */
33: SEG_REG_INVALID, /* 4 */
34: KERNEL_SEG_REG5_VALUE, /* 5 - I/O segment */
35: SEG_REG_INVALID, /* 6 */
36: SEG_REG_INVALID, /* 7 */
37: KERNEL_SEG_REG8_VALUE, /* 8-F are possible IO space */
38: KERNEL_SEG_REG9_VALUE,
39: KERNEL_SEG_REG10_VALUE,
40: KERNEL_SEG_REG11_VALUE,
41: KERNEL_SEG_REG12_VALUE,
42: KERNEL_SEG_REG13_VALUE,
43: KERNEL_SEG_REG14_VALUE, /* 14 - A/V video */
44: KERNEL_SEG_REG15_VALUE /* 15 - NuBus etc */
45: };
46: #else
47: extern unsigned int kernel_seg_regs[];
48: #endif
49:
50: // The sophisticated BAT manager
51:
52: unsigned int mappedSegments = 0;
53: unsigned int availableBATs = 0xE; // BAT0 used, 1-3 available
54:
55: vm_offset_t
56: PEResidentAddress( vm_offset_t address, vm_size_t length )
57: {
58: if( mappedSegments & (1 << (15 & (address >> 28))))
59: return( address);
60: else
61: return( 0);
62: }
63:
64: vm_offset_t
65: PEMapSegment( vm_offset_t address, vm_size_t length )
66: {
67: vm_offset_t retAddress;
68: bat_t bat;
69: int batNum;
70:
71: retAddress = PEResidentAddress( address, length );
72: if( retAddress)
73: return( retAddress);
74:
75: if( length < (256 * 1024))
76: return( 0);
77: if( availableBATs == 0)
78: return( 0);
79:
80: for( batNum = 0;
81: (0 == (availableBATs & (1 << batNum)));
82: batNum++);
83:
84: bat.upper.word = address & 0xf0000000;
85: bat.lower.word = bat.upper.word;
86:
87: bat.upper.bits.bl = 0x7ff; /* size = 256M */
88: bat.upper.bits.vs = 1;
89: bat.upper.bits.vp = 0; /* user disabled */
90:
91: bat.lower.bits.wimg = PTE_WIMG_IO;
92: bat.lower.bits.pp = 2; /* read/write access */
93:
94: // Update the shadow bats.
95: shadow_BAT.DBATs[batNum].upper = bat.upper.word;
96: shadow_BAT.DBATs[batNum].lower = bat.lower.word;
97:
98: sync();isync();
99: switch( batNum) { // !%$@!! mtdbat needs literal
100: case 0:
101: mtdbatu( 0, BAT_INVALID); /* invalidate old mapping */
102: mtdbatl( 0, bat.lower.word);
103: mtdbatu( 0, bat.upper.word);
104: break;
105: case 1:
106: mtdbatu( 1, BAT_INVALID);
107: mtdbatl( 1, bat.lower.word);
108: mtdbatu( 1, bat.upper.word);
109: break;
110: case 2:
111: mtdbatu( 2, BAT_INVALID);
112: mtdbatl( 2, bat.lower.word);
113: mtdbatu( 2, bat.upper.word);
114: break;
115: case 3:
116: mtdbatu( 3, BAT_INVALID);
117: mtdbatl( 3, bat.lower.word);
118: mtdbatu( 3, bat.upper.word);
119: break;
120: }
121: sync();isync();
122:
123: availableBATs &= ~(1 << batNum);
124: mappedSegments |= (1 << (15 & (address >> 28)));
125:
126: return( address);
127: }
128:
129: void initialize_bats(boot_args *args)
130: {
131: int i;
132:
133: /* Give ourselves the virtual map that we would like */
134: bat_t bat;
135:
136: /* Make sure that the BATs map what we expect. Note
137: * that we assume BAT0 maps kernel text & data.
138: *
139: * Except, oops, none of the BATs have ever been set.
140: * Developer worked only by fluke.
141: */
142:
143: bat.upper.word = 0;
144: bat.upper.bits.bepi = 0x0; /* start at logical addr 0M */
145: /*
146: * We should be smarter here about picking an
147: * amount to map
148: */
149: bat.upper.bits.bl = 0x7ff; /* size = 256M */
150: bat.upper.bits.vs = 1;
151: bat.upper.bits.vp = 0;
152:
153: bat.lower.word = 0;
154: bat.lower.bits.brpn = 0x0; /* start at physical addr 0 */
155: bat.lower.bits.wimg = PTE_WIMG_DEFAULT;
156: bat.lower.bits.pp = 2; /* read/write access */
157:
158: /* Mustn't cause any data traffic here,
159: * we're modifying our data BAT register!
160: */
161:
162: sync();
163: mtdbatu(0, BAT_INVALID); /* invalidate old mapping */
164: isync();
165: mtdbatl(0, bat.lower.word);
166: isync();
167: mtdbatu(0, bat.upper.word); /* update with new mapping */
168: isync();
169: mtibatl(0, bat.lower.word);
170: isync();
171: mtibatu(0, bat.upper.word); /* update with new mapping */
172: isync();
173:
174: sync();isync();
175: mtdbatu(1,BAT_INVALID); mtdbatl(1,BAT_INVALID);
176: mtibatu(1,BAT_INVALID); mtibatl(1,BAT_INVALID);
177: mtdbatu(2,BAT_INVALID); mtdbatl(2,BAT_INVALID);
178: mtibatu(2,BAT_INVALID); mtibatl(2,BAT_INVALID);
179: mtdbatu(3,BAT_INVALID); mtdbatl(3,BAT_INVALID);
180: mtibatu(3,BAT_INVALID); mtibatl(3,BAT_INVALID);
181: sync();isync();
182:
183: PEMapSegment( 0xf0000000, 0x10000000);
184: if( args->Video.v_baseAddr)
185: PEMapSegment( args->Video.v_baseAddr, 0x10000000);
186:
187: /* Set up segment registers as VM through space 0 */
188: isync();
189: for (i=0; i<=15; i++) {
190: mtsrin(KERNEL_SEG_REG0_VALUE | i, i * 0x10000000);
191: }
192: isync();
193: }
194:
195: /*
196: * Adjust the size of the region mapped by a BAT
197: * to to be just large enough to include the specified
198: * offset, and return the offset of the new end of the region.
199: * Note that both 'offsets' are really *lengths*, i.e. the
200: * offset of the end of the mapped region from the beginning.
201: * Either the instruction or data BATs (or both) can be specified.
202: * If the new length is greater than the size mappable by a BAT,
203: * then that value is just returned and no changes are made.
204: */
205: vm_offset_t
206: adjust_bat_limit(
207: vm_offset_t new_minimum,
208: int batn,
209: boolean_t ibat,
210: boolean_t dbat
211: )
212: {
213: vm_offset_t new_limit;
214:
215: if (new_minimum <= 256*1024*1024) {
216: unsigned int bl = 0;
217:
218: new_limit = 128*1024;
219: while (new_limit < new_minimum) {
220: new_limit *= 2;
221: bl = (bl << 1) | 1;
222: }
223:
224: {
225: batu_t batu;
226:
227: if (dbat) switch (batn) {
228:
229: case 0:
230: mfdbatu(batu, 0 );
231: batu.bits.bl = bl;
232:
233: sync(); isync();
234: mtdbatu( 0, batu);
235: sync(); isync();
236:
237: break;
238:
239: case 1:
240: mfdbatu(batu, 1 );
241: batu.bits.bl = bl;
242:
243: sync(); isync();
244: mtdbatu( 1, batu);
245: sync(); isync();
246:
247: break;
248:
249: case 2:
250: mfdbatu(batu, 2 );
251: batu.bits.bl = bl;
252:
253: sync(); isync();
254: mtdbatu( 2, batu);
255: sync(); isync();
256:
257: break;
258:
259: case 3:
260: mfdbatu(batu, 3 );
261: batu.bits.bl = bl;
262:
263: sync(); isync();
264: mtdbatu( 3, batu);
265: sync(); isync();
266:
267: break;
268: }
269:
270: if (ibat) switch (batn) {
271:
272: case 0:
273: mfibatu(batu, 0 );
274: batu.bits.bl = bl;
275:
276: sync(); isync();
277: mtibatu( 0, batu);
278: sync(); isync();
279:
280: break;
281:
282: case 1:
283: mfibatu(batu, 1 );
284: batu.bits.bl = bl;
285:
286: sync(); isync();
287: mtibatu( 1, batu);
288: sync(); isync();
289:
290: break;
291:
292: case 2:
293: mfibatu(batu, 2 );
294: batu.bits.bl = bl;
295:
296: sync(); isync();
297: mtibatu( 2, batu);
298: sync(); isync();
299:
300: break;
301:
302: case 3:
303: mfibatu(batu, 3 );
304: batu.bits.bl = bl;
305:
306: sync(); isync();
307: mtibatu( 3, batu);
308: sync(); isync();
309:
310: break;
311: }
312: }
313: }
314: else
315: new_limit = new_minimum;
316:
317: return (new_limit);
318: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.