;+asm
;add lkopt "SC SD"
;do
;*
;
; ### Ramsey.asm by JM v 1.05b ###
;
; - Created 910813 by JM -
;
;
; Written because SetRamsey seems to be brain dead.
;
; Bugs: Well...
;
;
; Edited:
;
; - 910813 by JM -> v0.01	- Shouldn't take too long.
; - 910813 by JM -> v0.02	- Works but doesn't test for SC RAM yet.
; - 910813 by JM -> v1.00	- Tests for SC RAM and A3000.
; - 910813 by JM -> v1.01	- RAM type and refresh rate output added.
;				- A bug in sctest fixed (always cleared PMODE).
; - 910813 by JM -> v1.02	- New help system installed.
; - 910813 by JM -> v1.03	- An obsolete buffer definition removed.
; - 910816 by JM -> v1.03b	- Disable/Enable moved inside the SC test code.
;				- Debug information added.
; - 910820 by JM -> v1.04b	- Disable/Enable moved out from the SC test
;				  code.  A wait loop added after each write to
;				  RAMSEYCTRL.
; - 910820 by JM -> v1.05b	- One more waitloop added.  Might have caused
;				  problems with non-SC RAM.
;
;

		include	"bb.i"
		include	"exec/types.i"
		include	"exec/execbase.i"
		include	"exec/nodes.i"
		include	"exec/memory.i"
		include	"exec/io.i"
		include	"libraries/dos.i"
		include	"macros.i"
		include	"constants.i"

RAMSEYCTRL	equ	$00de0003
RAMSEYVERS	equ	$00de0043

PMODE		equ	0		; RAMSEY ctrl bits
BMODE		equ	1
WMODE		equ	2

EBUF		equ	512

DEBUG		equ	1

		.var	global
		dlibb	Dos
		dl	cmdlin
		dl	pagerams		; points to first PM RAM found
		dl	clfree

		dw	bf_changed,bf_newbits,show
		dw	ramsvers

		.share	mem,#MEMF_CLEAR!MEMF_PUBLIC
		dm	ebuf[EBUF]

main		.begin
		ra
		clr.b	-1(a0,d0.l)
		move.l	a0,cmdlin
		st	show			; default: show settings

		openlib	Dos,cleanup

		share	mem,cleanup		; get some memory

		move.l	cmdlin,a0
		lea.l	usage(pc),a1
		moveq	#0,d0			; 0 params is ok with us
		call	cmdhelp
		move.l	a1,clfree
		move.l	a0,cmdlin
		tst.l	d0
		beq	cleanup

		ifd	DEBUG
		 lea.s	'Dos opened, mem allocated, cmdline ok',LF,a0
		 call	dpy_msg
		endc

		lea.s	'battmem.resource',a1	; try opening battmem.res
		call	OpenResource
		tst.l	d0
		.if	eq
		 lea.s	'Are you kidding?  Get an Amiga 3000 first!',LF,a0
		 call	dpy_msg
		 bra	cleanup
		.end

		ifd	DEBUG
		 lea.s	'battmem.res opened',LF,a0
		 call	dpy_msg
		endc

		lea	RAMSEYVERS,a0
		bsr	super_r
		move.b	d0,ramsvers
		cmp.b	#$ff,d0
		.if	eq
		 lea.s	'Error: no RAMSEY present.  Get an Amiga 3000.',LF,a0
		 call	dpy_msg
		 bra	cleanup
		.end

		ifd	DEBUG
		 lea.s	'ramsey version read ok',LF,a0
		 call	dpy_msg
		endc

		bsr	check_07_RAM		; see if only SC RAM is present
		move.l	d0,pagerams

		ifd	DEBUG
		 lea.s	'RAM test ok',LF,a0
		 call	dpy_msg
		endc

		move.l	cmdlin,a0		; parse command line
		lea	cmdstrings(pc),a1
		lea	cmdvectors(pc),a2
		sub.l	a3,a3
		move.l	ebuf,d0
		call	parse
		.if	mi
		 move.l	ebuf,a0
		 call	dpy_msg
		 bra	cleanup
		.end

		ifd	DEBUG
		 lea.s	'command line parsed',LF,a0
		 call	dpy_msg
		endc

