1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 #include <mach/std_types.h>
26 #include <ppc/proc_reg.h>
27 #include <ppc/boot.h>
28 #include <ppc/mem.h>
29
30 // The sophisticated BAT manager
31
32 unsigned int mappedSegments = 0;
33 unsigned int availableBATs = 0xE; // BAT0 used, 1-3 available
34
35 vm_offset_t
36 PEResidentAddress( vm_offset_t address, vm_size_t length )
37 {
38 if( mappedSegments & (1 << (15 & (address >> 28))))
39 return( address);
40 else
41 return( 0);
42 }
43
44 vm_offset_t
45 PEMapSegment( vm_offset_t address, vm_size_t length )
46 {
47 vm_offset_t retAddress;
48 bat_t bat;
49 int batNum;
50
51 retAddress = PEResidentAddress( address, length );
52 if( retAddress)
53 return( retAddress);
54
55 if( length < (256 * 1024))
56 return( 0);
57 if( availableBATs == 0)
58 return( 0);
59
60 for( batNum = 0;
61 (0 == (availableBATs & (1 << batNum)));
62 batNum++);
63
64 bat.upper.word = address & 0xf0000000;
65 bat.lower.word = bat.upper.word;
66
67 bat.upper.bits.bl = 0x7ff; /* size = 256M */
68 bat.upper.bits.vs = 1;
69 bat.upper.bits.vp = 0; /* user disabled */
70
71 bat.lower.bits.wimg = PTE_WIMG_IO;
72 bat.lower.bits.pp = 2; /* read/write access */
73
74 // Update the shadow bats.
75 shadow_BAT.DBATs[batNum].upper = bat.upper.word;
76 shadow_BAT.DBATs[batNum].lower = bat.lower.word;
77
78 sync();isync();
79 switch( batNum) { // !%$@!! mtdbat needs literal
80 case 0:
81 mtdbatu( 0, BAT_INVALID); /* invalidate old mapping */
82 mtdbatl( 0, bat.lower.word);
83 mtdbatu( 0, bat.upper.word);
84 break;
85 case 1:
86 mtdbatu( 1, BAT_INVALID);
87 mtdbatl( 1, bat.lower.word);
88 mtdbatu( 1, bat.upper.word);
89 break;
90 case 2:
91 mtdbatu( 2, BAT_INVALID);
92 mtdbatl( 2, bat.lower.word);
93 mtdbatu( 2, bat.upper.word);
94 break;
95 case 3:
96 mtdbatu( 3, BAT_INVALID);
97 mtdbatl( 3, bat.lower.word);
98 mtdbatu( 3, bat.upper.word);
99 break;
100 }
101 sync();isync();
102
103 availableBATs &= ~(1 << batNum);
104 mappedSegments |= (1 << (15 & (address >> 28)));
105
106 return( address);
107 }
108
109 void initialize_bats(boot_args *args)
110 {
111 int i;
112
113 /* Give ourselves the virtual map that we would like */
114 bat_t bat;
115
116 /* Make sure that the BATs map what we expect. Note
117 * that we assume BAT0 maps kernel text & data.
118 *
119 * Except, oops, none of the BATs have ever been set.
120 * Developer worked only by fluke.
121 */
122
123 bat.upper.word = 0;
124 bat.upper.bits.bepi = 0x0; /* start at logical addr 0M */
125 /*
126 * We should be smarter here about picking an
127 * amount to map
128 */
129 bat.upper.bits.bl = 0x7ff; /* size = 256M */
130 bat.upper.bits.vs = 1;
131 bat.upper.bits.vp = 0;
132
133 bat.lower.word = 0;
134 bat.lower.bits.brpn = 0x0; /* start at physical addr 0 */
135 bat.lower.bits.wimg = PTE_WIMG_DEFAULT;
136 bat.lower.bits.pp = 2; /* read/write access */
137
138 /* Mustn't cause any data traffic here,
139 * we're modifying our data BAT register!
140 */
141
142 sync();
143 mtdbatu(0, BAT_INVALID); /* invalidate old mapping */
144 isync();
145 mtdbatl(0, bat.lower.word);
146 isync();
147 mtdbatu(0, bat.upper.word); /* update with new mapping */
148 isync();
149 mtibatl(0, bat.lower.word);
150 isync();
151 mtibatu(0, bat.upper.word); /* update with new mapping */
152 isync();
153
154 sync();isync();
155 mtdbatu(1,BAT_INVALID); mtdbatl(1,BAT_INVALID);
156 mtibatu(1,BAT_INVALID); mtibatl(1,BAT_INVALID);
157 mtdbatu(2,BAT_INVALID); mtdbatl(2,BAT_INVALID);
158 mtibatu(2,BAT_INVALID); mtibatl(2,BAT_INVALID);
159 mtdbatu(3,BAT_INVALID); mtdbatl(3,BAT_INVALID);
160 mtibatu(3,BAT_INVALID); mtibatl(3,BAT_INVALID);
161 sync();isync();
162
163 PEMapSegment( 0xf0000000, 0x10000000);
164 if( args->Video.v_baseAddr)
165 PEMapSegment( args->Video.v_baseAddr, 0x10000000);
166
167 /* Set up segment registers as VM through space 0 */
168 isync();
169 for (i=0; i<=15; i++) {
170 mtsrin(KERNEL_SEG_REG0_VALUE | i, i * 0x10000000);
171 }
172 isync();
173 }
174
175 /*
176 * Adjust the size of the region mapped by a BAT
177 * to to be just large enough to include the specified
178 * offset, and return the offset of the new end of the region.
179 * Note that both 'offsets' are really *lengths*, i.e. the
180 * offset of the end of the mapped region from the beginning.
181 * Either the instruction or data BATs (or both) can be specified.
182 * If the new length is greater than the size mappable by a BAT,
183 * then that value is just returned and no changes are made.
184 */
185 vm_offset_t
186 adjust_bat_limit(
187 vm_offset_t new_minimum,
188 int batn,
189 boolean_t ibat,
190 boolean_t dbat
191 )
192 {
193 vm_offset_t new_limit;
194
195 if (new_minimum <= 256*1024*1024) {
196 unsigned int bl = 0;
197
198 new_limit = 128*1024;
199 while (new_limit < new_minimum) {
200 new_limit *= 2;
201 bl = (bl << 1) | 1;
202 }
203
204 {
205 batu_t batu;
206
207 if (dbat) switch (batn) {
208
209 case 0:
210 mfdbatu(batu, 0 );
211 batu.bits.bl = bl;
212
213 sync(); isync();
214 mtdbatu( 0, batu);
215 sync(); isync();
216
217 break;
218
219 case 1:
220 mfdbatu(batu, 1 );
221 batu.bits.bl = bl;
222
223 sync(); isync();
224 mtdbatu( 1, batu);
225 sync(); isync();
226
227 break;
228
229 case 2:
230 mfdbatu(batu, 2 );
231 batu.bits.bl = bl;
232
233 sync(); isync();
234 mtdbatu( 2, batu);
235 sync(); isync();
236
237 break;
238
239 case 3:
240 mfdbatu(batu, 3 );
241 batu.bits.bl = bl;
242
243 sync(); isync();
244 mtdbatu( 3, batu);
245 sync(); isync();
246
247 break;
248 }
249
250 if (ibat) switch (batn) {
251
252 case 0:
253 mfibatu(batu, 0 );
254 batu.bits.bl = bl;
255
256 sync(); isync();
257 mtibatu( 0, batu);
258 sync(); isync();
259
260 break;
261
262 case 1:
263 mfibatu(batu, 1 );
264 batu.bits.bl = bl;
265
266 sync(); isync();
267 mtibatu( 1, batu);
268 sync(); isync();
269
270 break;
271
272 case 2:
273 mfibatu(batu, 2 );
274 batu.bits.bl = bl;
275
276 sync(); isync();
277 mtibatu( 2, batu);
278 sync(); isync();
279
280 break;
281
282 case 3:
283 mfibatu(batu, 3 );
284 batu.bits.bl = bl;
285
286 sync(); isync();
287 mtibatu( 3, batu);
288 sync(); isync();
289
290 break;
291 }
292 }
293 }
294 else
295 new_limit = new_minimum;
296
297 return (new_limit);
298 }
Cache object: a35b6821c3574a40e260f268f8b3e179
|