;======================================================================
;
;	SetCPU V1.60
;	by Dave Haynie, April 13, 1990
;	Released to the Public Domain
;
;	OTHER.A MODULE
;
;	This module contains miscellaneous assembly functions that just
;	didn't seem to fit in elsewhere.
;
;======================================================================

	include "setcpu.i"

	cseg

;**********************************************************************
;
;	Some useful MMU functions.
;
**********************************************************************

	xdef	_SetMMUTag	; Sets up MMU from systag
	xdef	_FlushATC	; Flush MMU address translation cache

;======================================================================
;
;	This function cleanly sets up a new MMU context.  It accepts a
;	valid systag, and will first go to Supervisor more, turn off
;	the current MMU setup, then set CRP and finally TC.  The reason
;	this call is needed is that we need the OS alive to get to
;	Supervisor mode.  Setting up a new MMU context would normally
;	take three calls to Supervisor(), one to turn off the MMU
;	(ROM dies...), two to set first the new CRP and then the new
;	TC.
;
;	void SetMMUTag(struct systag *tag)
;
;======================================================================

_SetMMUTag:
	move.l	4(sp),a0		; Get the systag where we can use it
	move.l	4,a6			; Get ExecBase
	movem.l	a2/a5,-(sp)
	move.l	a0,a2
	lea.l	1$,a5			; Get the start of the supervisor code
 	CALLSYS	Supervisor
	movem.l	(sp)+,a2/a5		; Give back registers
	rts
1$
	lea.l	TAG_TC(a2),a0		; Get TC register
	lea.l	TAG_CRP_0(a2),a1	; Get CRP register

	and.l	#$7fffffff,(a0)		; Turn off MMU
	PMOVE_	(a0),tc	
	or.l	#$80000000,(a0)
	PMOVE_	(a1),crp		; Load up the CRP value
	PMOVE_	(a0),tc			; MMU goes back on
	rte

;======================================================================
;
;	This function flushes the MMU Address Translation Cache.
;
;	void FlushATC(void)
;
;======================================================================

_FlushATC:
	move.l	4,a6			; Get ExecBase
	move.l	a5,-(sp)
	lea.l	1$,a5			; Get the start of the supervisor code
	CALLSYS	Supervisor
	movem.l	(sp)+,a5		; Give back registers
	rts
1$
	PFLUSHA_			; Flush the ATC
	rte

;**********************************************************************
;
;	This section contains the keyboad patch routine.
;
;**********************************************************************

	xdef	_KeyCode	; Start of the keyboard patch
	xdef	_KeyCodeSize	; Size of the keyboard patch
	xdef	_SetKeyDelay	; Set keyboard count parameter

;======================================================================
;
;	This is the keyboard delay patch routine. 
;
;======================================================================

KeyCode:
	movem.l	d0/d1,-(sp)
KeyOpt:
	move.l	#12345678,d0
1$	move.w	ANYCREG,d1
	subq.l	#1,d0
	bne	1$
	movem.l	(sp)+,d0/d1
	rts
KeyCodeEnd:

;======================================================================
;
;	This function programs the patch delay value.
;
;	void SetKeyDelay(ULONG)
;
;======================================================================

_SetKeyDelay:
	move.l	4(sp),d0		; Get the delay value
	lea	KeyOpt,a0		; Get the location
	move.l	d0,2(a0)		; Set the value
	rts

_KeyCode:
	dc.l	KeyCode
_KeyCodeSize:
	dc.l	KeyCodeEnd-KeyCode+1

;**********************************************************************
;
;	This section contains the items used for the exception handler.
;
;**********************************************************************

	xdef	_BerrCode	; Start of the trap routine
	xdef	_BerrCodeSize	; Size of the trap routine

;======================================================================
;
;	This is the exception handler for Bus Errors (level 2).  User
;	code that misbehaves when the MMU is on can result in such an
;	exception.  While the code needs to be fixed if this happens, 
;	it's very possible that the code is not depending on it's random
;	action; especially in the case of an accidental write to ROM
;	space, which is harmless on a normally configured machine.
;	This routine is never directly called by SetCPU.  Instead, it's
;	copied into memory that's allocated as permanent by SetCPU.
;
;======================================================================

STATUS	EQU	$0a+4

SR_DF	EQU	8

BerrTrapCode:
	move.l	d0,-(sp)		; Save d0...
	move.w	STATUS(sp),d0		; Fetch exception status register

	bclr.l	#SR_DF,d0		; Clear the data fault bit
repair:
	move.w	d0,STATUS(sp)		; Fix the status word
done:
	move.l	(sp)+,d0
	rte

BerrTrapEnd:

;======================================================================
;
;	These give us the size and location of the Bus Error Code.
;
;======================================================================

_BerrCode:
	dc.l	BerrTrapCode
_BerrCodeSize:
	dc.l	BerrTrapEnd-BerrTrapCode+1

	end
