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