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.