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