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 221 Archive-name: util/setcpu-1.60/part01 [ uuencoded executable enclosed ...tad ] Here's the latest SetCPU program. This archive contains the executable, docs, and source files. This program is used to identify the CPU/FPU/MMU combinations in an Amiga computer, make decisions based on this, modify cache parameters, and on MMU-Based machines, run ROM emulations. The ROM emulation mechanism now supports 512K ROMs such as those used for AmigaOS 2.0. This program and the sources are public domain. -Dave Haynie #!/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 1 (of 4)." # Contents: CardROMList control.a control.i diskio.c expdev.c idents.a # makefile misc.c other.a reboot.a setcpu.i # Wrapped by tadguy@abcfd20 on Tue Aug 14 17:35:34 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'CardROMList' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'CardROMList'\" else echo shar: Extracting \"'CardROMList'\" \(59 characters\) sed "s/^X//" >'CardROMList' <<'END_OF_FILE' X0x202 0x01 0x10000 0x8000 0x4000 CBM_2090A_Disk_Controller END_OF_FILE if test 59 -ne `wc -c <'CardROMList'`; then echo shar: \"'CardROMList'\" unpacked with wrong size! fi # end of 'CardROMList' fi if test -f 'control.a' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'control.a'\" else echo shar: Extracting \"'control.a'\" \(5731 characters\) sed "s/^X//" >'control.a' <<'END_OF_FILE' X;====================================================================== X; X; SetCPU V1.60 X; by Dave Haynie, April 13, 1990 X; Released to the Public Domain X; X; CONTROL.A MODULE X; X; This module contains functions that access various control X; registers in the 32 bit CPUs and MMUs. X; X;====================================================================== X X include "setcpu.i" X X cseg X X;********************************************************************** X; X; These functions work with the CPU control registers. X; X********************************************************************** X X xdef _SetCACR ; Set CACR register X xdef _GetCACR ; Get CACR register X xdef _GetVBR ; Get the Vector Base Register X X;====================================================================== X; X; This function sets the value of the 68020/68030 CACR register. X; It assumes a 68020 or 68030 based system. X; X; void SetCACR(cacr) X; ULONG cacr; X; X;====================================================================== X X_SetCACR: X move.l 4(sp),d0 ; New CACR is on stack X move.l 4,a6 ; Get ExecBase X X move.w LIB_VERSION(a6),d1 ; Are we in 2.0? X cmp.w #36,d1 ; If so, use the 2.0 function X blt MySetCACR X X move.l #$ffffffff,d1 X CALLSYS CacheControl X rts X XMySetCACR: X move.l a5,-(sp) ; Save this register X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp)+,a5 ; Give it back X rts X1$ X MOVEC_ d0,cacr ; Set the CACR X rte X X;====================================================================== X; X; This function returns the 68020/68030 CACR register. It assumes X; a 68020 or better system. X; X; ULONG GetCACR() X; X;====================================================================== X X_GetCACR: X move.l 4,a6 ; Get ExecBase X X move.w LIB_VERSION(a6),d1 ; Are we in 2.0? X cmp.w #36,d1 ; If so, use the 2.0 function X blt MyGetCACR X X moveq.l #0,d0 X move.l d0,d1 X CALLSYS CacheControl X rts X XMyGetCACR: X move.l a5,-(sp) ; Save this register X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp)+,a5 ; Give back register X rts X1$ X MOVEC_ cacr,d0 ; Make CACR the return value X rte X X;====================================================================== X; X; This function returns the value of the Vector Base Register; X; all exceptions are referenced from this. This function assumes X; we're on a CPU with a VBR (eg, no 68000's need apply). X; X; ULONG *GetVBR() X; X;====================================================================== X X_GetVBR: X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) ; Save this register X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp)+,a5 ; Give back register X rts X1$ X MOVEC_ vbr,d0 ; Make CACR the return value X rte X X;********************************************************************** X; X; These functions access MMU registers X; X;********************************************************************** X X xdef _GetCRP ; Gets MMU CRP register X xdef _SetCRP ; Sets MMU CRP register X xdef _GetTC ; Gets MMU TC register X xdef _SetTC ; Gets MMU TC register X X;====================================================================== X; X; This function returns the MMU CRP register. It assumes a 68020 X; system with MMU, or a 68030 based system (eg, test for MMU before X; you call this, or you wind up in The Guru Zone). Note that the X; CRP register is two longwords long. X; X; void GetCRP(ULONG *) X; X;====================================================================== X X_GetCRP: X move.l 4(sp),a0 ; Pointer to the CRP storage area X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) X lea.l 2$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp)+,a5 X rts X2$ X PMOVE_ crp,(a0) ; Just get the CRP register X rte X X;====================================================================== X; X; This function sets the MMU CRP register. It assumes a 68020 X; system with MMU, or a 68030 based system (eg, test for MMU before X; you call this, or you wind up in The Guru Zone). Note that the X; CRP register is two longwords long. X; X; void SetCRP(ULONG *) X; X;====================================================================== X X_SetCRP: X move.l 4(sp),a0 ; Pointer to the CRP storage area X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X movem.l (sp)+,a5 ; Give back registers X rts X1$ X PMOVE_ (a0),crp ; Just load the CRP register X rte X X;====================================================================== X; X; This function returns the MMU TC register. It assumes a 68020 X; system with MMU, or a 68030 based system (eg, test for MMU before X; you call this, or you wind up in The Guru Zone). X; X; ULONG GetTC() X; X;====================================================================== X X_GetTC: X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) X subq.l #4,sp ; Make a place to dump TC X move.l sp,a0 X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp),d0 ; Here's the result X addq.l #4,sp X move.l (sp)+,a5 X rts X1$ X PMOVE_ tc,(a0) ; Just get the TC register X rte X X;====================================================================== X; X; This function sets the MMU TC register. It assumes a 68020 X; system with MMU, or a 68030 based system (eg, test for MMU before X; you call this, or you wind up in The Guru Zone). X; X; void SetTC(ULONG) X; X;====================================================================== X X_SetTC: X lea.l 4(sp),a0 ; Get address of our new TC value X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp)+,a5 X rts X1$ X PMOVE_ (a0),tc ; Just set the TC register X rte X X end END_OF_FILE if test 5731 -ne `wc -c <'control.a'`; then echo shar: \"'control.a'\" unpacked with wrong size! fi # end of 'control.a' fi if test -f 'control.i' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'control.i'\" else echo shar: Extracting \"'control.i'\" \(5383 characters\) sed "s/^X//" >'control.i' <<'END_OF_FILE' X;====================================================================== X; X; SetCPU V1.60 X; by Dave Haynie, April 13, 1990 X; Released to the Public Domain X; X; CONTROL.A MODULE X; X; This module contains functions that access various control X; registers in the 32 bit CPUs and MMUs. X; X;====================================================================== X X include "setcpu.i" X X cseg X X;********************************************************************** X; X; These functions work with the CPU control registers. X; X********************************************************************** X X xdef _SetCACR ; Set CACR register X xdef _GetCACR ; Get CACR register X xdef _GetVBR ; Get the Vector Base Register X X;====================================================================== X; X; This function sets the value of the 68020/68030 CACR register. X; It assumes a 68020 or 68030 based system. X; X; void SetCACR(cacr) X; ULONG cacr; X; X;====================================================================== X X_SetCACR: X move.l 4(sp),d0 ; New CACR is on stack X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) ; Save this register X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp)+,a5 ; Give it back X rts X1$ X MOVEC_ d0,cacr ; Set the CACR X rte X X;====================================================================== X; X; This function returns the 68020/68030 CACR register. It assumes X; a 68020 or better system. X; X; ULONG GetCACR() X; X;====================================================================== X X_GetCACR: X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) ; Save this register X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp)+,a5 ; Give back register X rts X1$ X MOVEC_ cacr,d0 ; Make CACR the return value X rte X X;====================================================================== X; X; This function returns the value of the Vector Base Register; X; all exceptions are referenced from this. This function assumes X; we're on a CPU with a VBR (eg, no 68000's need apply). X; X; ULONG *GetVBR() X; X;====================================================================== X X_GetVBR: X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) ; Save this register X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp)+,a5 ; Give back register X rts X1$ X MOVEC_ vbr,d0 ; Make CACR the return value X rte X X;********************************************************************** X; X; These functions access MMU registers X; X;********************************************************************** X X xdef _GetCRP ; Gets MMU CRP register X xdef _SetCRP ; Sets MMU CRP register X xdef _GetTC ; Gets MMU TC register X xdef _SetTC ; Gets MMU TC register X X;====================================================================== X; X; This function returns the MMU CRP register. It assumes a 68020 X; system with MMU, or a 68030 based system (eg, test for MMU before X; you call this, or you wind up in The Guru Zone). Note that the X; CRP register is two longwords long. X; X; void GetCRP(ULONG *) X; X;====================================================================== X X_GetCRP: X move.l 4(sp),a0 ; Pointer to the CRP storage area X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) X lea.l 2$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp)+,a5 X rts X2$ X PMOVE_ crp,(a0) ; Just get the CRP register X rte X X;====================================================================== X; X; This function sets the MMU CRP register. It assumes a 68020 X; system with MMU, or a 68030 based system (eg, test for MMU before X; you call this, or you wind up in The Guru Zone). Note that the X; CRP register is two longwords long. X; X; void SetCRP(ULONG *) X; X;====================================================================== X X_SetCRP: X move.l 4(sp),a0 ; Pointer to the CRP storage area X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X movem.l (sp)+,a5 ; Give back registers X rts X1$ X PMOVE_ (a0),crp ; Just load the CRP register X rte X X;====================================================================== X; X; This function returns the MMU TC register. It assumes a 68020 X; system with MMU, or a 68030 based system (eg, test for MMU before X; you call this, or you wind up in The Guru Zone). X; X; ULONG GetTC() X; X;====================================================================== X X_GetTC: X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) X subq.l #4,sp ; Make a place to dump TC X move.l sp,a0 X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp),d0 ; Here's the result X addq.l #4,sp X move.l (sp)+,a5 X rts X1$ X PMOVE_ tc,(a0) ; Just get the TC register X rte X X;====================================================================== X; X; This function sets the MMU TC register. It assumes a 68020 X; system with MMU, or a 68030 based system (eg, test for MMU before X; you call this, or you wind up in The Guru Zone). X; X; void SetTC(ULONG) X; X;====================================================================== X X_SetTC: X lea.l 4(sp),a0 ; Get address of our new TC value X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp)+,a5 X rts X1$ X PMOVE_ (a0),tc ; Just set the TC register X rte X END_OF_FILE if test 5383 -ne `wc -c <'control.i'`; then echo shar: \"'control.i'\" unpacked with wrong size! fi # end of 'control.i' fi if test -f 'diskio.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'diskio.c'\" else echo shar: Extracting \"'diskio.c'\" \(5075 characters\) sed "s/^X//" >'diskio.c' <<'END_OF_FILE' X/* X SetCPU V1.60 X by Dave Haynie, April 13, 1990 X Released to the Public Domain X X DISKIO.C MODULE X X This module is responsible for fetching ROM images from various X kinds of disks and files. X*/ X X#include "setcpu.h" X X/* This function allocates a ROM image from a KickStart disk for KICKROM. */ X X#define ColorShift(x) (LONG)((((x)&0xf)+1)%15) X Xstruct systag *AllocKSImage(name) Xchar *name; X{ X struct systag *tag = NULL; X ULONG *buf = NULL, blocks; X char *ptr; X LONG unit, i, r = 0x0004L, g = 0x0008L, b = 0x000cL,start; X struct MsgPort *port = NULL; X struct IOStdReq *req = NULL; X struct Window *hand = NULL; X BOOL devok = FALSE; X X /* Then we expect it to be a kickstart disk, so we check out the device, X the disk, etc. If all goes well, we'll be in business. */ X X if ((unit = CheckTDDev(name)) == -1L) { X LoadErr = 16; X goto fail; X } X X /* This is the stuff that need opening... */ X port = (struct MsgPort *) CreatePort("diskreq.port",0L); X if (port) req = CreateStdIO(port,0L); X if (req) devok = !OpenDevice("trackdisk.device",unit,(struct IORequest *)req,0L); X if (devok) buf = (ULONG *)AllocMem(512L,MEMF_CHIP); X if (!port || !req || !devok || !buf) goto fail; X X /* Make sure we're a kick disk. */ X hand = CoolHand(); X while ((ReadBuf((char *)buf,0L,req) != READOK) || X !strniequ("KICK",(char *)buf,4)) X Delay(150L); X X /* Check the size of this kickstart. */ X X if (!(tag = AllocMem(SizeOf(struct systag),0L))) goto fail; X start = 0; X do { X if (ReadBuf((char *)buf,++start,req) != READOK) goto fail; X ptr = (char *)SizeROM(tag,buf,TRUE); X } while (ptr == NULL && start < 32L); X X if (!ptr) goto fail; X X blocks = tag->romsize/512L; X X /* Looks like we're in shape to get the actual system. */ X X SetRGB4(&(hand->WScreen->ViewPort),2L,r,g,b); X for (i = 1; i <= blocks; ++i) { X if (ReadBuf((char *)buf,i,req) != READOK) break; X MemCopy((char *)buf,ptr,512L); X ptr += 512L; X r = ColorShift(r); X g = ColorShift(g); X b = ColorShift(b); X X SetRGB4(&(hand->WScreen->ViewPort),2L,r,g,b); X } X LoadErr = 0; X Xdone: X if (buf) FreeMem((char *)buf,512L); X if (devok) { X MotorOff(req); X CloseDevice((struct IORequest *)req); X } X if (req) DeleteStdIO(req); X if (port) DeletePort(port); X return tag; X Xfail: X if (tag) { X FreeMem(tag,SizeOf(struct systag)); X tag = NULL; X } X goto done; X} X X/* This function allocates a ROM image from an AmigaDOS file for either X KICKROM or FASTROM. */ X Xstruct systag *AllocFILEImage(name) Xchar *name; X{ X struct systag *tag = NULL; X ULONG *rom = NULL, space[2], check; X BPTR file = NULL; X struct FileInfoBlock *fib; X X /* First off, let's check out this here file. */ X X if (!(fib = AllocMem(SizeOf(struct FileInfoBlock),0L))) goto fail; X if (!(file = Lock(name,ACCESS_READ))) { X LoadErr = 24; X goto fail; X } X Examine(file,fib); X UnLock(file); X file = NULL; X if (fib->fib_DirEntryType > 0L || !(file = Open(name,MODE_OLDFILE))) { X LoadErr = 24; X goto fail; X } X X /* Try to find a sensible ROM header, either its a plain ROM, or the one X with the extra sizing info at the head. */ X X Read(file,(char *)space,8L); X if (space[0]) X Seek(file,0L,OFFSET_BEGINNING); X else { X check = space[1]; X Read(file,(char *)space,8L); X Seek(file,8L,OFFSET_BEGINNING); X } X X /* Let's allocate the space I need. KICKROMs don't use a disk image X directly, so they don't need an MMU table and don't care about any special X alignment. FASTROMs read from disk do care, so I will align this image. */ X X SmartlyGetRange(); X if (!(tag = AllocAligned(SizeOf(struct systag),8L))) goto fail; X X if (!(rom = SizeROM(tag,space,TRUE))) { X LoadErr == 22; X goto fail; X } X if (tag->romsize != Read(file,(char *)rom,tag->romsize)) { X LoadErr = 23; X goto fail; X } X Close(file); X FreeMem(fib,SizeOf(struct FileInfoBlock)); X return tag; X Xfail: X if (file) Close(file); X if (fib) FreeMem(fib,SizeOf(struct FileInfoBlock)); X if (rom) FreeMem(rom,tag->romsize); X if (tag) FreeMem(tag,SizeOf(struct systag)); X return NULL; X} X X/* This function gets a ROM image from disk; in temporary unaligned memory X for a KICKROM image, permanent aligned memory for a FASTROM image. */ X Xstruct systag *AllocDISKImage(type,name) XUWORD type; Xchar *name; X{ X struct systag *tag; X ULONG *table; X X /* Reset the error code. */ X LoadErr = 0; X X /* Let's check out this here file. It's easy to tell; we want a FILE X image if we aren't passed a KICK_ROM request with a device name. */ X X if (type == ROM_FAST || name[strlen(name)-1] != ':') { X tag = AllocFILEImage(name); X if ((tag->romtype = type) == ROM_FAST) { X FindWrap(tag); X if (!(table = AllocAligned(tag->tablesize+4,TABROUND))) return NULL; X tag->maintable = table; X FillBasicTable(tag,FALSE); X } X return tag; X } X X return AllocKSImage(name); X} END_OF_FILE if test 5075 -ne `wc -c <'diskio.c'`; then echo shar: \"'diskio.c'\" unpacked with wrong size! fi # end of 'diskio.c' fi if test -f 'expdev.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'expdev.c'\" else echo shar: Extracting \"'expdev.c'\" \(6166 characters\) sed "s/^X//" >'expdev.c' <<'END_OF_FILE' X/* X SetCPU V1.60 X by Dave Haynie, April 13, 1990 X Released to the Public Domain X X EXPANSION DEVICE MODULE X X This module maintains the code used to detect and translate X a given expansion device. X*/ X X#include "setcpu.h" X X/* ====================================================================== */ X X/* Stuff I need for this module. */ X Xchar *malloc(); Xint sscanf(); X X/* ====================================================================== */ X X/* This section manages devices with on-board ROM. The actual X implementation of this stuff is pretty well hidden in this X module. */ X X/* This structure manages the expansion devices that we know about. */ X Xstruct ExpDev { X struct Node node; X ULONG manuf; X ULONG board; X ULONG size; X ULONG romoffset; X ULONG romsize; X}; X X/* Here's the list of all the devices we know about. */ X Xstatic struct List Devices = X {(struct Node *)&Devices.lh_Tail,NULL,(struct Node *)&Devices.lh_Head,0,0}; X Xstatic struct ExpDev *CurrentDevice = NULL; X X/* This function reads the list of expansion devices from the given file. X The file should contain data for one device per line, with the X following format: X X MANUF PROD SIZE START LENGTH id-string X X Except for the last field, all numbers are integers, which may be X expressed as decimal or hexidecimal. The last field is a text X string which may contain any information. It's very likely that X the line for each device will have to be supplied by the maker X of any device, since there's no way to figure out if a device's X ROM is on the same MMU page as an important I/O register which X shouldn't ever be translated. The description I use for the Amiga X 2090A controller is: X X 0x202 0x01 0x10000 0x8000 0x4000 CBM 2090A Disk Controller X X The actual fields are: X X MANUF The Manufacturer's code for the PIC X PROD The Product code for the PIC X SIZE The configured size of the PIC X START The offset from the PIC base for the start of ROM X LENGTH The length of the ROM X id-string Whatever the hell you want X*/ X XLONG ReadExpDevs(name) Xchar *name; X{ X FILE *file; X char buf[256],msg[256]; X struct ExpDev *ed; X int len,i; X X if (!(file = fopen(name,"r"))) return FALSE; X X while (fgets(buf,256,file)) { X ed = (struct ExpDev *)malloc(sizeof(struct ExpDev)); X if (sscanf(buf,"%lx%lx%lx%lx%lx%s",&ed->manuf,&ed->board,&ed->size, X &ed->romoffset,&ed->romsize,msg) >= 5) { X if (len = strlen(msg)) { X ed->node.ln_Name = (char *)malloc(len+1); X for (i = 0; i <= len; ++i) X ed->node.ln_Name[i] = (msg[i] == '_')?' ':msg[i]; X } X if (ed->romsize = ((ed->romsize/DEVROUND)*DEVROUND)) X AddHead(&Devices,(struct Node *)ed); X else X free(ed); X } else X free(ed); X } X fclose(file); X CurrentDevice = (struct ExpDev *)Devices.lh_Head; X return TRUE; X} X X/* ====================================================================== */ X X/* This function returns the ROM information I'll need for a given X expansion device. Because of some Commodore screwups, the A2090A X appears the same device as other boards like the Commodore RAM X board. So I have the size passed as well, as a consistency X check. The returned ExpROMData structure is allocated here, and X can be freed when no longer needed. */ X Xstruct ExpROMData *GetExpROM() X{ X struct ConfigDev *cd; X struct DiagArea *da; X struct ExpROMData *ed; X X if (!CurrentDevice || !ExpansionBase) return NULL; X cd = FindConfigDev(NULL,CurrentDevice->manuf,CurrentDevice->board); X X while (cd) { X if (((ULONG)cd->cd_BoardSize == CurrentDevice->size) && X (cd->cd_Rom.er_Type & ERTF_DIAGVALID)) { X da = (struct DiagArea *)(((ULONG)cd->cd_BoardAddr)+((ULONG)cd->cd_Rom.er_InitDiagVec)); X X /* This is just a sanity check to make sure we really use the X ROM out on this card -- a nybble or byte wide ROM will be in X RAM already. */ X if ((da->da_Config & DAC_BUSWIDTH) == DAC_WORDWIDE) { X ed = (struct ExpROMData *)AllocMem(SizeOf(struct ExpROMData),MEMF_CLEAR); X ed->ROMbase = ((ULONG)cd->cd_BoardAddr) + CurrentDevice->romoffset; X ed->ROMsize = CurrentDevice->romsize; X ed->imagebase = NULL; X ed->tablebase = NULL; X ed->name = (char *)AllocMem((ULONG) X strlen(CurrentDevice->node.ln_Name)+1,0L); X strcpy(ed->name,CurrentDevice->node.ln_Name); X ++CurrentDevice; X return ed; X } X } X cd = FindConfigDev(cd,CurrentDevice->manuf,CurrentDevice->board); X } X CurrentDevice = (struct ExpDev *)CurrentDevice->node.ln_Succ; X return NULL; X} X X/* This function removes a CardROMFile generated I/O ROM table list. */ X Xvoid FreeExpROM(emem) Xstruct ExpROMData *emem; X{ X struct ExpROMData *edel; X X while (emem) { X edel = emem; X emem = emem->next; X FreeMem(edel->imagebase,edel->ROMsize); X FreeMem(edel->name,(ULONG)strlen(edel->name)+1); X FreeMem(edel,SizeOf(struct ExpROMData)); X } X} X X/* ====================================================================== */ X X/* This routine is called to configure the system devices without calling any X ROM routines that could possibly goober up on older OS releases. Other X than skipping ROMs, this should do the same thing as the ConfigChain() X function in expansion.library. */ X Xvoid SafeConfigDevs() X{ X struct ConfigDev *cd; X char *base = (char *)0xe80000; X X if (!ExpansionBase) return; X X /* Should also loop only as long as X !(ExpansionBase->eb_Flags & EBB_CLOGGED), X but I don't know what EBB_CLOGGED is yet.. */ X X while (cd = AllocConfigDev()) { X if (ReadExpansionRom(base,cd)) { X FreeConfigDev(cd); X break; X } X X /* Got it, let's get rid of any ROM critters. */ X cd->cd_Rom.er_Type &= ~ERTF_DIAGVALID; X X /* Now adding the board should be safe! */ X if (ConfigBoard(base,cd)) { X FreeConfigDev(cd); X break; X } X AddConfigDev(cd); X } X} X END_OF_FILE if test 6166 -ne `wc -c <'expdev.c'`; then echo shar: \"'expdev.c'\" unpacked with wrong size! fi # end of 'expdev.c' fi if test -f 'idents.a' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'idents.a'\" else echo shar: Extracting \"'idents.a'\" \(6346 characters\) sed "s/^X//" >'idents.a' <<'END_OF_FILE' X;====================================================================== X; X; SetCPU V1.60 X; by Dave Haynie, April 13, 1990 X; Released to the Public Domain X; X; IDENTS.A MODULE X; X; This module contains the functions that ID the CPU, MMU, and FPU X; type indtalled in the system. X; X;====================================================================== X X include "setcpu.i" X X cseg X X xdef _GetCPUType ; ID the CPU X xdef _GetMMUType ; ID the MMU X xdef _GetFPUType ; ID the FPU X X;====================================================================== X; X; This routine checks CPU flags early in ExecBase for extended X; CPUs that test as a 68020 under 1.3. If these flags are set, X; the actual CPU/MMU type test can be skipped. X; X;====================================================================== X XTestFlags: X moveq.l #0,d0 X btst.b #AFB_68040,ATNFLGS(a6) ; Does the OS think an '040 is here? X beq NoEarly40 X move.l #68040,d0 X rts XNoEarly40: X btst.b #AFB_68030,ATNFLGS(a6) ; Does the OS think an '030 is here? X beq NoEarly30 X move.l #68030,d0 ; Sure does... XNoEarly30: X rts X X X;====================================================================== X; X; This function returns the type of the CPU in the system as a X; longword: 68000, 68010, 68020, or 68030. The testing must be done X; in reverse order, in that any higher CPU also has the bits set for X; a lower CPU. Also, since 1.3 doesn't recognize the 68030, if I X; find the 68020 bit set, I always check for the presence of a X; 68030. X; X; This routine should be the first test routine called under 1.2 X; and 1.3. X; X; ULONG GetCPUType(); X; X;====================================================================== X X_GetCPUType: X move.l 4,a6 ; Get ExecBase X jsr TestFlags ; Check extended CPU types X cmp.l #0,d0 X beq CPURealTest X rts XCPURealTest: X movem.l a4/a5,-(sp) ; Save this register X btst.b #AFB_68020,ATNFLGS(a6) ; Maybe a 68020 X bne FindReal32 X btst.b #AFB_68010,ATNFLGS(a6) ; Maybe a 68010? X bne Found10 X move.l #68000,d0 ; Just a measley '000 X movem.l (sp)+,a4/a5 X rts XFound10: X move.l #68010,d0 ; Yup, we're an '010 X movem.l (sp)+,a4/a5 X rts XFindReal32: X move.w LIB_VERSION(a6),d0 ; Are we in 2.0? X cmp.w #36,d0 ; If so, we don't need to test X bge No40 X X lea.l SuperGCT,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X X btst.l #CIB_BURST,d0 ; Do we have a set burst bit? X beq No30 X move.l #68030,d0 ; It's a 68030 X bset.b #AFB_68030,ATNFLGS(a6) X movem.l (sp)+,a4/a5 X rts XNo30: X btst.l #CIB_ENABLE40,d1 ; Do we have 040 cache enable? X beq No40 X move.l #68040,d0 ; It's a 68040 X bset.b #AFB_68040,ATNFLGS(a6) X movem.l (sp)+,a4/a5 X rts XNo40: X move.l #68020,d0 ; Guess we're a plain old '020 X movem.l (sp)+,a4/a5 X rts X X ; This routine tries to set a few interesting CACR bits, and X ; returns the actual register value that took in d0. XSuperGCT: X MOVEC_ cacr,d1 ; Get the cache register X move.l d1,d0 ; Make a copy X bset.l #CIB_BURST,d0 ; Set the inst burst bit 030 X bclr.l #CIB_ENABLE,d0 ; Clear the inst cache bit 030 X bset.l #CIB_ENABLE40,d0 ; Set the inst cache bit 040 X MOVEC_ d0,cacr ; Try to set the CACR X MOVEC_ cacr,d0 ; Save the real value X MOVEC_ d1,cacr ; Restore it X rte X X;====================================================================== X; X; This function returns 0L if the system contains no MMU, X; 68851L if the system does contain an 68851, or the CPU number X; for CPUs with integral CPUs. X; X; This routine seems to lock up on at least some CSA 68020 X; boards, though it runs just fine on those from Ronin and X; Commodore, as well as all 68030 boards it's been tested on. X; X; ULONG GetMMUType() X; X;====================================================================== X X_GetMMUType: X move.l 4,a6 ; Get ExecBase X jsr TestFlags ; Check extended CPU types X cmp.l #0,d0 X beq MMURealTest X rts X X ; For any other machine, a real test must be done. The test will X ; try an MMU instruction. The instruction will fail unless we're X ; on a "bogus MMU" system, where the FPU responds as an MMU. XMMURealTest: X movem.l a3/a4/a5,-(sp) ; Save this stuff X move.l #0,a1 X CALLSYS FindTask ; Call FindTask(0L) X move.l d0,a3 X X move.l TC_TRAPCODE(a3),a4 ; Change the exception vector X move.l #MMUTraps,TC_TRAPCODE(a3) X X move.l #-1,d0 ; Try to detect undecode FPU X subq.l #4,sp ; Get a local variable X PMOVE_ tc,(sp) ; Let's try an MMU instruction X addq.l #4,sp ; Return that local X move.l a4,TC_TRAPCODE(a3) ; Reset exception stuff X movem.l (sp)+,a3/a4/a5 ; and return the registers X rts X X ; This is the exception code. No matter what machine we're on, X ; we get an exception. If the MMU's in place, we should get a X ; privilige violation; if not, an F-Line emulation exception. XMMUTraps: X move.l (sp)+,d0 ; Get Amiga supplied exception # X cmpi #11,d0 ; Is it an F-Line? X beq MMUNope ; If so, go to the fail routine X move.l #68851,d0 ; We have MMU X addq.l #4,2(sp) ; Skip the MMU instruction X rte XMMUNope: X moveq.l #0,d0 ; It dinna woik, X addq.l #4,2(sp) ; Skip the MMU instruction X rte X X;====================================================================== X; X; This function returns the type of the FPU in the system as a X; longword: 0 (no FPU), 68881, or 68882. X; X; ULONG GetFPUType(); X; X;====================================================================== X X_GetFPUType: X move.l 4,a6 ; Get ExecBase X btst.b #AFB_68040,ATNFLGS(a6) ; Is there a 68040 here? X beq Look4FPU X move.l #68040,d0 X rts XLook4FPU: X move.l a5,-(sp) ; Save this register X btst.b #AFB_68881,ATNFLGS(a6) ; Does the OS think an FPU is here? X bne FPUHere X moveq.l #0,d0 ; No FPU here, dude X move.l (sp)+,a5 ; Give back the register X rts XFPUHere: X btst.b #AFB_68882,ATNFLGS(a6) ; How's about an '882? X beq FPUTest X move.l #68882,d0 ; Sure does... X move.l (sp)+,a5 X rts XFPUTest: X move.w LIB_VERSION(a6),d0 ; Are we in 2.0? X cmp.w #36,d0 ; If so, we don't need to test X blt FPUTrap X move.l #68881,d0 X move.l (sp)+,a5 X rts XFPUTrap: X lea.l FPUSuper,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X move.l (sp)+,a5 ; Give back registers X rts XFPUSuper: X move.l #68881,d0 ; Assume we're a 68881 X fsave -(sp) ; Test and check X moveq.l #0,d1 X move.b 1(sp),d1 ; Size of this frame X cmpi #$18,d1 X beq FPU81 X move.l #68882,d0 ; It's a 68882 X bset.b #AFB_68882,ATNFLGS(a6) XFPU81: X frestore (sp)+ ; Restore the stack X rte X X end X END_OF_FILE if test 6346 -ne `wc -c <'idents.a'`; then echo shar: \"'idents.a'\" unpacked with wrong size! fi # end of 'idents.a' fi if test -f 'makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'makefile'\" else echo shar: Extracting \"'makefile'\" \(464 characters\) sed "s/^X//" >'makefile' <<'END_OF_FILE' X###################################################################### X# X# Makefile for SetCPU V1.6 X# X###################################################################### X X.a.o: X as -o $@ $*.a X XCFLAGS = +x5 XLFLAGS = -lm -lc X XCOBJS = expdev.o memory.o mmu.o coolhand.o misc.o diskio.o setcpu.o XAOBJS = idents.o control.o reboot.o other.o XOBJS = $(AOBJS) $(COBJS) X XSetCPU: $(OBJS) setcpu.o X ln $(OBJS) -o SetCPU $(LFLAGS) X X$(COBJS): setcpu.h X X$(AOBJS): setcpu.i END_OF_FILE if test 464 -ne `wc -c <'makefile'`; then echo shar: \"'makefile'\" unpacked with wrong size! fi # end of 'makefile' fi if test -f 'misc.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'misc.c'\" else echo shar: Extracting \"'misc.c'\" \(5481 characters\) sed "s/^X//" >'misc.c' <<'END_OF_FILE' X/* X SetCPU V1.60 X by Dave Haynie, April 13, 1990 X Released to the Public Domain X X MISC.C MODULE X X This module is responsible for managing ROM image patchs. X*/ X X#include "setcpu.h" X X X/* ====================================================================== */ X X/* This replaces the Lattice "stricmp()" function, plus it's a better form X for my needs here. */ X XLONG striequ(s1,s2) Xchar *s1,*s2; X{ X LONG aok = FALSE; X X while (*s1 && *s2 && (aok = (*s1++ & 0xdf) == (*s2++ & 0xdf))); X return (LONG) (!*s1 && !*s2 && aok); X} X XLONG strniequ(s1,s2,n) Xchar *s1,*s2; Xunsigned n; X{ X LONG aok = FALSE; X X while (n-- && *s1 && *s2 && (aok = (*s1++ & 0xdf) == (*s2++ & 0xdf))); X return aok; X} X X/* ====================================================================== */ X X/* The device I/O functions. */ X X/* This routine turns off the motor. */ X Xvoid MotorOff(req) Xstruct IOStdReq *req; X{ X req->io_Length = 0L; X req->io_Command = TD_MOTOR; X (void)DoIO((struct IORequest *)req); X} X X/* This function fills the buffer "buf" with the contents of the given X sector number. Returns 0 if there's no error. */ X XBYTE ReadBuf(buf,sect,req) Xchar *buf; XLONG sect; Xstruct IOStdReq *req; X{ X req->io_Length = 512L; X req->io_Data = (APTR) buf; X req->io_Command = CMD_READ; X req->io_Offset = (512L * sect); X (void)DoIO((struct IORequest *)req); X return req->io_Error; X} X X/* This function takes in a DOS name, and returns either the X trackdisk.device unit that it corresponds to, or -1L. */ X XLONG CheckTDDev(name) Xchar *name; X{ X char *devname; X struct DosLibrary *dl; X struct RootNode *dr; X struct DosInfo *di; X struct DeviceNode *dev; X struct FileSysStartupMsg *start; X struct DosEnvec *env; X X dl = (struct DosLibrary *)OpenLibrary("dos.library",0L); X dr = (struct RootNode *)dl->dl_Root; X di = (struct DosInfo *)BADDR(dr->rn_Info); X dev = (struct DeviceNode *)BADDR(di->di_DevInfo); X CloseLibrary((struct Library *)dl); X X /* Next we find the device */ X if (name[strlen(name)-1] == ':') name[strlen(name)-1] = '\0'; X X for (; dev != NULL; dev = (struct DeviceNode *)BADDR(dev->dn_Next)) { X if (dev->dn_Type != DLT_DEVICE) continue; X devname = (char *)BADDR(dev->dn_Name); X if (strniequ(name,devname+1,(unsigned)devname[0])) break; X } X X /* Is it a valid trackdisk.device? */ X if (!dev) return -1L; X if (!(start = (struct FileSysStartupMsg *)BADDR(dev->dn_Startup))) return -1L; X env = (struct DosEnvec *)BADDR(start->fssm_Environ); X if (env->de_BlocksPerTrack != 11L || env->de_LowCyl != 0L) return -1L; X devname = (char *)BADDR(start->fssm_Device); X if (!strniequ(devname+1,"trackdisk.device",16)) return -1L; X X return start->fssm_Unit; X} X X/* ====================================================================== */ X X/* The patch manager stuff. */ X X/* The "JSR address" opcode used for my patches. */ X X#define JSR_OPCODE 0x4eb9 X X/* These are for some string patches */ X Xstatic char DiskS[] = "SALV to recover it! "; X X/* These are the V1.3 patches */ X Xstruct pitem PL_345[] = { X { PT_KEYBOARD,0,0x2528a, 0L, NULL }, /* Keyboard... */ X { PT_STRING, 0,0x3fe19, 20L, (UWORD *)DiskS }, /* "DiskDoctor" name */ X { PT_END, 0, 0, 0L, NULL } X}; X Xstruct pitem PL_33180[] = { X { PT_KEYBOARD,0,0x2572a, 0L, NULL }, /* Keyboard... */ X { PT_STRING, 0,0x3fe11, 20L, (UWORD *)DiskS }, /* "DiskDoctor" name */ X { PT_END, 0, 0, 0L, NULL } X}; X X/* This is main system patch list. */ X Xstruct patch SystemPatch[] = { X { &SystemPatch[1], &PL_345[0],34,5 }, X { NULL, &PL_33180[0],33,180 } X}; X X/* This is a pointer to the base of the last applied patch, for making X patch links. The structure of any applied allocated patch, such as X a JSR patch, is a link pointer, the actual patch size, and then the X patch code. This lets any version of SetCPU remove allocated patches X from any other version, providing it can locate the tag. */ X Xstruct MemChunk *lastpatch = NULL; X X/* This routine applys the patch */ X XLONG AddPatch(rom,lst,tag) XULONG rom; Xstruct patch *lst; Xstruct systag *tag; X{ X UWORD *kickver = (UWORD *)(0x100000C - ( * (ULONG *) 0xFFFFEC )); X UWORD *addr, *base; X struct pitem *item; X struct MemChunk *chunk; X LONG any = FALSE; X X while (lst) { X if (lst->Version == kickver[0] && lst->Revision == kickver[1]) { X for (item = &lst->list[0]; item->Type != PT_END; ++item) { X any = TRUE; X switch (item->Type) { X case PT_IGNORE : X break; X case PT_STRING : X MemCopy(item->Code,(char *)(rom+item->Offset),item->Length); X ++tag->patches; X break; X case PT_JSR : X chunk = (struct MemChunk *)AllocMem(item->Length+14L,0L); X chunk->mc_Next = lastpatch; X lastpatch = chunk; X chunk->mc_Bytes = item->Length+14L; X addr = (UWORD *)(((ULONG)chunk)+8L); X base = (UWORD *)(rom+item->Offset); X MemCopy(base,addr,6L); X base[0] = (UWORD)JSR_OPCODE; X base[1] = (UWORD)(((ULONG)addr)>>16L); X base[2] = (UWORD)(((ULONG)addr)&0x0ffff); X MemCopy(item->Code,&addr[3],item->Length); X ++tag->patches; X break; X } X } X } X lst = lst->next; X } X return any; X} X X X X X X X X X X X X X X X X X X X X X X X X END_OF_FILE if test 5481 -ne `wc -c <'misc.c'`; then echo shar: \"'misc.c'\" unpacked with wrong size! fi # end of 'misc.c' fi if test -f 'other.a' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'other.a'\" else echo shar: Extracting \"'other.a'\" \(4879 characters\) sed "s/^X//" >'other.a' <<'END_OF_FILE' X;====================================================================== X; X; SetCPU V1.60 X; by Dave Haynie, April 13, 1990 X; Released to the Public Domain X; X; OTHER.A MODULE X; X; This module contains miscellaneous assembly functions that just X; didn't seem to fit in elsewhere. X; X;====================================================================== X X include "setcpu.i" X X cseg X X;********************************************************************** X; X; Some useful MMU functions. X; X********************************************************************** X X xdef _SetMMUTag ; Sets up MMU from systag X xdef _FlushATC ; Flush MMU address translation cache X X;====================================================================== X; X; This function cleanly sets up a new MMU context. It accepts a X; valid systag, and will first go to Supervisor more, turn off X; the current MMU setup, then set CRP and finally TC. The reason X; this call is needed is that we need the OS alive to get to X; Supervisor mode. Setting up a new MMU context would normally X; take three calls to Supervisor(), one to turn off the MMU X; (ROM dies...), two to set first the new CRP and then the new X; TC. X; X; void SetMMUTag(struct systag *tag) X; X;====================================================================== X X_SetMMUTag: X move.l 4(sp),a0 ; Get the systag where we can use it X move.l 4,a6 ; Get ExecBase X movem.l a2/a5,-(sp) X move.l a0,a2 X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X movem.l (sp)+,a2/a5 ; Give back registers X rts X1$ X lea.l TAG_TC(a2),a0 ; Get TC register X lea.l TAG_CRP_0(a2),a1 ; Get CRP register X X and.l #$7fffffff,(a0) ; Turn off MMU X PMOVE_ (a0),tc X or.l #$80000000,(a0) X PMOVE_ (a1),crp ; Load up the CRP value X PMOVE_ (a0),tc ; MMU goes back on X rte X X;====================================================================== X; X; This function flushes the MMU Address Translation Cache. X; X; void FlushATC(void) X; X;====================================================================== X X_FlushATC: X move.l 4,a6 ; Get ExecBase X move.l a5,-(sp) X lea.l 1$,a5 ; Get the start of the supervisor code X CALLSYS Supervisor X movem.l (sp)+,a5 ; Give back registers X rts X1$ X PFLUSHA_ ; Flush the ATC X rte X X;********************************************************************** X; X; This section contains the keyboad patch routine. X; X;********************************************************************** X X xdef _KeyCode ; Start of the keyboard patch X xdef _KeyCodeSize ; Size of the keyboard patch X xdef _SetKeyDelay ; Set keyboard count parameter X X;====================================================================== X; X; This is the keyboard delay patch routine. X; X;====================================================================== X XKeyCode: X movem.l d0/d1,-(sp) XKeyOpt: X move.l #12345678,d0 X1$ move.w ANYCREG,d1 X subq.l #1,d0 X bne 1$ X movem.l (sp)+,d0/d1 X rts XKeyCodeEnd: X X;====================================================================== X; X; This function programs the patch delay value. X; X; void SetKeyDelay(ULONG) X; X;====================================================================== X X_SetKeyDelay: X move.l 4(sp),d0 ; Get the delay value X lea KeyOpt,a0 ; Get the location X move.l d0,2(a0) ; Set the value X rts X X_KeyCode: X dc.l KeyCode X_KeyCodeSize: X dc.l KeyCodeEnd-KeyCode+1 X X;********************************************************************** X; X; This section contains the items used for the exception handler. X; X;********************************************************************** X X xdef _BerrCode ; Start of the trap routine X xdef _BerrCodeSize ; Size of the trap routine X X;====================================================================== X; X; This is the exception handler for Bus Errors (level 2). User X; code that misbehaves when the MMU is on can result in such an X; exception. While the code needs to be fixed if this happens, X; it's very possible that the code is not depending on it's random X; action; especially in the case of an accidental write to ROM X; space, which is harmless on a normally configured machine. X; This routine is never directly called by SetCPU. Instead, it's X; copied into memory that's allocated as permanent by SetCPU. X; X;====================================================================== X XSTATUS EQU $0a+4 X XSR_DF EQU 8 X XBerrTrapCode: X move.l d0,-(sp) ; Save d0... X move.w STATUS(sp),d0 ; Fetch exception status register X X bclr.l #SR_DF,d0 ; Clear the data fault bit Xrepair: X move.w d0,STATUS(sp) ; Fix the status word Xdone: X move.l (sp)+,d0 X rte X XBerrTrapEnd: X X;====================================================================== X; X; These give us the size and location of the Bus Error Code. X; X;====================================================================== X X_BerrCode: X dc.l BerrTrapCode X_BerrCodeSize: X dc.l BerrTrapEnd-BerrTrapCode+1 X X end END_OF_FILE if test 4879 -ne `wc -c <'other.a'`; then echo shar: \"'other.a'\" unpacked with wrong size! fi # end of 'other.a' fi if test -f 'reboot.a' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'reboot.a'\" else echo shar: Extracting \"'reboot.a'\" \(5211 characters\) sed "s/^X//" >'reboot.a' <<'END_OF_FILE' X;====================================================================== X; X; SetCPU V1.60 X; by Dave Haynie, April 13, 1990 X; Released to the Public Domain X; X; REBOOT.A MODULE X; X; This module contains functions that do the clever reset magic X; needed for KickStart imaging. X; X;====================================================================== X X include "setcpu.i" X X cseg X X xdef _RAMBoot ; Effects the reboot into a RAM image X xdef _BootCode ; Actual main reboot code X xdef _BootCodeSize ; Size of this magic code X xdef _CleanBoot ; Boot back to system ROM, reset Exec X xdef _ResetCode ; Smart reset routine X xdef _ResetCodeSize ; Size of this magic code X X;====================================================================== X; X; This is the RAMBoot routine as called from C. The C code has X; set up the tag structure with valid MMU data and a pointer to X; the main reset routine in safe memory. The routine will fetch X; the systag from the stack, then call the safe routine in the X; supervisor mode. That call is the last kernal call used; the X; reset routine itself doesn't use any ROM routines, so it can X; safely turn off the MMU before it goes to work, methinks. X; X; void RAMBoot(struct systag *tag, LONG ClearExec,LONG Delay) X; X;====================================================================== X X_RAMBoot: X move.l 4(sp),a2 ; Get the systag where we can use it X move.l 8(sp),d4 ; KeepExec? X move.l 12(sp),d5 ; Delay value X move.l 4,a6 X lea.l TrickyBits,a5 ; Get the supervisor code X CALLSYS Supervisor ; Go to supervisor mode X rts ; We never get here! X X;====================================================================== X; X; This is the start of the supervisor portion of the reboot code. X; This code gets things in the registers the ChipRAM code X; requires, loads up a reset routine into cache, freezes the X; cache, resets, waits for the CIA chips, and then calls the X; ChipRAM code portion which will turn the MMU on and jump to X; ROM's start address. X; X; a2 SetCPU system tag X; a6 ExecBase X; d4 KeepExec Flag X; d5 Boot Delay X; X;====================================================================== X XTrickyBits: X move.l TAG_ROMSTART(a2),a4 ; Get the ROM jump address X move.l TAG_RESETCODE(a2),a3 ; Get the ChipRAM based code X lea.l TAG_CRP_0(a2),a1 ; Get CRP register X lea.l TAG_TC(a2),a0 ; Get TC register X X and.l #$7fffffff,(a0) ; Turn off MMU X PMOVE_ (a0),tc ; -> $f010,$4000 X or.l #$80000000,(a0) ; Prep for startup X PMOVE_ (a1),crp ; -> $f011,$4c00 X X cmp.l #0,d4 ; If asked for, zap ExecBase good X bne 1$ X moveq.l #0,d0 X move.l d0,$4 X1$ X move.l #1,d1 ; Make sure inst cache is on! X MOVEC_ d1,cacr X X move.l #1,d3 ; First pass, no delay X lea.l CacheRun,a6 ; Get the initial branch address X XRSTLoop: X jmp (a6) X XRSTIt: X reset ; Clobber the system X reset X XCacheRun: X move.w ANYCREG,d1 ; Set a spell, take yer shoes off X subq.l #1,d3 X bne CacheRun X move.b #3,$bfe201 ; Turn off Amiga ROM Overlay X move.b #2,$bfe001 X X cmp.l a3,a6 ; Last time through? X beq RSTLoop ; If so, go back X X move.l a3,a6 ; No? Get the address, X move.l d5,d3 ; the delay X move.l #3,d1 ; freeze the cache X MOVEC_ d1,cacr X bra RSTIt ; And Up to the reset stuff X X;====================================================================== X; X; This is the RAM reboot code, which is called to reset the X; system into the new ROM, which is of course now in some magic X; and safe place. The ROM's jump address in in A4 when this X; code is called, and the TC register is in A0. X; X;====================================================================== X XRAMBootCode: X move.l #0,d1 ; Turn all caches off X MOVEC_ d1,cacr X move.l #10,d1 ; Let 'em know we're here X1$ X bchg #1,$bfe001 X move.l #80000,d0 X2$ subq.l #1,d0 X bne 2$ X dbra d1,1$ X X PMOVE_ (a0),tc ; Turn on the MMU X jmp (a4) ; Start up the ROM X nop X nop X nop X nop XRAMBootEnd: X X_BootCode: X dc.l RAMBootCode X_BootCodeSize: X dc.l RAMBootEnd-RAMBootCode+1 X X;====================================================================== X; X; This routine forces a boot back to ROM, clearing out the X; ExecBase and turning off the MMU and caches. X; X; void CleanBoot(void) X; X;====================================================================== X X_CleanBoot: X move.l 4,a6 X X lea 1$,a5 X CALLSYS Supervisor X rts X1$ X move.l #0,(sp) ; Turn off MMU X move.l sp,a0 X PMOVE_ (a0),tc ; -> $f010,$4000 X X move.l #0,d1 ; Turn all caches off X MOVEC_ d1,cacr X X move.l 4,a6 ; Clear out ExecBase X move.l #0,$4 X X move.l $00f80000,d0 ; Which kind of real ROM? X cmp.l #$11144ef9,d0 X beq 2$ X move.l $00fc0004,a0 X bra 3$ X2$ X move.l $00f80004,a0 ; We have a 512K ROM X3$ X reset X reset X jmp (a0) X nop X nop X nop X nop XCleanBootEnd: X X;====================================================================== X; X; Pointers to the smart reset routine, and the length of this X; routine. Currently I'm using the CleanBoot routine, which will X; get the machine back to the ROM OS. A better smart reset routine X; could boot back to the virtual ROM rather than the physcial ROM. X; X;====================================================================== X X_ResetCode: X dc.l _CleanBoot X_ResetCodeSize: X dc.l CleanBootEnd-_CleanBoot+1 X X end END_OF_FILE if test 5211 -ne `wc -c <'reboot.a'`; then echo shar: \"'reboot.a'\" unpacked with wrong size! fi # end of 'reboot.a' fi if test -f 'setcpu.i' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'setcpu.i'\" else echo shar: Extracting \"'setcpu.i'\" \(4271 characters\) sed "s/^X//" >'setcpu.i' <<'END_OF_FILE' X;====================================================================== X; X; SetCPU V1.60 X; by Dave Haynie, April 13, 1990 X; Released to the Public Domain X; X; Assembly Header File X; X; All assembly files need this included X; X;====================================================================== X X;====================================================================== X; X; Macros & constants used herein. The Manx assembler is supposed X; to handle the 68881 and some of the 68020/30 instructions, but X; these macros will help out on older assemblers, and complete the X; set of instructions I need. X; X;====================================================================== X XCALLSYS macro * X jsr LVO\1(A6) X endm X XPMOVE_ macro * X ifc '\1','tc' X ifc '\2','(sp)' X dc.w $f017 ; PMOVE tc,(sp) X dc.w $4200 X mexit X endc X ifc '\2','(a0)' X dc.w $f010 ; PMOVE tc,(a0) X dc.w $4200 X mexit X endc X endc X ifc '\1','crp' X ifc '\2','(a0)' X dc.w $f010 ; PMOVE crp,(a0) X dc.w $4e00 X mexit X endc X endc X ifc '\1','(a0)' X ifc '\2','crp' X dc.w $f010 ; PMOVE (a0),crp X dc.w $4c00 X mexit X endc X ifc '\2','tc' X dc.w $f010 ; PMOVE (a0),tc X dc.w $4000 X mexit X endc X endc X ifc '\1','(a1)' X ifc '\2','crp' X dc.w $f011 ; PMOVE (a1),crp X dc.w $4c00 X mexit X endc X endc X endm XPFLUSHA_ macro * X dc.w $f000 X dc.w $2400 X endm X XMOVEC_ macro * X ifc '\1','cacr' X ifc '\2','d0' X dc.w $4e7a ; MOVEC cacr,d0 X dc.w $0002 X mexit X endc X ifc '\2','d1' X dc.w $4e7a ; MOVEC cacr,d1 X dc.w $1002 X mexit X endc X endc X ifc '\2','cacr' X ifc '\1','d0' X dc.w $4e7b ; MOVEC d0,cacr X dc.w $0002 X mexit X endc X ifc '\1','d1' X dc.w $4e7b ; MOVEC d1,cacr X dc.w $1002 X mexit X endc X endc X ifc '\1','vbr' X ifc '\2','d0' X dc.w $4e7a ; MOVEC vbr,d0 X dc.w $0801 X mexit X endc X endm X XCIB_ENABLE EQU 0 XCIB_FREEZE EQU 1 XCIB_ENTRY EQU 2 XCIB_CLEAR EQU 3 XCIB_BURST EQU 4 X XCDB_ENABLE EQU 8 XCDB_FREEZE EQU 9 XCDB_ENTRY EQU 10 XCDB_CLEAR EQU 11 XCDB_BURST EQU 12 XCDB_WALLOC EQU 13 X XCIB_ENABLE40 EQU 15 XCDB_ENABLE40 EQU 31 X XAFB_68030 EQU 2 XAFB_68040 EQU 3 XAFB_68882 EQU 5 X XATNFLGS EQU $129 X XLVOSupervisor EQU -30 XLVOSuperState EQU -150 XLVOFindTask EQU -294 XLVOAllocTrap EQU -342 XLVOFreeTrap EQU -348 XLVOCacheClearU EQU -636 XLVOCacheControl EQU -648 X XANYCREG EQU $00dff010 X X;====================================================================== X; X; Need just a little more stuff X; X;====================================================================== X X NOLIST X include "exec/types.i" X include "exec/execbase.i" X include "exec/tasks.i" X LIST X X;====================================================================== X; X; The assembly version of my tag structure X; X;====================================================================== X X STRUCTURE TAG,0 X ULONG TAG_TAGSIZE ; Size of this tag X ULONG TAG_PROGVER ; The program version X APTR TAG_MAINTABLE ; The main ROM table X APTR TAG_ROMHI ; The main ROM image X UWORD TAG_ROMTYPE ; Type of MMU ROM X UWORD TAG_PATCHES ; The number of other patches applied X APTR TAG_PATCHLIST ; List of installed patches X APTR TAG_DEVS ; Translated device ROMs X ULONG TAG_TC ; Precomputed TC used for KICK. X ULONG TAG_CRP_0 ; Precomputed CRP used for KICK. X ULONG TAG_CRP_1 X UWORD TAG_CONFIG ; Configuration status. X ULONG TAG_BERRSIZE ; Size of bus error handler. X APTR TAG_OLDBERR ; The old BERR routine. X APTR TAG_BERRHANDLER ; My BERR routine. X SHORT TAG_WRAPUP ; Upper address wrap bound. X SHORT TAG_WRAPDOWN ; Lower address wrap bound. X ULONG TAG_TABLESIZE ; Main table size. X APTR TAG_RESETCODE ; Actual reset routine X ULONG TAG_ROMSIZE ; Size of ROM image X ULONG TAG_ROMLOC ; Where does the fool thing go? X ULONG TAG_ROMSTART ; And where do we start it up? X APTR TAG_ROMLO ; Secondary ROM image, if needed X APTR TAG_SYSSTACK ; Physical system stack image X ULONG TAG_SYSSTKSIZE ; System Stack allocated size X ULONG TAG_RESETSIZE ; Size of the reset code. X APTR TAG_OLDRESET ; Old Reset Code X LABEL TAG_SIZE X X;TAG_TC EQU 28 X;TAG_CRP_0 EQU 32 X;TAG_RESETCODE EQU 62 X;TAG_ROMSTART EQU 74 X X machine mc68020 X mc68881 X END_OF_FILE if test 4271 -ne `wc -c <'setcpu.i'`; then echo shar: \"'setcpu.i'\" unpacked with wrong size! fi # end of 'setcpu.i' fi echo shar: End of archive 1 \(of 4\). cp /dev/null ark1isdone 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.