amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (08/15/90)
Submitted-by: daveh@cbmvax.commodore.com (Dave Haynie) Posting-number: Volume 90, Issue 222 Archive-name: util/setcpu-1.60/part02 #!/bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 2 (of 4)." # Contents: SetCPU.h coolhand.c memory.c mmu.c # Wrapped by tadguy@abcfd20 on Tue Aug 14 17:35:35 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'SetCPU.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'SetCPU.h'\" else echo shar: Extracting \"'SetCPU.h'\" \(10417 characters\) sed "s/^X//" >'SetCPU.h' <<'END_OF_FILE' X/* X SetCPU V1.60 X by Dave Haynie, April 13, 1990 X Released to the Public Domain X X HEADER FILE X*/ X X X#define PROGRAM_VERSION 160 X X#include <exec/types.h> X#include <exec/execbase.h> X#include <exec/nodes.h> X#include <exec/lists.h> X#include <exec/memory.h> X#include <exec/io.h> X#include <devices/trackdisk.h> X#include <libraries/expansionbase.h> X#include <libraries/configregs.h> X#include <libraries/configvars.h> X#include <graphics/gfxbase.h> X#include <graphics/gfxmacros.h> X#include <intuition/intuition.h> X#include <intuition/intuitionbase.h> X#include <libraries/dosextens.h> X#include <libraries/filehandler.h> X#include <functions.h> X#include <stdio.h> X#include <ctype.h> X X/* ====================================================================== */ X X/* Define all bit components used for manipulation of the Cache Control X Register. */ X X#define CACR_INST ((ULONG)(1L<<0)) X#define CACR_DATA ((ULONG)(1L<<8)) X#define CACR_FIXED ((ULONG)(CACR_DATA<<CACR_WALLOC)) X X#define CACR_WALLOC 5 X#define CACR_BURST 4 X#define CACR_CLEAR 3 X#define CACR_ENTRY 2 X#define CACR_FREEZE 1 X#define CACR_ENABLE 0 X X#define CACR_ENABLE40 15 X#define CACR_DATA40 16 X X/* ====================================================================== */ X X/* Define important bits used in various MMU registers. */ X X/* Here are the CRP definitions. The CRP register is 64 bits long, but X only the first 32 bits are control bits, the next 32 bits provide the X base address of the table. */ X X#define CRP_UPPER (1L<<31) /* Upper/lower limit mode */ X#define CRP_LIMIT(x) ((ULONG)((x)&0x7fff)<<16)/* Upper/lower limit value */ X#define CRP_SG (1L<<9) /* Indicates shared space */ X#define CRP_DT_INVALID 0x00 /* Invalid root descriptor */ X#define CRP_DT_PAGE 0x01 /* Fixed offset, auto-genned */ X#define CRP_DT_V4BYTE 0x02 /* Short root descriptor */ X#define CRP_DT_V8BYTE 0x03 /* Long root descriptor */ X X/* Here are the TC definitions. The TC register is 32 bits long. */ X X#define TC_ENB (1L<<31) /* Enable the MMU */ X#define TC_SRE (1L<<25) /* For separate Supervisor */ X#define TC_FCL (1L<<24) /* Use function codes? */ X#define TC_PS(x) ((ULONG)((x)&0x0f)<<20) /* Page size */ X#define TC_IS(x) ((ULONG)((x)&0x0f)<<16) /* Logical shift */ X#define TC_TIA(x) ((ULONG)((x)&0x0f)<<12) /* Table indices */ X#define TC_TIB(x) ((ULONG)((x)&0x0f)<<8) X#define TC_TIC(x) ((ULONG)((x)&0x0f)<<4) X#define TC_TID(x) ((ULONG)((x)&0x0f)<<0) X X/* Here are the page descriptor definitions, for short desctriptors only, X since that's all I'm using at this point. */ X X#define PD_ADDR(x) ((ULONG)(x)&~0x0fL) /* Translated Address */ X#define IV_ADDR(x) ((ULONG)(x)&~0x03L) /* Invalid unused field */ X#define PD_WP (1L<<2) /* Write protect it! */ X#define PD_CI (1L<<6) /* Cache inhibit */ X#define PD_DT_TYPE 0x03 /* Page descriptor type */ X#define PD_DT_INVALID 0x00 /* Invalid root descriptor */ X#define PD_DT_PAGE 0x01 /* Fixed offset, auto-genned */ X#define PD_DT_V4BYTE 0x02 /* Short root descriptor */ X#define PD_DT_V8BYTE 0x03 /* Long root descriptor */ X X/* This is needed for identification of bogus systems that test positive X for MMUs. */ X X#define BOGUSMMU 0xffffffffL X X/* Here's the MMU support stuff. */ X X#define ROMROUND 0x00020000L /* ROM/Main level at 128K grain */ X#define SMALLROMSIZE 0x00040000L X#define BIGROMSIZE 0x00080000L X#define DEVROUND 0x00004000L /* Device level at 16K grain */ X#define STKROUND 0x00000400L /* Stack level at 1K grain */ X#define TABROUND 0x00000400L /* Table alignment matches page size */ X#define PAGESIZE 0x00020000L X#define MAINTABSIZE (128L * sizeof(ULONG)) X#define SUBTABSIZE (8L * sizeof(ULONG)) X#define STKTABSIZE (16L * sizeof(ULONG)) X X/* Magic ROM numbers */ X X#define MAGIC_256 0x11114ef9 X#define MAGIC_512 0x11144ef9 X X/* ====================================================================== */ X X/* Some external system declarations. */ X Xextern BPTR Lock(), Open(); X X/* Checking logic */ X X#define CK68000 0 X#define CK68010 1 X#define CK68020 2 X#define CK68030 3 X#define CK68040 4 X#define CK68851 5 X#define CK68881 6 X#define CK68882 7 X#define CKFPU 8 X#define CKMMU 9 X#define CKMMUON 10 X#define CKMMUROM 11 X#define CKMMUALIEN 12 X#define CHECKS 13 X X#define WARNING 5 X#define READOK 0L X X#define SizeOf(x) ((ULONG)sizeof(x)) X#define min(a,b) ((a<b)?a:b) X#define max(a,b) ((a>b)?a:b) X X/* ====================================================================== */ X X/* From the CONTROL.A module */ X Xextern void SetCACR(), X GetCRP(), X SetCRP(), X SetTC(); X Xextern ULONG GetCACR(), X *GetVBR(), X GetTC(); X X/* ====================================================================== */ X X/* From the IDENTS.A module */ X Xextern ULONG GetCPUType(), X GetMMUType(), X GetFPUType(); X X/* ====================================================================== */ X X/* From the OTHER.A module */ X Xextern void SetMMUTag(), X FlushATC(), X SetKeyDelay(); X Xextern ULONG KeyCode, X KeyCodeSize, X BerrCode, X BerrCodeSize; X X/* ====================================================================== */ X X/* From the REBOOT.A module. */ X Xextern void ROMBoot(), X CleanBoot(); X Xextern ULONG BootCode, X BootCodeSize, X ResetCode, X ResetCodeSize; X X X/* ====================================================================== */ X X/* From the EXPDEV.C module. */ X X/* This structure is device information used by the memory mapping routine. */ X Xstruct ExpROMData { X struct ExpROMData *next; X ULONG ROMbase; X ULONG ROMsize; X ULONG imagebase; X ULONG tablebase; X char *name; X}; X Xextern LONG ReadExpDevs(); Xextern struct ExpROMData *GetExpROM(); Xextern void FreeExpROM(), X SafeConfigDevs(); X X/* ====================================================================== */ X X/* From the MISC.C module. */ X X/* Patch types */ X X#define PT_STRING 1 X#define PT_JSR 2 X#define PT_END 3 X#define PT_IGNORE 4 X#define PT_KEYBOARD 5 X X/* This is a item */ X Xstruct pitem { X UWORD Type; /* The type of patch to apply */ X UWORD Pad; /* Nothing here yet... */ X ULONG Offset; /* The offset at which to apply the patch */ X ULONG Length; /* The length of the patch item */ X UWORD *Code; /* The actual patch item */ X}; X X/* This is the patch structure. */ X Xstruct patch { X struct patch *next; /* Next patchlist */ X struct pitem *list; /* First item in this patchlist */ X UWORD Version; /* Which ROM version */ X UWORD Revision; /* and revision */ X}; X X/* These are the some patch system variables. */ X X#define KEYPATCH 0 X Xextern struct patch SystemPatch[]; Xextern struct MemChunk *lastpatch; X X/* The actual functions. */ X Xextern LONG striequ(), X strniequ(); X Xextern void MotorOff(); Xextern BYTE ReadBuf(); Xextern LONG CheckTDDev(); X Xextern LONG AddPatch(); X X/* ====================================================================== */ X X/* From the MMU.C module. */ X Xextern void Phantom(), X SetMMURegs(), X FillBasicTable(), X FreeMMUTable(), X MakeExpTable(), X MakeFastStack(), X FreeFastStack(); X X/* ====================================================================== */ X X/* From the MEMORY.C module. */ X X/* This section describes the system tag structure, where I stick all the X information that I like to keep around. */ X X#define ROM_NOP 0x0000 /* No ROM operation called for */ X#define ROM_FAST 0x0002 /* Normally installed FASTROM image */ X#define ROM_KICK 0x0003 /* Installed as a KICK image */ X#define ROM_FKICK 0x0004 /* A KICK image made into a FAST image */ X X/* This was originally the patchtag structure, which looked like a patch. I X decided that was real kludgy. I hook the systag onto an invalid page X descriptor which I locate in the physical ROM image, a place that should X always be safe to have an invalid tag structure. Don't change this without X checking in the "030Stuff.a" file -- some of these structure members are X used by the reboot code. */ X Xstruct systag { X ULONG tagsize; /* Size of this tag */ X ULONG progver; /* The program version */ X ULONG *maintable; /* The main ROM table */ X ULONG *romhi; /* The main ROM image */ X UWORD romtype; /* Type of MMU ROM */ X UWORD patches; /* The number of other patches applied */ X struct MemChunk *patchlist; /* List of installed patches */ X struct ExpROMData *devs; /* Translated device ROMs */ X ULONG TC; /* Precomputed TC used for KICK. */ X ULONG CRP[2]; /* Precomputed CRP used for KICK. */ X UWORD config; /* Configuration status. */ X ULONG BerrSize; /* Size of bus error handler. */ X char *OldBerr; /* The old BERR routine. */ X char *BerrHandler; /* My BERR routine. */ X short wrapup; /* Upper address wrap bound. */ X short wrapdown; /* Lower address wrap bound. */ X ULONG tablesize; /* Main table size. */ X char *ResetCode; /* Actual reset routine */ X ULONG romsize; /* Size of ROM image */ X ULONG romloc; /* Where does the fool thing go? */ X ULONG romstart; /* And where do we start it up? */ X ULONG *romlo; /* Secondary ROM image, if needed */ X char *sysstack; /* Physical system stack image */ X ULONG sysstksize; /* System Stack allocated size. */ X ULONG ResetSize; /* Size of the reset code. */ X char *OldReset; /* Old Reset Code */ X}; X X/* The actual functions */ X Xextern void MemCopy(), X SetMMURegs(), X *AllocAligned(), X SnoopSpecial(), X FillBasicTable(), X FreeSAFEImage(); XULONG * SizeROM(); Xextern struct systag *AllocROMImage(), X *AllocDISKImage(), X *AllocSAFEImage(), X *GetSysTag(); Xextern LONG SmartlyGetRange(); X X/* ====================================================================== */ X X/* From the DISKIO.C module. */ X Xextern struct systag *AllocKSImage(), X *AllocFILEImage(), X *AllocDISKImage(); X X/* ====================================================================== */ X X/* From the COOLHAND.C module. */ X Xstruct Window *CoolHand(); X X/* ====================================================================== */ X X/* Intermodule globals */ X Xstruct CfgBlock { X ULONG Addr, Size; X}; X X#ifdef MAIN_MODULE Xstruct ExpansionBase *ExpansionBase = NULL; /* The expansion library */ Xunsigned short LoadErr = 16; Xstruct CfgBlock Bridge = { 0L, 0L }, A26x0 = { 0L, 0L }; X#else Xextern struct ExpansionBase *ExpansionBase; Xextern unsigned short LoadErr, forcewrap; Xextern struct CfgBlock Bridge, A26x0; Xextern BOOL allochead,aliens; Xextern ULONG cpu; X#endif X END_OF_FILE if test 10417 -ne `wc -c <'SetCPU.h'`; then echo shar: \"'SetCPU.h'\" unpacked with wrong size! fi # end of 'SetCPU.h' fi if test -f 'coolhand.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'coolhand.c'\" else echo shar: Extracting \"'coolhand.c'\" \(7518 characters\) sed "s/^X//" >'coolhand.c' <<'END_OF_FILE' X/* X SetCPU V1.60 X by Dave Haynie, April 13, 1990 X Released to the Public Domain X X COOLHAND MODULE X X This module contains the code used to display a cool looking X KickStart prompt hand on the screen. X*/ X X#include "setcpu.h" X X/* ====================================================================== */ X X/* This is the KickStart hand design as in the A1000. Only, Intuition makes X it considerably easier to build than they way the Kernel ROM does it. */ X X/* Define the vectors. The hand is a drawing composed of a series of line X vectors. Intuition provides a handy structure, called a boarder, that'll X render this whole mess with a single function call. */ X Xstatic WORD vect1[] = { 0, 0, 23, 0, 23, 22, 78, 22, 78, 0, 90, 0,101, 11, X 101, 83, 92, 83, 92, 45, 29, 45, 27, 43, 18, 43, 17, 45, X 10, 45, 10, 54, 0, 61, 0, 0 }; Xstatic WORD vect2[] = { 0, 0, 0,-62, 93,-62,105,-50,105, 23, 53, 23, 53, 28, X 49, 36, 45, 41, 41, 44, 35, 53, 27, 57, 27, 68,-23, 68, X -23, 37,-24, 37,-24, 9,-20, 3,-13, -3,-12, -7, -8,-14, X -3,-17, 0,-18, 0,-18, -3,-16, -7,-14,-11, -7,-12, -3, X -19, 3,-23, 9,-23, 36,-22, 37,-22, 67, 7, 67, 7, 46, X 15, 46, 19, 44, 19, 23, 17, 20, 17, 10, 32, -3, 32,-15, X 29,-17, 26,-17, 29,-14, 29, -7, 28, -6, 21, -6, 18, -9, X 9, -2, -3, 4,-15, 13,-15, 12, -3, 3, -7, 2,-10, -1, X -7, 1, -3, 2, 0, 0 }; Xstatic WORD vect3[] = { 0, 0, 2, -7, 10, -6, 11, -3, 11, 4, 4, 4, 0, 0 }; Xstatic WORD vect4[] = { 0, 0, 0,-10, 15,-23, 15,-35, 74,-35, 74, 2, 1, 2, X 0, -2 }; Xstatic WORD vect5[] = { 0, 0, 51, 0, 51, 21, 0, 21, 0, 0 }; Xstatic WORD vect6[] = { 0, 0, 11, 0, 11, 14, 0, 14, 0, 0 }; Xstatic WORD vect7[] = { 0, 0, 7, 0, 7, 12, 0, 12, 0, 0 }; Xstatic WORD vect8[] = { 0, 0, 3, 0, 3, 2, 0, 6, 0, 0 }; Xstatic WORD vect9[] = { 0, 0, 0,-20, 7,-20, 12,-25, 12,-34, 16,-32, 24,-32, X 24,-30, 28,-25, 32,-25, 32,-23, 26,-14, 18,-11, 18, 0, X 0, 0 }; Xstatic WORD vect10[] = { 0, 0, 0, 5, 5, 2, 0, 0 }; Xstatic WORD vect11[] = { 0, 0, -4, 2, -4, -3, 17, -3, 7, 7, 6, 7, 8, 5, X 3, 0, 0, 0 }; X Xstatic WORD vect12[] = { 0, 0, 7, 0, 7, 5, 3, 13, 0, 17, -5, 18, -8, 18, X -11, 14,-11, 11, 0, 0 }; X Xstatic WORD vect13[] = { 0, 0, 0, 3, 2, 6, 2, 6, 8, 5, 9, 2, 5, -1, X 0, 0 }; Xstatic WORD vect14[] = { 0, 0, 8, 2, 10, -1, 6, -5, 3, -5, 0, -3, 0, 0 }; Xstatic WORD vect15[] = { 0, 0, 11, 11, 11, 83 }; X Xstatic struct Border HandLines[] = { X { 105, 51,1,0,JAM1,18, &vect1[0], &HandLines[1] }, X { 103,112,1,0,JAM1,59, &vect2[0], &HandLines[2] }, X { 120,101,1,0,JAM1, 7, &vect3[0], &HandLines[3] }, X { 121,132,1,0,JAM1, 8, &vect4[0], &HandLines[4] }, X { 130, 51,1,0,JAM1, 5, &vect5[0], &HandLines[5] }, X { 166, 54,1,0,JAM1, 5, &vect6[0], &HandLines[6] }, X { 168, 55,1,0,JAM1, 5, &vect7[0], &HandLines[7] }, X { 117, 97,1,0,JAM1, 5, &vect8[0], &HandLines[8] }, X { 111,179,1,0,JAM1,15, &vect9[0], &HandLines[9] }, X { 123,135,1,0,JAM1, 4,&vect10[0],&HandLines[10] }, X { 127,138,1,0,JAM1, 9,&vect11[0],&HandLines[11] }, X { 148,135,1,0,JAM1,10,&vect12[0],&HandLines[12] }, X { 138,146,1,0,JAM1, 8,&vect13[0],&HandLines[13] }, X { 124,144,1,0,JAM1, 7,&vect14[0],&HandLines[14] }, X { 196, 51,1,0,JAM1, 3,&vect15[0],NULL }, X}; X X/* This is a list of area fills to perform; the first number is the "A" pen X to set, the next two numbers are the screen position to start filling X from. */ X Xstatic WORD FillList[][3] = { X { 2, 107,109 }, { 3, 132, 71 }, { 2, 169, 66 }, { 1, 104, 51 }, X { 1, 129, 51 }, { 1, 167, 55 }, { 1, 176, 67 }, { 1, 182, 55 }, X { 1, 196,134 }, { 1, 145,136 }, { 1, 116, 97 } X}; X X#define FILLCNT 11 X X/* Finally, I've got a few images to render, which I do using the standard X Intuition Image structures. */ X XUWORD image0[] = { /* AMIGA */ X 0x1f9f,0xfe3f,0xff77,0xfe7c, 0x070c,0xef8f,0x1e71,0xdc30, X 0x07f8,0xe7ce,0x1cf3,0x1fe0, 0x0731,0xf3ce,0x1df6,0x1cc0, X 0x0760,0x03dc,0x3ffc,0x1d80, 0x07c0,0x879c,0x3f78,0x1f00, X 0x0780,0xcf78,0x7e78,0x1e00, 0x0700,0xfeff,0xfc7c,0x1c00, X 0x1001,0x8220,0x4050,0x0004, 0x0404,0x8889,0x1210,0x5010, X 0x0408,0x2448,0x1090,0x1020, 0x0410,0x1042,0x0510,0x1040, X 0x0420,0x0050,0x2690,0x1080, 0x0440,0x0484,0x0900,0x1100, X 0x0480,0x4960,0x4208,0x1200, 0x0500,0x0683,0x8404,0x1400, X}; X XUWORD image1[] = { /* Kick */ X 0xc71f,0x1e63,0x8000, 0x6631,0x8c63,0x0000, 0x3e01,0x8c33,0x0000, X 0x6631,0x8c1f,0x0000, 0xc61f,0x0e33,0x0000, 0x0600,0x0063,0x0000, X 0x0700,0x0c63,0x8000 X}; X XUWORD image2[] = { /* Start */ X 0x703c,0xdc38,0x3e00, 0x9818,0x664c,0x6000, 0x1998,0x780c,0x3c00, X 0x19b8,0x600c,0x0600, 0x7cdc,0x3c3e,0x7c00, 0x1800,0x000c,0x0000, X 0x1000,0x0008,0x0000 X}; X Xstruct Image NameImage[] = { X { 126,122,64,8,2,&image0[0],3,0,&NameImage[1] }, X { 144,112,48,7,1,&image1[0],2,0,&NameImage[2] }, X { 140,102,48,7,1,&image2[0],2,0,NULL } X}; X X/* Here's the color scheme. */ X Xstatic WORD coolColor[] = { 0x0fff,0x0000,0x077c,0x0bbb }; X X/* ====================================================================== */ X X/* This section contains data for the mechanics of the CoolHand. */ X Xstatic struct NewScreen newScreen = { X 0,0,320,200,2,0,1,0,CUSTOMSCREEN,NULL,NULL,NULL,NULL X}; X Xstatic struct NewWindow newWindow = { X 0,0,320,200,2,0,0,BORDERLESS|ACTIVATE,NULL,NULL,NULL,NULL,NULL,0,0,0,0, X CUSTOMSCREEN X}; X Xstatic struct Screen *coolScreen; Xstatic struct Window *coolWindow, *coolShade; X Xstruct GfxBase *GfxBase; Xstruct IntuitionBase *IntuitionBase; X X/* ====================================================================== */ X X/* This is the main section. Since I consider the CoolHand prompt the end X of this life and the beginning of the next, I'm not going to worry about X freeing stuff up. */ X Xstruct Window *CoolHand() { X struct RastPort *rp; X struct ViewPort *vp; X struct Image *image; X LONG size; X UWORD i,*bits,*pointer; X BOOL ok = TRUE; X X GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L); X IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L); X if (!GfxBase || !IntuitionBase) return; X if (!(coolScreen = OpenScreen(&newScreen))) return; X ShowTitle(coolScreen,0L); X LoadRGB4(vp = &coolScreen->ViewPort,&coolColor[0],4L); X newWindow.Screen = coolScreen; X pointer = (UWORD *)AllocMem(64L,MEMF_CHIP|MEMF_CLEAR); X if (!(coolShade = OpenWindow(&newWindow))) return; X if (!(coolWindow = OpenWindow(&newWindow))) return; X WindowToFront(coolShade); X SetPointer(coolWindow,pointer,2L,2L,0L,0L); X Delay(25L); X DrawBorder(rp = coolWindow->RPort,&HandLines[0],0L,0L); X X SetOPen(rp,1L); X for (i = 0; i < FILLCNT; ++i) { X SetAPen(rp,(long)FillList[i][0]); X Flood(rp,0L,(long)FillList[i][1],(long)FillList[i][2]); X } X for (image = &NameImage[0]; image; image = image->NextImage) { X size = (LONG) (((image->Width+15)/16)*image->Height)*2*image->Depth; X movmem((char *)image->ImageData, X (char *)(bits = (UWORD *)AllocMem(size,MEMF_CHIP)), X (int)size); X image->ImageData = bits; X } X DrawImage(rp,&NameImage[0],0L,0L); X CloseWindow(coolShade); X return coolWindow; X} END_OF_FILE if test 7518 -ne `wc -c <'coolhand.c'`; then echo shar: \"'coolhand.c'\" unpacked with wrong size! fi # end of 'coolhand.c' fi if test -f 'memory.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'memory.c'\" else echo shar: Extracting \"'memory.c'\" \(11245 characters\) sed "s/^X//" >'memory.c' <<'END_OF_FILE' X/* X SetCPU V1.60 X by Dave Haynie, April 13, 1990 X Released to the Public Domain X X MEMORY.C MODULE X X This module is responsible for ROM image allocation, MMU table X allocation and creation, and other functions based on memory. X*/ X X#include "setcpu.h" X X/* ====================================================================== */ X X/* Local data types */ X Xstruct range { X ULONG first; X ULONG last; X}; X X/* ====================================================================== */ X X/* This function copies from the source to the destination, by longword, with X BYTE length "length". */ X Xvoid MemCopy(src,des,len) XULONG *src, *des; XULONG len; X{ X len = (len + 3)>>2; X while (len--) *des++ = *src++; X} X X/* ====================================================================== */ X X/* This section contains the memory allocation code. There are two X problems here. First of all, we'd like to use 32 bit FAST memory if X at all possible. Next, block translation and page tables must be on at X least a page sized boundary, if not a block boundary. */ X X/* This routine finds the memory block for me to use in AllocAligned(). X It takes into account either A2620 or A2630 systems, where I can snoop X out the memory for that particular board, knowing it's the fastest. I X can adjust for 1.4's automatic memory merging in this case too, to be X sure I have 32 bit RAM. If I don't have one of my boards, I'll return X a pointer to the first non-$C00000 memory list marked as FAST. */ X Xstatic struct range SRange = { 0L, 0L }; Xstatic ULONG MaxMem = 0; X XLONG SmartlyGetRange() { X struct ExecBase *eb = *((struct ExecBase **)4L); X register struct MemHeader *mem; X X /* First try for either A2620 or A2630 */ X X if (A26x0.Addr && A26x0.Size) { X SRange.first = A26x0.Addr; X SRange.last = A26x0.Size + SRange.first; X } X X /* For another critters, but we go here to find MaxMem, even X if we know it's an A26x0. */ X X for (mem = (struct MemHeader *)eb->MemList.lh_Head; mem->mh_Node.ln_Succ; X mem = (struct MemHeader *)mem->mh_Node.ln_Succ) { X if ((ULONG)(mem->mh_Upper) > MaxMem) MaxMem = (ULONG)mem->mh_Upper; X if (mem->mh_Attributes & MEMF_CHIP) continue; X if (((ULONG)mem >= 0xc00000 && (ULONG)mem <= 0xc80000)) continue; X if (!SRange.first) { X SRange.first = (ULONG)mem->mh_Lower; X SRange.last = (ULONG)mem->mh_Upper; X } X } X if (SRange.first) X return TRUE; X return FALSE; X} X X/* This routine allocates such an aligned block of memory from a specified X memory list. */ X Xvoid *AllocAligned(size,bound) Xregister ULONG size; Xregister ULONG bound; X{ X register ULONG target; X void *mem = NULL; X X Forbid(); X if (!allochead) { X target = (SRange.last-size) & ~(bound-1); X while (target > SRange.first && !(mem = AllocAbs(size,target))) X target -= bound; X SRange.last = (ULONG)mem; X } else { X target = (SRange.first+size+bound-1) & ~(bound-1); X while (target < SRange.last && !(mem = AllocAbs(size,target))) X target += bound; X SRange.first = (ULONG)mem+size; X } X Permit(); X return mem; X} X X/* This routine finds the memory wrap and appropriate MMU table size for X the given configuration. It requires the value of MaxMem to have been X already calculated. */ X Xvoid FindWrap(tag) Xstruct systag *tag; X{ X ULONG test; X X if (forcewrap == -1) { X tag->wrapdown = 0; X for (test = MaxMem; !(test & 0x80000000) && tag->wrapdown < 8; test <<= 1) X tag->wrapdown++; X } else X tag->wrapdown = forcewrap; X tag->tablesize = (128 << (8 - tag->wrapdown)) * sizeof(ULONG); X} X X/* This routine computes the ROM size from the magic tag values. */ X XULONG CalcROMSize(tagval) XULONG tagval; X{ X if (tagval == MAGIC_256) return SMALLROMSIZE; X if (tagval == MAGIC_512) return BIGROMSIZE; X return 0L; X} X X/* This function sizes the ROM based on its base value and correctly splits X a base address between possible ROM halves. This routine uses the Commodore X ROM file format, which is like this: X X 0: 00000000 X 4: size X 8: start of ROM X X The ROM, in any case, begins with either "$11114ef9", for 256L ROMs, or X "$11144ef9", for 512K ROMs. The next longword can be used to figure out X where the ROM actually goes, in memory. */ X XULONG *SizeROM(tag,base,getram) Xstruct systag *tag; XULONG *base, getram; X{ X ULONG *rom = NULL; X X if (!(tag->romsize = CalcROMSize(base[0]))) return NULL; X X if (getram) X if (!(rom = (ULONG *)AllocAligned(tag->romsize,ROMROUND))) return NULL; X X if (tag->romsize == SMALLROMSIZE) { X tag->romstart = base[1]; X tag->romloc = base[1] & 0xfffc0000; X tag->romlo = 0L; X tag->romhi = rom; X } else { X tag->romstart = base[1]; X tag->romloc = base[1] & 0xfff80000; X tag->romlo = rom; X tag->romhi = (ULONG *)((ULONG)rom + SMALLROMSIZE); X } X return rom; X} X X/* ====================================================================== */ X X/* This section contains routines that manage different ROM image types. */ X X/* This function gets an aligned ROM image copied from system ROM. */ X Xstruct systag *AllocROMImage(type) XUWORD type; X{ X struct systag *tag = NULL, *oldtag = NULL; X ULONG *rom = NULL, *table = NULL, *base; X X /* Let's make the allocations. I allocate the ROM first, then the table, X then the tag; since we're coming from the end of memory, this should X result in the least fragging. */ X X SmartlyGetRange(); X if (!(tag = AllocAligned(SizeOf(struct systag),8L))) goto fail; X if (oldtag = GetSysTag()) X base = (ULONG *)oldtag->romloc; X else { X if (*(base = (ULONG *)0x00f80000) != MAGIC_512) X base = (ULONG *)0x00fc0000; X } X rom = SizeROM(tag,base,TRUE); X FindWrap(tag); X if (!(table = AllocAligned(tag->tablesize+4,TABROUND))) goto fail; X tag->maintable = table; X tag->romtype = type; X MemCopy(tag->romloc,rom,tag->romsize); X FillBasicTable(tag,FALSE); X return tag; X Xfail: X if (rom) FreeMem(rom,tag->romsize); X if (table) FreeMem(table,tag->tablesize+4); X if (tag) FreeMem(tag,SizeOf(struct systag)); X return NULL; X} X X/* This function gets an aligned, reset-safe image in either $00C00000 or X CHIP memory, copies the ROM code from the passed temporary image, and X then sets up it's MMU table such that the memory used for the safe image X will be missed by the Amiga's memory-sizing logic on reboot. */ X Xstruct systag *AllocSAFEImage(temp) Xstruct systag *temp; X{ X struct ExecBase *eb = *((struct ExecBase **)4L); X struct MemHeader *safe, *safeC000 = NULL, *safeCHIP = NULL, *tmem; X struct systag *tag; X ULONG upper, base, *table; X X for (safe = (struct MemHeader *)eb->MemList.lh_Head; safe->mh_Node.ln_Succ; X safe = (struct MemHeader *)safe->mh_Node.ln_Succ) { X tmem = (struct MemHeader *)safe; X if ((ULONG)(tmem->mh_Upper) > MaxMem) MaxMem = (ULONG)tmem->mh_Upper; X if (tmem->mh_Attributes & MEMF_CHIP) { X if (!safeCHIP || safeCHIP->mh_Upper < tmem->mh_Upper) X safeCHIP = tmem; X } else if ((ULONG)safe >= 0xc00000 && (ULONG)safe <= 0xc80000) { X if (!safeC000 || safeC000->mh_Upper < tmem->mh_Upper) X safeC000 = tmem; X } X } X X /* Will it fit? You need at least 1 meg of memory. */ X X if (!safeC000 && safeCHIP->mh_Upper < 0x080000L) return NULL; X X /* Now, where should it go. */ X X if (safeC000) X upper = ((ULONG)safeC000->mh_Upper+ROMROUND-1L) & ~(ROMROUND-1L); X else if (safeCHIP) X upper = ((ULONG)safeCHIP->mh_Upper+ROMROUND-1L) & ~(ROMROUND-1L); X X FindWrap(temp); X table = (ULONG *)(base = upper-ROMROUND); X tag = (struct systag *)(base = (base + temp->tablesize + 36L) & ~7L); X *tag = *temp; X tag->maintable = table; X X if (temp->romlo) { X tag->romlo = (ULONG *)(upper - SMALLROMSIZE - ROMROUND); X if (safeC000) { X upper = ((ULONG)safeCHIP->mh_Upper+ROMROUND-1L) & ~(ROMROUND-1L); X tag->romhi = (ULONG *)(upper - SMALLROMSIZE); X } else X tag->romhi = (ULONG *)(upper - SMALLROMSIZE*2 - ROMROUND); X } else { X tag->romhi = (ULONG *)(upper - temp->romsize - ROMROUND); X tag->romlo = 0L; X } X X /* Other tag initializations. */ X X tag->romtype = ROM_KICK; X FillBasicTable(tag,TRUE); X X base = (base + SizeOf(struct systag) + 32L) & ~7L; X X tag->BerrHandler = (char *)(base = (base + SizeOf(struct systag)+32L) & ~7L); X tag->BerrSize = (BerrCodeSize + 4) & ~3L; X X if (tag->romlo) MemCopy(temp->romlo,tag->romlo,SMALLROMSIZE); X MemCopy(temp->romhi,tag->romhi,SMALLROMSIZE); X X tag->ResetCode = (char *)(base = (base + BerrCodeSize + 32L) & ~7L); X tag->ResetSize = BerrCodeSize; X MemCopy(BootCode,tag->ResetCode,BootCodeSize); X X return tag; X} X X/* This function returns memory to the system, automatically setting the X appropriate memory flags. */ X Xvoid ReturnMem(size,mem) XULONG size; XULONG mem; X{ X if (mem < 0x00200000) X AddMemList(size,MEMF_CHIP|MEMF_PUBLIC,-15L,(char *)mem,NULL); X else if (mem >= 0x00c00000 && mem < 0x00c80000) X AddMemList(size,MEMF_FAST|MEMF_PUBLIC,-15L,(char *)mem,NULL); X else X AddMemList(size,MEMF_FAST|MEMF_PUBLIC,0L,(char *)mem,NULL); X} X X/* This function can be used after rebooting to remove the specially allocated X SAFE image. This is normally used after copying the safe image into a X standard FASTROM image and adjusting the MMU accordingly. The SAFE RAM X at this point isn't in any memory list, so we aren't really freeing it, X just linking it into a list. */ X Xvoid FreeSAFEImage(kick) Xstruct systag *kick; X{ X if (kick->romlo == 0 || (ULONG)kick->romhi+SMALLROMSIZE == (ULONG)kick->romlo) X ReturnMem(ROMROUND+kick->romsize,kick->romhi); X else { X ReturnMem(ROMROUND+SMALLROMSIZE,kick->romlo); X ReturnMem(SMALLROMSIZE,kick->romhi); X } X} X X/* ====================================================================== */ X X/* This routine gets the system tag from the patched system, if it's X there. This tag is stored in an invalid table entry that's within the X physical ROM image. If the MMU isn't on, there's no system tag, by X definition. This has been enhanced to perform a sanity check on the X tag encountered -- the systag contains a pointer to the table, this X can be checked. */ X Xstruct systag *GetSysTag() { X struct systag *maybetag; X ULONG i, myCRP[2], *table = NULL,size; X APTR oldTrap; X struct Task *task; X X if (cpu == 68040 || !(GetTC() & TC_ENB) || aliens) return NULL; X X GetCRP(myCRP); X table = (ULONG *)myCRP[1]; X X /* In case the MMU is alien and has some of this memory read protected... */ X task = FindTask(0L); X oldTrap = task->tc_TrapCode; X task->tc_TrapCode = (APTR)BerrCode; X X /* The tag is now in an easier-to-locate place. This isn't SetCPU V1.5 X compatible; SetCPU V1.5 FASTROM will appear alien to SetCPU V1.6. But X this is much better for modern systems and modern software. */ X size = (myCRP[0]>>16)+1; X maybetag = (struct systag *)IV_ADDR(table[size]); X if (!maybetag || maybetag->maintable != table || maybetag->tablesize != size<<2) X maybetag = NULL; X X /* Restore the trap vector */ X task->tc_TrapCode = oldTrap; X return maybetag; X} X END_OF_FILE if test 11245 -ne `wc -c <'memory.c'`; then echo shar: \"'memory.c'\" unpacked with wrong size! fi # end of 'memory.c' fi if test -f 'mmu.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'mmu.c'\" else echo shar: Extracting \"'mmu.c'\" \(8963 characters\) sed "s/^X//" >'mmu.c' <<'END_OF_FILE' X/* X SetCPU V1.60 X by Dave Haynie, April 13, 1990 X Released to the Public Domain X X MMU.C MODULE X X This module is responsible for some of the MMU table creation X functions. X*/ X X#include "setcpu.h" X X X/* ====================================================================== */ X X/* This function maps the phantom area for a given memory location. */ X Xvoid Phantom(tag,loc) Xstruct systag *tag; XULONG loc; X{ X ULONG xindex = loc/ROMROUND; X X if (xindex < 60) X tag->maintable[xindex] = PD_ADDR(0x00800000)|PD_DT_PAGE; X else X tag->maintable[xindex] = PD_ADDR(0x00ce0000)|PD_DT_PAGE; X} X X X/* This table contains a list of the blocks of memory that should be X cache-inhibited. */ X Xstatic ULONG InTable[] = { 0x00000000,0x00200000,0x00b00000,0x00f00000,0L,0L }; X X X/* This function fills the basic MMU table and other standard tag itemd from X an allocated image. Some tables may need additional information in the X table. The basic table consists of one table level and uses direct page X translation on a grain of 128K per entry. Everything's directly mapped X except for the last two entries, which are for the $FC0000-$FFFFFF area. */ X Xvoid FillBasicTable(tag,phantoms) Xstruct systag *tag; XLONG phantoms; X{ X register ULONG i, image, j; X ULONG page,size,loc; X X tag->tagsize = SizeOf(struct systag); X tag->progver = PROGRAM_VERSION; X tag->patches = 0; X tag->patchlist = tag->devs = NULL; X tag->config = 1; X tag->BerrSize = 0L; X tag->OldBerr = tag->BerrHandler = NULL; X tag->sysstack = NULL; X tag->sysstksize = 0; X tag->OldReset = tag->ResetCode = NULL; X tag->ResetSize = 0; X X /* Here I make a table that maps everything straight through. */ X for (i = 0; i < tag->tablesize/sizeof(ULONG); i++) X tag->maintable[i] = PD_ADDR(i<<17)|PD_DT_PAGE; X tag->maintable[i] = IV_ADDR(tag)|PD_DT_INVALID; X X /* Mark the inhibited pages. */ X for (i = 0; InTable[i+1]; i += 2) X for (j = InTable[i]/PAGESIZE; j < InTable[i+1]/PAGESIZE; ++j) X tag->maintable[j] |= PD_CI; X X /* Here I map the ROM image to the ROM location. */ X image = (ULONG)tag->romlo; X loc = tag->romloc/PAGESIZE; X if (image) { X if (phantoms) Phantom(tag,image); X tag->maintable[loc++] = PD_ADDR(image)|PD_WP|PD_DT_PAGE; X if (phantoms) Phantom(tag,image+PAGESIZE); X tag->maintable[loc++] = PD_ADDR(image+PAGESIZE)|PD_WP|PD_DT_PAGE; X } X image = (ULONG)tag->romhi; X if (phantoms) Phantom(tag,image); X tag->maintable[loc++] = PD_ADDR(image)|PD_WP|PD_DT_PAGE; X if (phantoms) Phantom(tag,image+PAGESIZE); X tag->maintable[loc] = PD_ADDR(image+PAGESIZE)|PD_WP|PD_DT_PAGE; X X /* Here I look for Bridge Cards, which are known to have problems with X the data cache enabled, so I always disable it, reguardless of X whether caching is actually enabled in the CACR. */ X X if (Bridge.Addr && Bridge.Size) { X page = Bridge.Addr/PAGESIZE; X size = max((ULONG)Bridge.Size/PAGESIZE,1); X while (size-- && page < tag->tablesize) X if ((tag->maintable[page] & PD_DT_TYPE) == PD_DT_PAGE) X tag->maintable[page++] |= PD_CI; X } X} X X/* This routine sets up the MMU registers (shadowed in tag fields) in the X standard SetCPU fashion. The CPU Root Pointer tells the MMU about the X table I've set up, and all that's left to do is bang the Translation X Control Register to turn the thing on. Note that the first half of the X CRP is control data, the second the address of my table. */ X Xvoid SetMMURegs(tag) Xstruct systag *tag; X{ X tag->CRP[0] = CRP_LIMIT(tag->tablesize/sizeof(ULONG)-1)|CRP_SG|CRP_DT_V4BYTE; X tag->CRP[1] = (ULONG)(tag->maintable); X X tag->TC = TC_PS(0x0a)|TC_IS(tag->wrapup)| X TC_TIA(0x0f-tag->wrapup)|TC_TIB(0x03)|TC_TIC(0x04)|TC_TID(0); X} X X/* ====================================================================== */ X X/* This function frees all MMU tables. */ X Xvoid FreeMMUTable(tag) Xstruct systag *tag; X{ X ULONG i,j, *subtab; X X for (i = 0; i < 128; ++i) X if ((tag->maintable[i] & PD_DT_TYPE) == PD_DT_V4BYTE) { X for (subtab = (ULONG *)PD_ADDR(tag->maintable[i]), j = 0; j < 8; ++j) X if ((subtab[j] & PD_DT_TYPE) == PD_DT_V4BYTE) X FreeMem((char *)PD_ADDR(subtab[j]),STKTABSIZE); X FreeMem((char *)subtab,SUBTABSIZE); X } X FreeMem((char *)tag->maintable,tag->tablesize); X} X X/* ====================================================================== */ X X/* This function makes subtables for CardROMFile I/O devices. */ X Xvoid MakeExpTable(tag) Xstruct systag *tag; X{ X ULONG i, *SUBTable, iospace; X struct ExpROMData *er; X X while (er = GetExpROM()) { X er->next = tag->devs; X tag->devs = er; X X iospace = ((ULONG)er->ROMbase)/ROMROUND; X X /* If necessary, modify the table */ X if (tag->maintable[iospace] == PD_ADDR(iospace<<17)|PD_DT_PAGE) { X if (SUBTable = AllocAligned(SUBTABSIZE,TABROUND)) { X for (i = 0; i < 8; ++i) X SUBTable[i] = PD_ADDR((iospace<<17)+(i<<14))|PD_CI|PD_DT_PAGE; X tag->maintable[iospace] = PD_ADDR(SUBTable)|PD_DT_V4BYTE; X } X } else X SUBTable = (ULONG *)PD_ADDR(tag->maintable[iospace]); X X if (SUBTable) { X er->imagebase = (ULONG)AllocAligned(er->ROMsize,DEVROUND); X er->tablebase = (ULONG)&SUBTable[0]; X X MemCopy(er->ROMbase,er->imagebase,er->ROMsize); X iospace = (er->ROMbase - (iospace * ROMROUND))/DEVROUND; X for (i = 0; i < er->ROMsize/DEVROUND; ++i) X SUBTable[iospace+i] = PD_ADDR(er->imagebase+(DEVROUND*i))|PD_CI|PD_DT_PAGE; X } X } X} X X/* ====================================================================== */ X X/* This function hunts down the system stack and translates it into a X block of 32 bit memory if it's found to be located in Chip RAM. Note X that this routine must only be called when the MMU is turned on. The X current functions used to turn the MMU on make use of the supervisor X stack. This code must be run in user mode to insure that the supervisor X stack image and the actual stack are the same during the transfer of X control. */ X Xvoid MakeFastStack(tag) Xstruct systag *tag; X{ X struct ExecBase *eb = *((struct ExecBase **)4L); X ULONG i, *SUBTable, *STKTable, tabndx, subndx, stkndx, tmem, base; X X base = (((ULONG)eb->SysStkLower)/STKROUND)*STKROUND; X X if (base >= 0x00200000L) return; X X tag->sysstksize = (((ULONG)eb->SysStkUpper - (ULONG)eb->SysStkLower + 1)/STKROUND)*STKROUND; X tabndx = base/ROMROUND; X tmem = tabndx * ROMROUND; X X /* Make the I/O level subtable (level 2). Most entries are going to be X a straight translation. */ X X if (!(SUBTable = AllocAligned(SUBTABSIZE,TABROUND)) || X !(STKTable = AllocAligned(STKTABSIZE,TABROUND))) return; X X for (i = 0; i < 8; ++i) X SUBTable[i] = PD_ADDR(tmem+(i*DEVROUND))|PD_DT_PAGE; X tag->maintable[tabndx] = PD_ADDR(SUBTable)|PD_DT_V4BYTE; X X /* Make the Stack level subtable (level 3). Fill all 16 entries with a X straight translation. */ X X subndx = (base - tmem)/DEVROUND; X tmem += subndx * DEVROUND; X X for (i = 0; i < 16; ++i) X STKTable[i] = PD_ADDR((tmem)+(i*STKROUND))|PD_DT_PAGE; X SUBTable[subndx] = PD_ADDR(STKTable)|PD_DT_V4BYTE; X X /* Now take care of the actual stack translation. */ X X tag->sysstack = (char *)AllocAligned(tag->sysstksize,STKROUND); X MemCopy(base,tag->sysstack,tag->sysstksize); X X stkndx = (base - tmem)/STKROUND; X X for (i = 0; i < tag->sysstksize/STKROUND && i < 16; ++i) X STKTable[i+stkndx] = PD_ADDR(tag->sysstack+(STKROUND*i))|PD_DT_PAGE; X FlushATC(); X} X X/* This function removes the fast stack translation. Like the fast stack X creation routine, this must be called with the MMU turned on, in user X mode, so that both stack images can be identical when the switch is X made. This routine doesn't clean up the MMU tables, it just deals X with the stack image. */ X Xvoid FreeFastStack(tag) Xstruct systag *tag; X{ X struct ExecBase *eb = *((struct ExecBase **)4L); X ULONG *SUBTable, *STKTable, tabndx, subndx, tmem, base; X X base = (((ULONG)eb->SysStkLower)/STKROUND)*STKROUND; X X /* Find the stack's translation table. */ X X tabndx = base/ROMROUND; X tmem = tabndx * ROMROUND; X SUBTable = (ULONG *)PD_ADDR(tag->maintable[tabndx]); X X subndx = (base - tmem)/DEVROUND; X X /* Set things back the way they were. */ X X Disable(); X STKTable = (ULONG *)PD_ADDR(SUBTable[subndx]); X MemCopy(tag->sysstack,base,tag->sysstksize); X SUBTable[subndx] = PD_ADDR(tmem+(subndx*DEVROUND))|PD_DT_PAGE; X FlushATC(); X Enable(); X X /* Get rid of the fast image stuff. */ X X FreeMem((char *)STKTable,STKTABSIZE); X FreeMem((char *)tag->sysstack,tag->sysstksize); X} X X/* ====================================================================== */ X X/* This routine knows the best way to reset the system, in an attempt to X avoid MMU-based troubles. */ X Xvoid CleverReset() X{ X geta4(); X CleanBoot(); X} END_OF_FILE if test 8963 -ne `wc -c <'mmu.c'`; then echo shar: \"'mmu.c'\" unpacked with wrong size! fi # end of 'mmu.c' fi echo shar: End of archive 2 \(of 4\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 4 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>. Mail comments to the moderator at <amiga-request@uunet.uu.net>. Post requests for sources, and general discussion to comp.sys.amiga.