; Set RAMSEY control register if necessary:

		move.b	bf_changed,d2		; any bits changed?
		.if	ne			; yeah:
		 move.l	pagerams,d0		; page mode RAM installed?
		 .if	ne
		  lea.s	'Error: you have page mode RAM at address $%08lx.',LF,a0
		  call	dpy_msg
		  bra	cleanup
		 .end
		 call	Disable			; disable interrupts
		 lea	RAMSEYCTRL,a0
		 bsr	super_r			; get current bits
		 not.b	d2			; reverse bits
		 and.b	d2,d0			; clr bits that were changed
		 or.b	bf_newbits,d0		; set the ones set
		 move.b	d0,bf_newbits		; save them
		 bsr	ramsctrl_w		; store new bits
		 call	Enable			; enable again
		.end

		ifd	DEBUG
		 lea.s	'RAMSEY mode set',LF,a0
		 call	dpy_msg
		endc

		tst.w	show			; print current settings?
		.if.w	ne			; yup:
		 lea.l	bf_newbits,a3		; 'structure'
		 tst.b	bf_changed		; already set those bits?
		 .if	eq			; nope:
		  lea	RAMSEYCTRL,a0
		  bsr	super_r			; get current bits
		  move.b d0,(a3)		; save bits
		 .end
		 lea	cmdstrings(pc),a0	; source
		 move.l	ebuf,a1			; destination
		 lea	=humtable(pc),a2	; commands
		 bsr	dumpstruct
		 tst.b	(show+1)(a4)		; user gave this cmd?
		 .if	ne			; yes!
		  move.b (a3),d0		; get RAMSEY flags
		  moveq  #3,d3
		  lsr.b  d3,d0
		  and.l  d3,d0
		  lea	 t_rams(pc),a0		; RAM type strings
		  call   strnth			; find DRAM type
		  move.l a0,d2			; ptr to RAM type
		  move.b (a3),d0		; get RAMSEY flags again
		  lsr.b	 #5,d0
		  and.l  d3,d0
		  lea    t_ref(pc),a0		; refresh strings
		  call	 strnth
		  move.l d2,d0
		  move.l a0,d1
		  lea.s  ' (%s DRAMs with %s refresh)',a0
		  call	sformat
		  lea.s	 '%s (rev.%02lx):%s',LF,a0; with user command
		  moveq  #0,d1
		  move.b ramsvers,d1		; get RAMSEY version
		  move.l ebuf,d2		; get buffer
		 .else
		  lea.s	'%s:%s',LF,a0		; with no CMDLIN options
		  move.l ebuf,d1		; get buffer
		 .end
		 lea.s	'RAMSEY',a1		; his name is RAMSEY
		 move.l	a1,d0
		 call	dpy_msg
		.end

cleanup		freesh	mem			; vapautetaan muisti
		move.l	clfree,a0
		call	free

		ifd	DEBUG
		 lea.s	'memory deallocated',LF,a0
		 call	dpy_msg
		endc

		closlib	Dos
		moveq	#0,d0			; virhekoodi = 0
		.end



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

super_r		.local			; read (a0).b -> d0 in SuperState
		.subr	a0/a2/a5
		move.l	a0,a2
		lea	=read(pc),a5
		call	Supervisor
		.end	subr
=read		move.b	(a2),d0
		rte
		.end	local

ramsctrl_w	.local			; write d0.b -> RAMSEYCTRL in SuperState
		.subr	a0/a2/a5/d2
		lea	RAMSEYCTRL,a2
		move.l	d0,d2
		lea	=write(pc),a5
		call	Supervisor
		move.l	d2,d0
		.end	subr
