home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 2: PC
/
frozenfish_august_1995.bin
/
bbs
/
d04xx
/
d0400.lha
/
SetCPU
/
mmu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-03
|
9KB
|
277 lines
/*
SetCPU V1.60
by Dave Haynie, April 13, 1990
Released to the Public Domain
MMU.C MODULE
This module is responsible for some of the MMU table creation
functions.
*/
#include "setcpu.h"
/* ====================================================================== */
/* This function maps the phantom area for a given memory location. */
void Phantom(tag,loc)
struct systag *tag;
ULONG loc;
{
ULONG xindex = loc/ROMROUND;
if (xindex < 60)
tag->maintable[xindex] = PD_ADDR(0x00800000)|PD_DT_PAGE;
else
tag->maintable[xindex] = PD_ADDR(0x00ce0000)|PD_DT_PAGE;
}
/* This table contains a list of the blocks of memory that should be
cache-inhibited. */
static ULONG InTable[] = { 0x00000000,0x00200000,0x00b00000,0x00f00000,0L,0L };
/* This function fills the basic MMU table and other standard tag itemd from
an allocated image. Some tables may need additional information in the
table. The basic table consists of one table level and uses direct page
translation on a grain of 128K per entry. Everything's directly mapped
except for the last two entries, which are for the $FC0000-$FFFFFF area. */
void FillBasicTable(tag,phantoms)
struct systag *tag;
LONG phantoms;
{
register ULONG i, image, j;
ULONG page,size,loc;
tag->tagsize = SizeOf(struct systag);
tag->progver = PROGRAM_VERSION;
tag->patches = 0;
tag->patchlist = tag->devs = NULL;
tag->config = 1;
tag->BerrSize = 0L;
tag->OldBerr = tag->BerrHandler = NULL;
tag->sysstack = NULL;
tag->sysstksize = 0;
tag->OldReset = tag->ResetCode = NULL;
tag->ResetSize = 0;
/* Here I make a table that maps everything straight through. */
for (i = 0; i < tag->tablesize/sizeof(ULONG); i++)
tag->maintable[i] = PD_ADDR(i<<17)|PD_DT_PAGE;
tag->maintable[i] = IV_ADDR(tag)|PD_DT_INVALID;
/* Mark the inhibited pages. */
for (i = 0; InTable[i+1]; i += 2)
for (j = InTable[i]/PAGESIZE; j < InTable[i+1]/PAGESIZE; ++j)
tag->maintable[j] |= PD_CI;
/* Here I map the ROM image to the ROM location. */
image = (ULONG)tag->romlo;
loc = tag->romloc/PAGESIZE;
if (image) {
if (phantoms) Phantom(tag,image);
tag->maintable[loc++] = PD_ADDR(image)|PD_WP|PD_DT_PAGE;
if (phantoms) Phantom(tag,image+PAGESIZE);
tag->maintable[loc++] = PD_ADDR(image+PAGESIZE)|PD_WP|PD_DT_PAGE;
}
image = (ULONG)tag->romhi;
if (phantoms) Phantom(tag,image);
tag->maintable[loc++] = PD_ADDR(image)|PD_WP|PD_DT_PAGE;
if (phantoms) Phantom(tag,image+PAGESIZE);
tag->maintable[loc] = PD_ADDR(image+PAGESIZE)|PD_WP|PD_DT_PAGE;
/* Here I look for Bridge Cards, which are known to have problems with
the data cache enabled, so I always disable it, reguardless of
whether caching is actually enabled in the CACR. */
if (Bridge.Addr && Bridge.Size) {
page = Bridge.Addr/PAGESIZE;
size = max((ULONG)Bridge.Size/PAGESIZE,1);
while (size-- && page < tag->tablesize)
if ((tag->maintable[page] & PD_DT_TYPE) == PD_DT_PAGE)
tag->maintable[page++] |= PD_CI;
}
}
/* This routine sets up the MMU registers (shadowed in tag fields) in the
standard SetCPU fashion. The CPU Root Pointer tells the MMU about the
table I've set up, and all that's left to do is bang the Translation
Control Register to turn the thing on. Note that the first half of the
CRP is control data, the second the address of my table. */
void SetMMURegs(tag)
struct systag *tag;
{
tag->CRP[0] = CRP_LIMIT(tag->tablesize/sizeof(ULONG)-1)|CRP_SG|CRP_DT_V4BYTE;
tag->CRP[1] = (ULONG)(tag->maintable);
tag->TC = TC_PS(0x0a)|TC_IS(tag->wrapup)|
TC_TIA(0x0f-tag->wrapup)|TC_TIB(0x03)|TC_TIC(0x04)|TC_TID(0);
}
/* ====================================================================== */
/* This function frees all MMU tables. */
void FreeMMUTable(tag)
struct systag *tag;
{
ULONG i,j, *subtab;
for (i = 0; i < 128; ++i)
if ((tag->maintable[i] & PD_DT_TYPE) == PD_DT_V4BYTE) {
for (subtab = (ULONG *)PD_ADDR(tag->maintable[i]), j = 0; j < 8; ++j)
if ((subtab[j] & PD_DT_TYPE) == PD_DT_V4BYTE)
FreeMem((char *)PD_ADDR(subtab[j]),STKTABSIZE);
FreeMem((char *)subtab,SUBTABSIZE);
}
FreeMem((char *)tag->maintable,tag->tablesize);
}
/* ====================================================================== */
/* This function makes subtables for CardROMFile I/O devices. */
void MakeExpTable(tag)
struct systag *tag;
{
ULONG i, *SUBTable, iospace;
struct ExpROMData *er;
while (er = GetExpROM()) {
er->next = tag->devs;
tag->devs = er;
iospace = ((ULONG)er->ROMbase)/ROMROUND;
/* If necessary, modify the table */
if (tag->maintable[iospace] == PD_ADDR(iospace<<17)|PD_DT_PAGE) {
if (SUBTable = AllocAligned(SUBTABSIZE,TABROUND)) {
for (i = 0; i < 8; ++i)
SUBTable[i] = PD_ADDR((iospace<<17)+(i<<14))|PD_CI|PD_DT_PAGE;
tag->maintable[iospace] = PD_ADDR(SUBTable)|PD_DT_V4BYTE;
}
} else
SUBTable = (ULONG *)PD_ADDR(tag->maintable[iospace]);
if (SUBTable) {
er->imagebase = (ULONG)AllocAligned(er->ROMsize,DEVROUND);
er->tablebase = (ULONG)&SUBTable[0];
MemCopy(er->ROMbase,er->imagebase,er->ROMsize);
iospace = (er->ROMbase - (iospace * ROMROUND))/DEVROUND;
for (i = 0; i < er->ROMsize/DEVROUND; ++i)
SUBTable[iospace+i] = PD_ADDR(er->imagebase+(DEVROUND*i))|PD_CI|PD_DT_PAGE;
}
}
}
/* ====================================================================== */
/* This function hunts down the system stack and translates it into a
block of 32 bit memory if it's found to be located in Chip RAM. Note
that this routine must only be called when the MMU is turned on. The
current functions used to turn the MMU on make use of the supervisor
stack. This code must be run in user mode to insure that the supervisor
stack image and the actual stack are the same during the transfer of
control. */
void MakeFastStack(tag)
struct systag *tag;
{
struct ExecBase *eb = *((struct ExecBase **)4L);
ULONG i, *SUBTable, *STKTable, tabndx, subndx, stkndx, tmem, base;
base = (((ULONG)eb->SysStkLower)/STKROUND)*STKROUND;
if (base >= 0x00200000L) return;
tag->sysstksize = (((ULONG)eb->SysStkUpper - (ULONG)eb->SysStkLower + 1)/STKROUND)*STKROUND;
tabndx = base/ROMROUND;
tmem = tabndx * ROMROUND;
/* Make the I/O level subtable (level 2). Most entries are going to be
a straight translation. */
if (!(SUBTable = AllocAligned(SUBTABSIZE,TABROUND)) ||
!(STKTable = AllocAligned(STKTABSIZE,TABROUND))) return;
for (i = 0; i < 8; ++i)
SUBTable[i] = PD_ADDR(tmem+(i*DEVROUND))|PD_DT_PAGE;
tag->maintable[tabndx] = PD_ADDR(SUBTable)|PD_DT_V4BYTE;
/* Make the Stack level subtable (level 3). Fill all 16 entries with a
straight translation. */
subndx = (base - tmem)/DEVROUND;
tmem += subndx * DEVROUND;
for (i = 0; i < 16; ++i)
STKTable[i] = PD_ADDR((tmem)+(i*STKROUND))|PD_DT_PAGE;
SUBTable[subndx] = PD_ADDR(STKTable)|PD_DT_V4BYTE;
/* Now take care of the actual stack translation. */
tag->sysstack = (char *)AllocAligned(tag->sysstksize,STKROUND);
MemCopy(base,tag->sysstack,tag->sysstksize);
stkndx = (base - tmem)/STKROUND;
for (i = 0; i < tag->sysstksize/STKROUND && i < 16; ++i)
STKTable[i+stkndx] = PD_ADDR(tag->sysstack+(STKROUND*i))|PD_DT_PAGE;
FlushATC();
}
/* This function removes the fast stack translation. Like the fast stack
creation routine, this must be called with the MMU turned on, in user
mode, so that both stack images can be identical when the switch is
made. This routine doesn't clean up the MMU tables, it just deals
with the stack image. */
void FreeFastStack(tag)
struct systag *tag;
{
struct ExecBase *eb = *((struct ExecBase **)4L);
ULONG *SUBTable, *STKTable, tabndx, subndx, tmem, base;
base = (((ULONG)eb->SysStkLower)/STKROUND)*STKROUND;
/* Find the stack's translation table. */
tabndx = base/ROMROUND;
tmem = tabndx * ROMROUND;
SUBTable = (ULONG *)PD_ADDR(tag->maintable[tabndx]);
subndx = (base - tmem)/DEVROUND;
/* Set things back the way they were. */
Disable();
STKTable = (ULONG *)PD_ADDR(SUBTable[subndx]);
MemCopy(tag->sysstack,base,tag->sysstksize);
SUBTable[subndx] = PD_ADDR(tmem+(subndx*DEVROUND))|PD_DT_PAGE;
FlushATC();
Enable();
/* Get rid of the fast image stuff. */
FreeMem((char *)STKTable,STKTABSIZE);
FreeMem((char *)tag->sysstack,tag->sysstksize);
}
/* ====================================================================== */
/* This routine knows the best way to reset the system, in an attempt to
avoid MMU-based troubles. */
void CleverReset()
{
geta4();
CleanBoot();
}