home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 2: PC / frozenfish_august_1995.bin / bbs / d04xx / d0400.lha / SetCPU / mmu.c < prev    next >
C/C++ Source or Header  |  1990-11-03  |  9KB  |  277 lines

  1. /*
  2.     SetCPU V1.60
  3.     by Dave Haynie, April 13, 1990
  4.     Released to the Public Domain
  5.  
  6.     MMU.C MODULE
  7.  
  8.     This module is responsible for some of the MMU table creation
  9.         functions.
  10. */
  11.  
  12. #include "setcpu.h"
  13.  
  14.  
  15. /* ====================================================================== */
  16.  
  17. /* This function maps the phantom area for a given memory location. */
  18.  
  19. void Phantom(tag,loc)
  20. struct systag *tag;
  21. ULONG loc;
  22. {
  23.    ULONG xindex = loc/ROMROUND;
  24.  
  25.    if (xindex < 60)
  26.       tag->maintable[xindex] = PD_ADDR(0x00800000)|PD_DT_PAGE;
  27.    else
  28.       tag->maintable[xindex] = PD_ADDR(0x00ce0000)|PD_DT_PAGE;
  29. }
  30.  
  31.  
  32. /* This table contains a list of the blocks of memory that should be 
  33.    cache-inhibited. */
  34.  
  35. static ULONG InTable[] = { 0x00000000,0x00200000,0x00b00000,0x00f00000,0L,0L };
  36.    
  37.  
  38. /* This function fills the basic MMU table and other standard tag itemd from 
  39.    an allocated image.  Some tables may need additional information in the 
  40.    table.  The basic table consists of one table level and uses direct page 
  41.    translation on a grain of 128K per entry.  Everything's directly mapped 
  42.    except for the last two entries, which are for the $FC0000-$FFFFFF area. */
  43.  
  44. void FillBasicTable(tag,phantoms)
  45. struct systag *tag;
  46. LONG phantoms;
  47. {
  48.    register ULONG i, image, j;
  49.    ULONG page,size,loc;
  50.     
  51.    tag->tagsize = SizeOf(struct systag);
  52.    tag->progver = PROGRAM_VERSION;
  53.    tag->patches = 0;
  54.    tag->patchlist = tag->devs = NULL;
  55.    tag->config = 1;
  56.    tag->BerrSize = 0L;
  57.    tag->OldBerr = tag->BerrHandler = NULL;
  58.    tag->sysstack = NULL;
  59.    tag->sysstksize = 0;
  60.    tag->OldReset = tag->ResetCode = NULL;
  61.    tag->ResetSize = 0;
  62.  
  63.   /* Here I make a table that maps everything straight through. */
  64.    for (i = 0; i < tag->tablesize/sizeof(ULONG); i++) 
  65.       tag->maintable[i] = PD_ADDR(i<<17)|PD_DT_PAGE;
  66.    tag->maintable[i] = IV_ADDR(tag)|PD_DT_INVALID;
  67.  
  68.   /* Mark the inhibited pages. */
  69.    for (i = 0; InTable[i+1]; i += 2)
  70.       for (j = InTable[i]/PAGESIZE; j < InTable[i+1]/PAGESIZE; ++j)
  71.          tag->maintable[j] |= PD_CI;
  72.  
  73.   /* Here I map the ROM image to the ROM location. */
  74.    image = (ULONG)tag->romlo;
  75.    loc = tag->romloc/PAGESIZE;
  76.    if (image) {
  77.       if (phantoms) Phantom(tag,image);
  78.       tag->maintable[loc++] = PD_ADDR(image)|PD_WP|PD_DT_PAGE;
  79.       if (phantoms) Phantom(tag,image+PAGESIZE);
  80.       tag->maintable[loc++] = PD_ADDR(image+PAGESIZE)|PD_WP|PD_DT_PAGE;
  81.    }
  82.    image = (ULONG)tag->romhi;
  83.    if (phantoms) Phantom(tag,image);
  84.    tag->maintable[loc++] = PD_ADDR(image)|PD_WP|PD_DT_PAGE;
  85.    if (phantoms) Phantom(tag,image+PAGESIZE);
  86.    tag->maintable[loc]   = PD_ADDR(image+PAGESIZE)|PD_WP|PD_DT_PAGE;
  87.  
  88.   /* Here I look for Bridge Cards, which are known to have problems with
  89.      the data cache enabled, so I always disable it, reguardless of 
  90.      whether caching is actually enabled in the CACR. */
  91.  
  92.    if (Bridge.Addr && Bridge.Size) {
  93.       page = Bridge.Addr/PAGESIZE;
  94.       size = max((ULONG)Bridge.Size/PAGESIZE,1);
  95.       while (size-- && page < tag->tablesize)
  96.          if ((tag->maintable[page] & PD_DT_TYPE) == PD_DT_PAGE)
  97.             tag->maintable[page++] |= PD_CI;
  98.    }     
  99. }
  100.  
  101. /* This routine sets up the MMU registers (shadowed in tag fields) in the
  102.    standard SetCPU fashion.  The CPU Root Pointer tells the MMU about the 
  103.    table I've set up, and all that's left to do is bang the Translation
  104.    Control Register to turn the thing on.  Note that the first half of the 
  105.    CRP is control data, the second the address of my table.  */
  106.    
  107. void SetMMURegs(tag)
  108. struct systag *tag;
  109. {
  110.    tag->CRP[0] = CRP_LIMIT(tag->tablesize/sizeof(ULONG)-1)|CRP_SG|CRP_DT_V4BYTE;
  111.    tag->CRP[1] = (ULONG)(tag->maintable);
  112.  
  113.    tag->TC = TC_PS(0x0a)|TC_IS(tag->wrapup)|
  114.              TC_TIA(0x0f-tag->wrapup)|TC_TIB(0x03)|TC_TIC(0x04)|TC_TID(0);
  115. }
  116.  
  117. /* ====================================================================== */
  118.  
  119. /* This function frees all MMU tables. */
  120.  
  121. void FreeMMUTable(tag)
  122. struct systag *tag;
  123. {
  124.    ULONG i,j, *subtab;
  125.  
  126.    for (i = 0; i < 128; ++i)
  127.       if ((tag->maintable[i] & PD_DT_TYPE) == PD_DT_V4BYTE) {
  128.          for (subtab = (ULONG *)PD_ADDR(tag->maintable[i]), j = 0; j < 8; ++j)
  129.             if ((subtab[j] & PD_DT_TYPE) == PD_DT_V4BYTE)
  130.                FreeMem((char *)PD_ADDR(subtab[j]),STKTABSIZE);
  131.          FreeMem((char *)subtab,SUBTABSIZE);
  132.       }
  133.    FreeMem((char *)tag->maintable,tag->tablesize);
  134. }
  135.  
  136. /* ====================================================================== */
  137.  
  138. /* This function makes subtables for CardROMFile I/O devices. */
  139.  
  140. void MakeExpTable(tag)
  141. struct systag *tag;
  142. {
  143.    ULONG i, *SUBTable, iospace;
  144.    struct ExpROMData *er;
  145.  
  146.    while (er = GetExpROM()) {
  147.       er->next = tag->devs;
  148.       tag->devs = er;
  149.  
  150.       iospace = ((ULONG)er->ROMbase)/ROMROUND;
  151.  
  152.      /* If necessary, modify the table */
  153.       if (tag->maintable[iospace] == PD_ADDR(iospace<<17)|PD_DT_PAGE) {
  154.          if (SUBTable = AllocAligned(SUBTABSIZE,TABROUND)) {
  155.             for (i = 0; i < 8; ++i) 
  156.                SUBTable[i] = PD_ADDR((iospace<<17)+(i<<14))|PD_CI|PD_DT_PAGE;
  157.             tag->maintable[iospace] = PD_ADDR(SUBTable)|PD_DT_V4BYTE;
  158.          }
  159.       } else
  160.          SUBTable = (ULONG *)PD_ADDR(tag->maintable[iospace]);
  161.  
  162.       if (SUBTable) {
  163.          er->imagebase = (ULONG)AllocAligned(er->ROMsize,DEVROUND);
  164.          er->tablebase = (ULONG)&SUBTable[0];
  165.  
  166.          MemCopy(er->ROMbase,er->imagebase,er->ROMsize);
  167.          iospace = (er->ROMbase - (iospace * ROMROUND))/DEVROUND;
  168.          for (i = 0; i < er->ROMsize/DEVROUND; ++i)
  169.             SUBTable[iospace+i] = PD_ADDR(er->imagebase+(DEVROUND*i))|PD_CI|PD_DT_PAGE;
  170.       }
  171.    }
  172. }
  173.  
  174. /* ====================================================================== */
  175.  
  176. /* This function hunts down the system stack and translates it into a 
  177.    block of 32 bit memory if it's found to be located in Chip RAM. Note
  178.    that this routine must only be called when the MMU is turned on.  The
  179.    current functions used to turn the MMU on make use of the supervisor
  180.    stack.  This code must be run in user mode to insure that the supervisor
  181.    stack image and the actual stack are the same during the transfer of
  182.    control. */
  183.  
  184. void MakeFastStack(tag)
  185. struct systag *tag;
  186. {
  187.    struct ExecBase *eb = *((struct ExecBase **)4L);
  188.    ULONG i, *SUBTable, *STKTable, tabndx, subndx, stkndx, tmem, base;
  189.  
  190.    base = (((ULONG)eb->SysStkLower)/STKROUND)*STKROUND;
  191.  
  192.    if (base >= 0x00200000L) return;
  193.  
  194.    tag->sysstksize = (((ULONG)eb->SysStkUpper - (ULONG)eb->SysStkLower + 1)/STKROUND)*STKROUND;
  195.    tabndx = base/ROMROUND;
  196.    tmem = tabndx * ROMROUND;
  197.  
  198.   /* Make the I/O level subtable (level 2).  Most entries are going to be
  199.      a straight translation. */
  200.  
  201.    if (!(SUBTable = AllocAligned(SUBTABSIZE,TABROUND)) ||
  202.        !(STKTable = AllocAligned(STKTABSIZE,TABROUND))) return;
  203.  
  204.    for (i = 0; i < 8; ++i) 
  205.       SUBTable[i] = PD_ADDR(tmem+(i*DEVROUND))|PD_DT_PAGE;
  206.    tag->maintable[tabndx] = PD_ADDR(SUBTable)|PD_DT_V4BYTE;
  207.  
  208.   /* Make the Stack level subtable (level 3).  Fill all 16 entries with a
  209.      straight translation. */
  210.    
  211.    subndx = (base - tmem)/DEVROUND;
  212.    tmem += subndx * DEVROUND;
  213.  
  214.    for (i = 0; i < 16; ++i)
  215.       STKTable[i] = PD_ADDR((tmem)+(i*STKROUND))|PD_DT_PAGE;
  216.    SUBTable[subndx] = PD_ADDR(STKTable)|PD_DT_V4BYTE;
  217.  
  218.   /* Now take care of the actual stack translation. */
  219.  
  220.    tag->sysstack = (char *)AllocAligned(tag->sysstksize,STKROUND);
  221.    MemCopy(base,tag->sysstack,tag->sysstksize);
  222.  
  223.    stkndx = (base - tmem)/STKROUND;
  224.    
  225.    for (i = 0; i < tag->sysstksize/STKROUND && i < 16; ++i)
  226.       STKTable[i+stkndx] = PD_ADDR(tag->sysstack+(STKROUND*i))|PD_DT_PAGE;
  227.    FlushATC();
  228. }
  229.  
  230. /* This function removes the fast stack translation. Like the fast stack
  231.    creation routine, this must be called with the MMU turned on, in user
  232.    mode, so that both stack images can be identical when the switch is
  233.    made.  This routine doesn't clean up the MMU tables, it just deals
  234.    with the stack image. */
  235.  
  236. void FreeFastStack(tag)
  237. struct systag *tag;
  238. {
  239.    struct ExecBase *eb = *((struct ExecBase **)4L);
  240.    ULONG *SUBTable, *STKTable, tabndx, subndx, tmem, base;
  241.  
  242.    base = (((ULONG)eb->SysStkLower)/STKROUND)*STKROUND;
  243.  
  244.   /* Find the stack's translation table. */
  245.  
  246.    tabndx = base/ROMROUND;
  247.    tmem = tabndx * ROMROUND;
  248.    SUBTable = (ULONG *)PD_ADDR(tag->maintable[tabndx]);
  249.  
  250.    subndx = (base - tmem)/DEVROUND;
  251.  
  252.   /* Set things back the way they were. */
  253.  
  254.    Disable();
  255.    STKTable = (ULONG *)PD_ADDR(SUBTable[subndx]);
  256.    MemCopy(tag->sysstack,base,tag->sysstksize);
  257.    SUBTable[subndx] = PD_ADDR(tmem+(subndx*DEVROUND))|PD_DT_PAGE;
  258.    FlushATC();
  259.    Enable();
  260.  
  261.   /* Get rid of the fast image stuff. */
  262.  
  263.    FreeMem((char *)STKTable,STKTABSIZE);
  264.    FreeMem((char *)tag->sysstack,tag->sysstksize);
  265. }
  266.  
  267. /* ====================================================================== */
  268.  
  269. /* This routine knows the best way to reset the system, in an attempt to
  270.    avoid MMU-based troubles. */
  271.  
  272. void CleverReset()
  273. {
  274.    geta4();
  275.    CleanBoot();
  276. }
  277.