=write		move.b	d2,(a2)		; write
		cmp.b	(a2),d2		; wait until it takes effect
		bne.s	=write
		rte
		.end	local


		.local
check_07_RAM	.subr	d1/a0-a2
		lea	$07000000,a2		; start of RAM (maybe)
=lp		lea.l	64(a2),a1		; skip MemHeader
		call	TypeOfMem		; see if this is RAM
		tst.l	d0
		.if	ne			; yes, there is RAM here
		ifd	DEBUG
		 lea.s	'checking 1MB RAM bank at $%08lx...',LF,a0
		 move.l	a2,d0
		 call	dpy_msg
		endc
		 move.l	a2,a0
		 jsr	test_sc			; see if it's Static Column RAM
		 tst.l	d0
		 bne.s	=next			; yes: check next chunk
		 move.l	a2,d0			; no: return address in d0
		 .exit	subr
		.end
=next		add.l	#$00100000,a2		; next 1 Meg chunk
		cmp.l	#$08000000,a2		; all done?
		blo.s	=lp			; nope, loop
		moveq	#0,d0			; no errors!
		.end	subr
		.end	local


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

		.local
dumpstruct	.subr	d2-d7/a2-a3
		move.l	a0,d6
=loop		moveq	#0,d2
		move.b	(a2)+,d2		; command
		beq	=alldone
		move.b	(a2)+,d3		; bit#
		move.w	(a2)+,d4		; offset

		moveq	#0,d1
		move.b	#' ',(a1)+

		subq.w	#1,d2
		add.w	d2,d2
		lea	=cmds(pc,d2.w),a0
		add.w	(a0),a0
		jsr	(a0)
		bra	=loop

=cmds		dptr	=bitb		; 1
		dptr	=bitw		; 2
		dptr	=bitl		; 3
		dptr	=prtb		; 4
		dptr	=prtw		; 5
		dptr	=prtl		; 6

=bitb		move.w	(a2)+,d0		; # of text
		move.b	0(a3,d4.w),d1
		bra	=do_flags

=bitw		move.w	(a2)+,d0		; # of text
		move.w	0(a3,d4.w),d1
		bra	=do_flags

=bitl		move.w	(a2)+,d0		; # of text
		move.l	0(a3,d4.w),d1
=do_flags	btst	d3,d1
		.if	ne
		 addq.w	#1,d0
		.end
		move.l	d6,a0
		call	strnth
		strcpy	a0,a1
		subq.l	#1,a1
		rts

=prtb		move.b	0(a3,d4.w),d1
		ext.w	d1
		ext.l	d1
		bra.s	=do_prt
=prtw		move.w	0(a3,d4.w),d1
		ext.l	d1
		bra.s	=do_prt
=prtl		move.l	0(a3,d4.w),d1
=do_prt		move.w	(a2)+,d0		; # of text
		move.l	d6,a0
		call	strnth
		move.l	a0,d0
		push	d0-d1/a0-a3
		move.l	a1,a3
		lea.s	'%s=%ld',a0
		move.l	sp,a1
		lea	=putc(pc),a2
		call	RawDoFmt
		pull	d0-d1/a0-a3
=cklen		tst.b	(a1)+
		bne.s	=cklen
		subq.l	#1,a1
		rts

=putc		move.b	d0,(a3)+
		rts
		
=alldone	clr.b	(a1)
		.end	subr
		.end	local


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;		cmd.b,bit.b,offset.w,text.w
=humtable	dc.b	1,0			; page
		dc.w	0,0

		dc.b	1,1			; burst
		dc.w	0,2

		dc.b	1,2			; wrap
		dc.w	0,4

		dc.w	0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cmdstrings	dc.b	'NOPage',0		; 0
		dc.b	'Page',0		; 1
		dc.b	'NOBurst',0		; 2
		dc.b	'Burst',0		; 3
		dc.b	'NOWrap',0		; 4
		dc.b	'Wrap',0		; 5
		dc.b	'Show',0		; 6
		dc.b	0
		ds.w	0

