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