]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/bat_init.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
22 #include <mach/std_types.h>
23 #include <ppc/proc_reg.h>
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 */
47 extern unsigned int kernel_seg_regs
[];
50 // The sophisticated BAT manager
52 unsigned int mappedSegments
= 0;
53 unsigned int availableBATs
= 0xE; // BAT0 used, 1-3 available
56 PEResidentAddress( vm_offset_t address
, vm_size_t length
)
58 if( mappedSegments
& (1 << (15 & (address
>> 28))))
65 PEMapSegment( vm_offset_t address
, vm_size_t length
)
67 vm_offset_t retAddress
;
71 retAddress
= PEResidentAddress( address
, length
);
75 if( length
< (256 * 1024))
77 if( availableBATs
== 0)
81 (0 == (availableBATs
& (1 << batNum
)));
84 bat
.upper
.word
= address
& 0xf0000000;
85 bat
.lower
.word
= bat
.upper
.word
;
87 bat
.upper
.bits
.bl
= 0x7ff; /* size = 256M */
88 bat
.upper
.bits
.vs
= 1;
89 bat
.upper
.bits
.vp
= 0; /* user disabled */
91 bat
.lower
.bits
.wimg
= PTE_WIMG_IO
;
92 bat
.lower
.bits
.pp
= 2; /* read/write access */
94 // Update the shadow bats.
95 shadow_BAT
.DBATs
[batNum
].upper
= bat
.upper
.word
;
96 shadow_BAT
.DBATs
[batNum
].lower
= bat
.lower
.word
;
99 switch( batNum
) { // !%$@!! mtdbat needs literal
101 mtdbatu( 0, BAT_INVALID
); /* invalidate old mapping */
102 mtdbatl( 0, bat
.lower
.word
);
103 mtdbatu( 0, bat
.upper
.word
);
106 mtdbatu( 1, BAT_INVALID
);
107 mtdbatl( 1, bat
.lower
.word
);
108 mtdbatu( 1, bat
.upper
.word
);
111 mtdbatu( 2, BAT_INVALID
);
112 mtdbatl( 2, bat
.lower
.word
);
113 mtdbatu( 2, bat
.upper
.word
);
116 mtdbatu( 3, BAT_INVALID
);
117 mtdbatl( 3, bat
.lower
.word
);
118 mtdbatu( 3, bat
.upper
.word
);
123 availableBATs
&= ~(1 << batNum
);
124 mappedSegments
|= (1 << (15 & (address
>> 28)));
129 void initialize_bats(boot_args
*args
)
133 /* Give ourselves the virtual map that we would like */
136 /* Make sure that the BATs map what we expect. Note
137 * that we assume BAT0 maps kernel text & data.
139 * Except, oops, none of the BATs have ever been set.
140 * Developer worked only by fluke.
144 bat
.upper
.bits
.bepi
= 0x0; /* start at logical addr 0M */
146 * We should be smarter here about picking an
149 bat
.upper
.bits
.bl
= 0x7ff; /* size = 256M */
150 bat
.upper
.bits
.vs
= 1;
151 bat
.upper
.bits
.vp
= 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 */
158 /* Mustn't cause any data traffic here,
159 * we're modifying our data BAT register!
163 mtdbatu(0, BAT_INVALID
); /* invalidate old mapping */
165 mtdbatl(0, bat
.lower
.word
);
167 mtdbatu(0, bat
.upper
.word
); /* update with new mapping */
169 mtibatl(0, bat
.lower
.word
);
171 mtibatu(0, bat
.upper
.word
); /* update with new mapping */
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
);
183 PEMapSegment( 0xf0000000, 0x10000000);
184 if( args
->Video
.v_baseAddr
)
185 PEMapSegment( args
->Video
.v_baseAddr
, 0x10000000);
187 /* Set up segment registers as VM through space 0 */
189 for (i
=0; i
<=15; i
++) {
190 mtsrin(KERNEL_SEG_REG0_VALUE
| i
, i
* 0x10000000);
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.
207 vm_offset_t new_minimum
,
213 vm_offset_t new_limit
;
215 if (new_minimum
<= 256*1024*1024) {
218 new_limit
= 128*1024;
219 while (new_limit
< new_minimum
) {
227 if (dbat
) switch (batn
) {
270 if (ibat
) switch (batn
) {
315 new_limit
= new_minimum
;