[comp.sources.amiga] v90i221: SetCPU 1.60 - identify and adjust parameters based on cpu type, Part01/04

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.