#include <mach/std_types.h>
#include <ppc/proc_reg.h>
#include <ppc/boot.h>
#include <ppc/mem.h>
unsigned int mappedSegments = 0;
unsigned int availableBATs = 0xE;
vm_offset_t
PEResidentAddress( vm_offset_t address, vm_size_t length )
{
if( mappedSegments & (1 << (15 & (address >> 28))))
return( address);
else
return( 0);
}
vm_offset_t
PEMapSegment( vm_offset_t address, vm_size_t length )
{
vm_offset_t retAddress;
bat_t bat;
int batNum;
retAddress = PEResidentAddress( address, length );
if( retAddress)
return( retAddress);
if( length < (256 * 1024))
return( 0);
if( availableBATs == 0)
return( 0);
for( batNum = 0;
(0 == (availableBATs & (1 << batNum)));
batNum++);
bat.upper.word = address & 0xf0000000;
bat.lower.word = bat.upper.word;
bat.upper.bits.bl = 0x7ff;
bat.upper.bits.vs = 1;
bat.upper.bits.vp = 0;
bat.lower.bits.wimg = PTE_WIMG_IO;
bat.lower.bits.pp = 2;
shadow_BAT.DBATs[batNum].upper = bat.upper.word;
shadow_BAT.DBATs[batNum].lower = bat.lower.word;
sync();isync();
switch( batNum) { case 0:
mtdbatu( 0, BAT_INVALID);
mtdbatl( 0, bat.lower.word);
mtdbatu( 0, bat.upper.word);
break;
case 1:
mtdbatu( 1, BAT_INVALID);
mtdbatl( 1, bat.lower.word);
mtdbatu( 1, bat.upper.word);
break;
case 2:
mtdbatu( 2, BAT_INVALID);
mtdbatl( 2, bat.lower.word);
mtdbatu( 2, bat.upper.word);
break;
case 3:
mtdbatu( 3, BAT_INVALID);
mtdbatl( 3, bat.lower.word);
mtdbatu( 3, bat.upper.word);
break;
}
sync();isync();
availableBATs &= ~(1 << batNum);
mappedSegments |= (1 << (15 & (address >> 28)));
return( address);
}
void initialize_bats(boot_args *args)
{
int i;
bat_t bat;
bat.upper.word = 0;
bat.upper.bits.bepi = 0x0;
bat.upper.bits.bl = 0x7ff;
bat.upper.bits.vs = 1;
bat.upper.bits.vp = 0;
bat.lower.word = 0;
bat.lower.bits.brpn = 0x0;
bat.lower.bits.wimg = PTE_WIMG_DEFAULT;
bat.lower.bits.pp = 2;
sync();
mtdbatu(0, BAT_INVALID);
isync();
mtdbatl(0, bat.lower.word);
isync();
mtdbatu(0, bat.upper.word);
isync();
mtibatl(0, bat.lower.word);
isync();
mtibatu(0, bat.upper.word);
isync();
sync();isync();
mtdbatu(1,BAT_INVALID); mtdbatl(1,BAT_INVALID);
mtibatu(1,BAT_INVALID); mtibatl(1,BAT_INVALID);
mtdbatu(2,BAT_INVALID); mtdbatl(2,BAT_INVALID);
mtibatu(2,BAT_INVALID); mtibatl(2,BAT_INVALID);
mtdbatu(3,BAT_INVALID); mtdbatl(3,BAT_INVALID);
mtibatu(3,BAT_INVALID); mtibatl(3,BAT_INVALID);
sync();isync();
PEMapSegment( 0xf0000000, 0x10000000);
if( args->Video.v_baseAddr)
PEMapSegment( args->Video.v_baseAddr, 0x10000000);
isync();
for (i=0; i<=15; i++) {
mtsrin(KERNEL_SEG_REG0_VALUE | i, i * 0x10000000);
}
isync();
}
vm_offset_t
adjust_bat_limit(
vm_offset_t new_minimum,
int batn,
boolean_t ibat,
boolean_t dbat
)
{
vm_offset_t new_limit;
if (new_minimum <= 256*1024*1024) {
unsigned int bl = 0;
new_limit = 128*1024;
while (new_limit < new_minimum) {
new_limit *= 2;
bl = (bl << 1) | 1;
}
{
batu_t batu;
if (dbat) switch (batn) {
case 0:
mfdbatu(batu, 0 );
batu.bits.bl = bl;
sync(); isync();
mtdbatu( 0, batu);
sync(); isync();
break;
case 1:
mfdbatu(batu, 1 );
batu.bits.bl = bl;
sync(); isync();
mtdbatu( 1, batu);
sync(); isync();
break;
case 2:
mfdbatu(batu, 2 );
batu.bits.bl = bl;
sync(); isync();
mtdbatu( 2, batu);
sync(); isync();
break;
case 3:
mfdbatu(batu, 3 );
batu.bits.bl = bl;
sync(); isync();
mtdbatu( 3, batu);
sync(); isync();
break;
}
if (ibat) switch (batn) {
case 0:
mfibatu(batu, 0 );
batu.bits.bl = bl;
sync(); isync();
mtibatu( 0, batu);
sync(); isync();
break;
case 1:
mfibatu(batu, 1 );
batu.bits.bl = bl;
sync(); isync();
mtibatu( 1, batu);
sync(); isync();
break;
case 2:
mfibatu(batu, 2 );
batu.bits.bl = bl;
sync(); isync();
mtibatu( 2, batu);
sync(); isync();
break;
case 3:
mfibatu(batu, 3 );
batu.bits.bl = bl;
sync(); isync();
mtibatu( 3, batu);
sync(); isync();
break;
}
}
}
else
new_limit = new_minimum;
return (new_limit);
}