cmdvectors	dptr	cmd_bclr		; nop
		dptr	cmd_bset		; page
		dptr	cmd_bclr
		dptr	cmd_bset		; burst
		dptr	cmd_bclr
		dptr	cmd_bset		; wrap
		dptr	cmd_show
		dc.l	0,0,0

cmd_bclr	lsr.l	#1,d0			; get bit number
		bclr	d0,bf_newbits		; clear this bit
		bset	d0,bf_changed		; set mask bit: bit changed
		moveq	#0,d0
		move.b	d0,show			; do not show
		rts
		
cmd_bset	lsr.l	#1,d0			; get bit number
		bset	d0,bf_newbits		; set this bit
		bset	d0,bf_changed		; set mask bit: bit changed
		moveq	#0,d0
		move.b	d0,show			; do not show
		rts

cmd_show	move.w	#-1,show		; please do show
		moveq	#0,d0
		rts

t_rams		dc.b	'1Mx1',0
		dc.b	'weird',0
		dc.b	'256kx4',0
		dc.b	'1Mx4',0
t_ref		dc.b	'154clk',0
		dc.b	'238clk',0
		dc.b	'380clk',0
		dc.b	'no',0

usage		.text
PAGE/S,NOPAGE/S,BURST/S,NOBURST/S,WRAP/S,NOWRAP/S,SHOW/S: \
\0\\
*** Ramsey v1.05b ***

© 1991 Supervisor Software
Written by JM, August 20, 1991

\CSI\3mBehold also the computers, which though they be so great,
and are driven at fierce clock speeds, yet are they turned about
with very small bits, whithersoever the operator listeth.\CSI\0m

\0\\
 [[NO]Page] [[NO]Burst] [[NO]Wrap] [Show]
\0\\

This command can be used to set and read the RAMSEY DRAM controller
bits on Amiga 3000.

Arguments (lower case chars optional):
 [NO]Page	control page mode operation
 [NO]Burst	control burst mode operation
 [NO]Wrap	control burst wrapping
 Show		list the current RAMSEY settings
\		.end

		.purge


		section	chipperi,code,chip
		.local
test_sc		.subr	d1-d7/a0-a6
		move.l	a0,a2			; address to be tested
		call	Disable
		lea	=test(pc),a5
		call	Supervisor		; execute in Superstate
		call	Enable
		move.l	d2,d0			; flag
		.end	subr

=test		lea	RAMSEYCTRL,a6		; RAMSEY control register
		move.b	(a6),d4			; save ctrl bits
		move.l	a2,a1			; mem being tested
		movem.l	(a1),a2-a5		; save RAM data
=on		bset	#PMODE,(a6)		; turn on PAGE MODE
		beq.s	=on
		movem.l	=testdata(pc),d0-d3	; get data for test
		movem.l	d0-d3,(a1)		; save in RAM being tested
		move.l	a1,a0
=off		bclr	#PMODE,(a6)		; turn off PAGE MODE
		bne.s	=off
		cmp.l	(a0)+,d0		; test if data correct
		bne.s	=error
		cmp.l	(a0)+,d1
		bne.s	=error
		cmp.l	(a0)+,d2
		bne.s	=error
		cmp.l	(a0),d3
		bne.s	=error
		moveq	#1,d2			; flag: SC RAM found
=res		move.b	d4,(a6)			; restore ctrl bits
		cmp.b	(a6),d4
		bne.s	=res			; wait until in effect
		movem.l	a2-a5,(a1)		; restore original data
		rte
=error		moveq	#0,d2			; flag: normal RAM
		bra	=res

=testdata	dc.l	$5ac35ac3
		dc.l	$ac35ac35
		dc.l	$c35ac35a
		dc.l	$35ac35ac

		.end	local

		end


