home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 100-199 / ff187.lzh / SetCPU / SetCPU.c < prev    next >
C/C++ Source or Header  |  1989-02-26  |  13KB  |  420 lines

  1. /*
  2.     SetCPU V1.4
  3.     by Dave Haynie (released to the public domain)
  4.  
  5.     MAIN PROGRAM
  6.  
  7.     V1.4
  8.     I now add several commands in the assembly stub for manipulating
  9.     a few of the MMU registers.  SetCPU now uses this to permit a
  10.     simple relocation of the ROM Kernel into 32 bit memory, which is
  11.     then translated back to the normal $00FC0000 base of the ROM
  12.     Kernel.  This will increase system performance noticably.
  13.  
  14.     V1.3
  15.     I now check for the existence of an MMU, and allow for testing of 
  16.     different CPUs, for use in CLI scripts and that kind of thing.
  17.     Apparently some 68020 boards out there don't fully decode CPU space
  18.     addresses, and, as a result, their math chip shows up in all 8
  19.     coprocessor slots.  This makes the MMU test hang, since instead of
  20.     getting no MMU, I get instead an FPU responding to an MMU 
  21.     instruction, which will probably hang the system.  The "NOMMUTEST"
  22.     option allows for the rest of this program to work on such a 
  23.     board.
  24.     
  25.     V1.2
  26.     The program now defaults to "WALLOC" mode for '030 data cache, since
  27.     that's the proper mode for Amiga data caches (user and supervisor
  28.     modes share data).
  29.     
  30.     V1.1
  31.     This program tells which Motorola CPU is in place, and allows the
  32.     some cache control on 68020 and 68030 machines.  It also sets up
  33.     the ExecBase->AttnFlags with 68030 information, so that any
  34.     subsequent program can use the standard methods to identify if the
  35.     system is a 68030 system.
  36.     
  37. */
  38.  
  39. #define PROGRAM_VERSION    "V1.4"
  40.  
  41. #include <exec/types.h>
  42. #include <exec/execbase.h>
  43. #include <exec/nodes.h>
  44. #include <exec/interrupts.h>
  45. #include <functions.h>
  46. #include <stdio.h>
  47.  
  48. /* ====================================================================== */
  49.  
  50. /* Define all bit components used for manipulation of the Cache Control
  51.    Register. */
  52.  
  53. #define CACR_INST    (1L<<0)
  54. #define CACR_DATA    (1L<<8)
  55.  
  56. #define CACR_WALLOC    5
  57. #define CACR_BURST    4
  58. #define CACR_CLEAR    3
  59. #define CACR_ENTRY    2
  60. #define CACR_FREEZE    1
  61. #define CACR_ENABLE    0
  62.  
  63. /* ====================================================================== */
  64.  
  65. /* Define important bits used in various MMU registers. */
  66.  
  67. /* Here are the CRP definitions.  The CRP register is 64 bits long, but
  68.    only the first 32 bits are control bits, the next 32 bits provide the
  69.    base address of the table. */
  70.  
  71. #define    CRP_UPPER    (1L<<31)        /* Upper/lower limit mode */
  72. #define CRP_LIMIT(x)    ((ULONG)((x)&0x7fff)<<16)/* Upper/lower limit value */
  73. #define CRP_SG        (1L<<9)            /* Indicates shared space */
  74. #define CRP_DT_INVALID    0x00            /* Invalid root descriptor */
  75. #define    CRP_DT_PAGE    0x01            /* Fixed offset, auto-genned */
  76. #define CRP_DT_V4BYTE    0x02            /* Short root descriptor */
  77. #define    CRP_DT_V8BYTE    0x03            /* Long root descriptor */
  78.  
  79. /* Here are the TC definitions.  The TC register is 32 bits long. */
  80.  
  81. #define    TC_ENB        (1L<<31)        /* Enable the MMU */
  82. #define    TC_SRE        (1L<<25)        /* For separate Supervisor */
  83. #define    TC_FCL        (1L<<24)        /* Use function codes? */
  84. #define    TC_PS(x)    ((ULONG)((x)&0x0f)<<20)    /* Page size */
  85. #define TC_IS(x)    ((ULONG)((x)&0x0f)<<16)    /* Logical shift */
  86. #define    TC_TIA(x)    ((ULONG)((x)&0x0f)<<12)    /* Table indices */
  87. #define    TC_TIB(x)    ((ULONG)((x)&0x0f)<<8)
  88. #define TC_TIC(x)    ((ULONG)((x)&0x0f)<<4)
  89. #define    TC_TID(x)    ((ULONG)((x)&0x0f)<<0)
  90.  
  91. /* Here are the page descriptor definitions, for short desctriptors only,
  92.    since that's all I'm using at this point. */
  93.    
  94. #define    PD_ADDR(x)    ((ULONG)(x)&~0x0f)    /* Translated Address */
  95. #define    PD_WP        (1L<<2)            /* Write protect it! */
  96. #define PD_DT_INVALID    0x00            /* Invalid root descriptor */
  97. #define    PD_DT_PAGE    0x01            /* Fixed offset, auto-genned */
  98. #define PD_DT_V4BYTE    0x02            /* Short root descriptor */
  99. #define    PD_DT_V8BYTE    0x03            /* Long root descriptor */
  100.  
  101. /* ====================================================================== */
  102.  
  103. /* Some external declarations. */
  104.  
  105. void SetCACR(), GetCRP(), SetCRP(), SetTC();
  106. ULONG GetCACR(), GetTC(), GetCPUType(), GetMMUType(), GetFPUType();
  107.  
  108. /* Checking logic */
  109.  
  110. #define    CK68000    0
  111. #define CK68010    1
  112. #define CK68020    2
  113. #define CK68030    3
  114. #define CK68851    4
  115. #define CK68881    5
  116. #define CK68882    6
  117. #define CKFPU    7
  118. #define CKMMU    8
  119. #define CHECKS    9
  120.  
  121. #define    WARNING    5
  122.  
  123. struct checker { char *item; BOOL tag; };
  124.  
  125. struct checker checks[CHECKS] = {
  126.    { "68000", FALSE },
  127.    { "68010", FALSE },
  128.    { "68020", FALSE },
  129.    { "68030", FALSE },
  130.    { "68851", FALSE },
  131.    { "68881", FALSE },
  132.    { "68882", FALSE },
  133.    { "FPU",   FALSE },
  134.    { "MMU",   FALSE }
  135. };
  136.  
  137. USHORT code = 0L;    /* Program return code */
  138.  
  139. /* ====================================================================== */
  140.  
  141. /* This replaces the Lattice "stricmp()" function, plus it's a better form
  142.    for my needs here. */
  143.    
  144. static BOOL striequ(s1,s2)
  145. char *s1,*s2;
  146. {
  147.    BOOL aok;
  148.    
  149.    while (*s1 && *s2 && (aok = (*s1++ & 0xdf) == (*s2++ & 0xdf)));
  150.    return (BOOL) (!*s1 && aok);
  151. }
  152.  
  153. /* This routine prints FPU codes and sets things accordingly. */
  154.  
  155. static void PrintFPU(fpu)
  156. ULONG fpu;
  157. {
  158.    if (fpu == 68881L) {
  159.       printf("68881 ");
  160.       if (checks[CK68881].tag) code = 0;
  161.    } else if (fpu == 68882L) {
  162.       printf("68882 ");
  163.       if (checks[CK68882].tag) code = 0;
  164.    }
  165.    if (fpu && checks[CKFPU].tag) code = 0;
  166. }
  167.  
  168. /* ====================================================================== */
  169.  
  170. /* Here's the MMU support stuff. */
  171.  
  172. #define ROUND        0x00001000L
  173. #define ROMBASE        0x00FC0000L
  174. #define ROMSIZE        0x00040000L
  175. #define TABSIZE        (128L * sizeof(ULONG))
  176.  
  177. /* Page tables and other MMU stuff must be on a page sized boundary, and
  178.    that boundary must be a power of two.  This routine allocates such an
  179.    aligned block of memory. */
  180.  
  181. static void *AllocAligned(size,bound)
  182. ULONG size;
  183. ULONG bound;
  184. {
  185.    void *mem, *aligned;
  186.    
  187.    if (!(mem = AllocMem(size+bound,0L))) return NULL;   
  188.    Forbid();
  189.    aligned = (void *)(((ULONG)mem + bound - 1) & ~(bound - 1));
  190.    FreeMem(mem,size+bound);
  191.    mem = AllocAbs(size,aligned);
  192.    Permit();
  193.    return mem;
  194. }
  195.  
  196. /* This routine creates the Fast ROM.  If the memory can't be allocated,
  197.    it returns FALSE, otherwise, TRUE.  The "wrapbits" argument probably
  198.    won't work for every case.  There's some magic here which I seem to
  199.    have working, but don't understand completely.  Basically, the TC
  200.    register must be correct, or you'll get a configuration exception,
  201.    otherwise know as GURU #38.  The big constraint is that sum of the
  202.    TIx fields from A to the first zero field, plus PS and IS, must be
  203.    equal to 32. */
  204.  
  205. static BOOL CreateFastROM(wrapbits)
  206. short wrapbits;
  207. {
  208.    ULONG i, myCRP[2], myTC, *ROM32 = NULL, *MMUTable = NULL;
  209.  
  210.   /* First off, get the memory for the 32 bit ROM and the MMU table. */
  211.  
  212.    ROM32 = AllocAligned(ROMSIZE,ROUND);
  213.    MMUTable = AllocAligned(TABSIZE,ROUND);
  214.    if (!ROM32 || !MMUTable) {
  215.       if (MMUTable) FreeMem(MMUTable,TABSIZE);
  216.       if (ROM32)    FreeMem(ROM32,ROMSIZE);
  217.       return FALSE;
  218.    }
  219.  
  220.   /* Here I set up the ROM, as quickly as possible! */
  221.  
  222.    CopyMemQuick(ROMBASE,ROM32,ROMSIZE);
  223.  
  224.   /* Now I initialize the MMU table.  This translation is really very
  225.      basic.  I set up one table level and use direct page translation
  226.      on a grain of 128K per entry.  Everything's directly mapped except
  227.      for the last two entries, which is for the $FC0000-$FFFFFF area.
  228.      This I translate to my fastram ROM, and write protect it too. */
  229.  
  230.    for (i = 0; i < 126; i++) MMUTable[i] = PD_ADDR(i<<17)|PD_DT_PAGE;
  231.    MMUTable[126] = PD_ADDR(ROM32)|PD_WP|PD_DT_PAGE;
  232.    MMUTable[127] = PD_ADDR(((ULONG)ROM32)+0x20000L)|PD_WP|PD_DT_PAGE;
  233.  
  234.   /* Now I have to set up the MMU.  The CPU Root Pointer tells the MMU about 
  235.      the table I've set up, and the Translation Control register will turn 
  236.      the thing on.  Note that the first half of the CRP is control data, the
  237.      second the address of my table. */
  238.  
  239.    myCRP[0] = CRP_LIMIT(0x007f)|CRP_SG|CRP_DT_V4BYTE;
  240.    myCRP[1] = (ULONG)MMUTable;
  241.    SetCRP(myCRP);
  242.  
  243.    myTC = TC_ENB|TC_PS(0x0c)|TC_IS(wrapbits)|
  244.           TC_TIA(0x0f-wrapbits)|TC_TIB(0x05)|TC_TIC(0)|TC_TID(0);
  245.    SetTC(myTC);
  246.    return TRUE;
  247. }
  248.  
  249. /* This routine remover the Fast ROM, and re-claims the memory previously
  250.    allocated.  We've already checked to make sure that the MMU was 
  251.    switched on. */
  252.  
  253. static void DeleteFastROM() {
  254.    ULONG myCRP[2], *ROM32 = NULL, *MMUTable = NULL;
  255.  
  256.   /* First off, turn of the MMU.  This lets us muck with the table and
  257.      reclaim memory without any trouble. */
  258.  
  259.    SetTC(0L);
  260.  
  261.   /* Now get the root pointer, which will tell where the memory has been
  262.      allocated. */
  263.  
  264.    GetCRP(myCRP);
  265.    MMUTable = (ULONG *)myCRP[1];
  266.    ROM32 = (ULONG *)PD_ADDR(MMUTable[126]);
  267.  
  268.   /* Now I just free up the memory, and I'm done! */
  269.   
  270.    FreeMem(MMUTable,TABSIZE);
  271.    FreeMem(ROM32,ROMSIZE);
  272. }
  273.  
  274. /* ====================================================================== */
  275.  
  276. /* Codes for the FASTROM action. */
  277.  
  278. #define    FR_NO_ACTION    0
  279. #define    FR_CREATE    1
  280. #define    FR_DELETE    2
  281.  
  282. /* This be the main program. */
  283.  
  284. int main(argc,argv)
  285. int argc;
  286. char *argv[];
  287. {
  288.    BOOL worked, dommutest = TRUE, fastrom = FR_NO_ACTION;
  289.    ULONG cacr,op,mode,test,cpu,fpu,mmu = 0;
  290.    USHORT i,j;
  291.    short wrapbits = 8;
  292.  
  293.    /* If they're just asking for help */
  294.  
  295.    if (argc >= 2 && argv[1][0] == '?') {
  296.       printf("\2337mSetCPU %s by Dave Haynie\2330m\n",PROGRAM_VERSION);
  297.       printf("Usage: SetCPU [INST|DATA] [[NO]CACHE|[NO]BURST]\n");
  298.       printf("              [[NO]FASTROM [TRAP]] [NOMMUTEST]\n");
  299.       printf("              [CHECK 680x0|68851|6888x|MMU|FPU]\n");
  300.       exit(0);
  301.    }
  302.  
  303.   /* Now we parse the command line.  The default cache operation acts on 
  304.      both data and instruction caches.  The way all the cache control
  305.      functions are defined, they're just NOPs on machines without the
  306.      appropriate caches. */
  307.    
  308.    mode = CACR_INST | CACR_DATA;
  309.    cacr = GetCACR();
  310.  
  311.    if (argc > 1) {
  312.       for (i = 1; i < argc; ++i) {
  313.          if (code == WARNING) for (j = 0; j < CHECKS; ++j)
  314.             if (striequ(checks[j].item,argv[i])) {
  315.                checks[j].tag = TRUE;
  316.                break;
  317.             }
  318.          if (striequ(argv[i],"CHECK"))        code = WARNING;
  319.          else if (striequ(argv[i],"FASTROM"))    fastrom = FR_CREATE;
  320.          else if (striequ(argv[i],"NOFASTROM"))    fastrom = FR_DELETE;
  321.          else if (striequ(argv[i],"TRAP"))    wrapbits = 0;
  322.          else if (striequ(argv[i],"NOMMUTEST"))    dommutest = FALSE;
  323.          else if (striequ(argv[i],"DATA"))    mode = CACR_DATA;
  324.          else if (striequ(argv[i],"INST"))    mode = CACR_INST;
  325.          else if (striequ(argv[i],"CACHE"))    cacr |=   mode << CACR_ENABLE;
  326.          else if (striequ(argv[i],"NOCACHE"))    cacr &= ~(mode << CACR_ENABLE);
  327.          else if (striequ(argv[i],"BURST"))    cacr |=   mode << CACR_BURST;
  328.          else if (striequ(argv[i],"NOBURST"))    cacr &= ~(mode << CACR_BURST);
  329.       }
  330.  
  331.      /* We ALWAYs want to be in Word Allocate mode, AmigaOS won't run 
  332.         otherwise. */
  333.  
  334.       SetCACR(cacr | CACR_DATA << CACR_WALLOC);
  335.    }
  336.  
  337.   /* Let's find out what we have, and perform the ROM translation, if it's
  338.      requested and hasn't been done already. */
  339.  
  340.    cpu = GetCPUType();
  341.    fpu = GetFPUType();
  342.    if (dommutest && (mmu = GetMMUType())) {
  343.       if (!(GetTC() & TC_ENB)) {
  344.          if (fastrom == FR_CREATE && !CreateFastROM(wrapbits)) {
  345.             printf("Error: Can't get memory for FASTROM translation\n");
  346.             exit(10);
  347.          }
  348.       } else if (fastrom == FR_DELETE)
  349.          DeleteFastROM();
  350.    }
  351.  
  352.    printf("SYSTEM: ");
  353.  
  354.    /* If they're not on a 68020/68030, we can't set anything.  For 
  355.       compatibility across systems, I don't consider a cache setting 
  356.       request an error, just ignore it. */
  357.  
  358.    if (cpu <= 68010L) {
  359.       if (cpu == 68010L) {
  360.          printf("68010 ");
  361.          if (checks[CK68010].tag) code = 0;
  362.       } else {
  363.          printf("68000 ");
  364.          if (checks[CK68000].tag) code = 0;
  365.       }
  366.       PrintFPU(fpu);
  367.       printf("\n");
  368.       exit(code);
  369.    }
  370.  
  371.    /* Now we're on a 32 bit system.  But EXEC doesn't know which.  If you
  372.       run SetCPU on a 68030 system once, the '030 flag's set, otherwise, 
  373.       we'll test for it. */
  374.  
  375.    if (cpu == 68030L) {
  376.       printf("68030 ");
  377.       if (checks[CK68030].tag) code = 0;
  378.    } else {
  379.       printf("68020 ");
  380.       if (checks[CK68020].tag) code = 0;
  381.    }
  382.  
  383.    PrintFPU(fpu);
  384.  
  385.    if (mmu == 68851L) {
  386.       printf("68851 ");
  387.       if (checks[CK68851].tag) code = 0;
  388.    }
  389.    if (mmu && checks[CKMMU].tag) code = 0;
  390.    if (mmu && (GetTC() & TC_ENB)) printf("FASTROM ");
  391.  
  392.    /* We always print the results, even if nothing has changed. */
  393.    
  394.    cacr = GetCACR();
  395.    printf("(INST: ");
  396.    if (!(cacr & (CACR_INST << CACR_ENABLE))) printf("NO");
  397.    printf("CACHE");
  398.  
  399.    if (cpu == 68030L) {
  400.       printf(" ");
  401.       if (!(cacr & (CACR_INST << CACR_BURST))) printf("NO");
  402.       printf("BURST) (DATA: ");
  403.       if (!(cacr & (CACR_DATA << CACR_ENABLE))) 
  404.          printf("NOCACHE ");
  405.       else
  406.          printf("CACHE ");
  407.  
  408.       if (!(cacr & (CACR_DATA << CACR_BURST))) printf("NO");
  409.       printf("BURST");
  410.    }
  411.    printf(")\n");
  412.  
  413.    /* For safety's sake, or personal paranoia, or whatever, I dump the
  414.       data cache before I go away. */
  415.  
  416.    if (cpu = 68030L) SetCACR(cacr|(CACR_DATA << CACR_CLEAR));
  417.    exit(code);
  418. }
  419.  
  420.