[comp.sys.atari.st] Ramdisk source

dyer@mudhut.UUCP (Landon Dyer) (10/12/87)

This is a re-posting of a ramdisk in heavy use at Atari.  It has
been modified to work for disk sizes greater than one megabyte. 

Size configuration is done at assembly-time.  It is not reset-
resistant.  If you feel the need to make modifications or add
features, go ahead.

You need MadMAC to assemble this straight out of the box, but
conversion to as68 will not be too hard. 


-------------------------------- cut here --------------------------------
* ramdisk.s

*------------------------------------------------------------------------
*									:
*	ST RAMDISK driver (M:)						:
*	Copyright 1986,1987 Atari Corp.					:
*									:
*	This program is *not* public domain, but you may give it away	:
*	to anyone who wants it.  You may not sell it.			:
*									:
*----------------							:
*	You need MADMAC to assemble this:				:
*									:
*		mac -p ramdisk.s					:
*	    or:								:
*		mac -p -Dramdisk_size=NNN ramdisk.s			:
*									:
*	where 'NNN' is from 1 to 9999, the size of the ramdisk in K.	:
*									:
*----------------							:
*	Stick this program in the \AUTO folder of the boot volume.  Or,	:
*	you can simply double-click it after the desktop comes up. This	:
*	is a pretty vanilla ramdisk --- more embellishments would be	:
*	easy.								:
*									:
*----------------							:
*  9-Aug-1985 lmd	Hacked it up					:
*  9-Jan-1986 lmd	Fixed sign-extension problem in _rw: and added	:
*			conditional assembly for two kinds of ramdisk.	:
*  9-Jan-1986 lmd	Make it "M:"					:
* 16-Apr-1986 lmd	Made it easier to adjust size of ramdisk. Print	:
*			correct size of ramdisk.			:
* 22-Sep-1986 lmd	Handle reads/writes to odd buffer locations.	:
*  6-Feb-1987 lmd	Fixed FAT count, added 2 to account for unused	:
*			clusters 0 and 1.				:
*  9-Sep-1987 lmd	Should work for sizes > 1000K.			:
*									:
*------------------------------------------------------------------------


*+
*  Define the size of the ramdisk and compute its REAL size.
*
*-
	.if !(^^defined ramdisk_size)
ramdisk_size	equ	128		; perceived size, in K
	.endif

FAT_size	= (ramdisk_size + 255 + 2) / 256	; #sectors of FAT
realsize	= ramdisk_size + (FAT_size * 2) + 4	; real size (in K)


*+
*  OS variables and vectors;
*  (stuff we have to subvert.)
*
*-
hdv_init	equ	$46a		; hdv_init()
hdv_bpb		equ	$472		; hdv_bpb(dev)
hdv_rw		equ	$476		; hdv_rw(rw, buf, count, recno, dev)
hdv_boot	equ	$47a		; hdv_boot()
hdv_mediach	equ	$47e		; hdv_mediach(dev)
_drvbits	equ	$4c2		; block device bitVector
_dskbufp	equ	$4c6		; pointer to common disk buffer



*+
*  Install driver;
*  setup ramdisk, then
*  terminate and stay resident.
*
*-
	move.l	4(sp),a4		; a4 -> our basepage
	clr.l	-(sp)			; get superuser mode
	move.w	#$20,-(sp)
	trap	#1
	addq	#6,sp
	move.l	d0,-(sp)		; save old SSP on stack

	bset.b	#4,_drvbits+2		; set bit for M:
	clr.l	a5			; easy zero-based pointer
	move.l	hdv_bpb(a5),o_bpb	; save old disk vectors
	move.l	hdv_rw(a5),o_rw
	move.l	hdv_mediach(a5),o_mediach
	move.l	#hbpb,hdv_bpb(a5)	; install ramdisk's vectors
	move.l	#hrw,hdv_rw(a5)
	move.l	#hmediach,hdv_mediach(a5)

	move.w	#$20,-(sp)		; back to user mode
	trap	#1			; (SSP already on the stack)
	addq	#6,sp

*--- clear FATs and root dir of ramdisk:
	lea	ramdisk(pc),a0
	move.w	#(FAT_size*2 + 4)*128 - 1,d0
clrit:	clr.l	(a0)+
	clr.l	(a0)+
	dbra	d0,clrit

*--- compute size of memory we want to keep:
	move.l	$c(a4),d3		; d3 = size of text
	add.l	$14(a4),d3		; d3 += size of data
	add.l	$1c(a4),d3		; d3 += size of bss
	add.l	#$0100,d3		; d3 += size of basepage
	add.l	#realsize*1024,d3	; d3 += size of ramdisk

	pea	message(pc)		; print something informative
	move.w	#9,-(sp)
	trap	#1
	addq	#6,sp

*--- terminate and stay resident
	clr.w	-(sp)			; return code of zero
	move.l	d3,-(sp)		; # bytes to keep
	move.w	#$31,-(sp)		; Ptermres()
	trap	#1			; do it
	illegal				; "cannot happen"



*+
* LONG hbpb(dev) - return ptr to BPB (or NULL)
*
* Passed:	dev	4(sp).W
*
*-
hbpb:
	move.w	4(sp),d0		; d0 = devno
	move.l	o_bpb,a0		; a0 -> pass-through vector
	lea	_bpb(pc),a1		; a1 -> our handler
	bra	check_dev		; do it


*+
* LONG rw(rw, buf, count, recno, dev)
*
* Passed:	dev	$e(sp).W
*		recno	$c(sp).W
*		count	$a(sp).W
*		buf	6(sp).L
*		rw	4(sp).W
*
*-
hrw:
	move.w	$e(sp),d0		; d0 = devno
	move.l	o_rw,a0			; a0 -> pass-through vector
	lea	_rw(pc),a1		; a1 -> our handler
	bra	check_dev		; do it


*+
* LONG mediach(dev)
*
* Passed:	dev	4(sp).W
*
*-
hmediach:
	move.w	4(sp),d0		; d0 = devno
	move.l	o_mediach,a0		; a0 -> pass-through vector
	lea	_mediach(pc),a1		; a1 -> our handler


*+
* check_dev - use handler, or pass vector through
*
* Passed:	d0.w = device#
*		a0 ->  old handler
*		a1 ->  new handler
*		a5 ->  $0000 (zero-page ptr)
*
* Jumps-to:	(a1) if dev in range for this handler
*		(a0) otherwise
*
*-
check_dev:
	cmp.w	#12,d0			; M:?
	bne	chkd_f			; (no)
	move.l	a1,a0			; yes -- follow success vector
chkd_f:	jmp	(a0)			; do it



*+
* _bpb - return BPB for RAMDISK
*  Synopsis:	LONG _bpb(dev)
*		WORD dev;
*
*  Returns:	NULL, or a pointer to the BPB buffer
*
*-
_bpb:
	move.l	#thebpb,d0
	rts


*+
* _rw - read/write ramdisk sectors
*  Synopsis:	_rw(rw, buf, count, recno, dev)
*
*  Passed:	dev	$e(sp).W
*		recno	$c(sp).W
*		count	$a(sp).W
*		buf	6(sp).L
*		rw	4(sp).W
*
*-
_rw:
	lea	ramdisk(pc),a0		; a0 -> base of ramdisk
	moveq	#0,d0
	move.w	$c(sp),d0		; d0 = sect# << 9
	lsl.l	#8,d0
	lsl.l	#1,d0
	add.l	d0,a0			; a0 -> ramdisk mem

	moveq	#0,d2			; d2 = byte count / 32
	move.w	$a(sp),d2
	lsl.l	#4,d2			; log2(512 / 32) = 4

	move.l	6(sp),a1		; a1 -> buffer
	tst.w	4(sp)			; if (rw) exchange(a0, a1)
	beq.s	rw_1
	exg	a0,a1			; swap src & dest

rw_1:	move.l	a1,d0			; if (odd operation)
	btst	#0,d0			;	then do it slowly
	bne.s	rw_odd

rw_2:	move.l	(a0)+,(a1)+		; move 32 bytes
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	subq.l	#1,d2			; while (--d2)
	bmi.s	rw_q
	bne.w	rw_2
	bra.s	rw_q

rw_odd:	lsl.w	#3,d2			; d2 *= 8 (== count/4)
rw_3:	move.b	(a0)+,(a1)+
	move.b	(a0)+,(a1)+
	move.b	(a0)+,(a1)+
	move.b	(a0)+,(a1)+
	subq.l	#1,d2			; while (--d2)
	bmi.s	rw_q
	bne.w	rw_3

rw_q:	clr.l	d0			; return OK
	rts


*+
* _mediach - return FALSE media change (RAMDISK never changes)
* Synopsis:	_mediach(dev)
*		WORD dev;
*
* Returns:	0L
*
*-
_mediach:
	clr.l	d0
	rts


*+
*  BPB for ramdisk
*
*-
RDLEN	=	4			; root directory size

thebpb:	dc.w	512			; #bytes/sector
	dc.w	2			; #sectors/cluster
	dc.w	1024			; #bytes/cluster
	dc.w	RDLEN			; rdlen (64 files)
	dc.w	FAT_size		; fat size
	dc.w	FAT_size		; 2nd FAT start (no boot sector)
	dc.w	FAT_size*2 + RDLEN	; 1st cluster start
	dc.w	ramdisk_size+2		; #clusters on media
	dc.w	$0001			; flags (16-bit FATs)



o_init:		dc.l	0		; old hdv_init
o_bpb:		dc.l	0		; old hdv_bpb
o_rw:		dc.l	0		; old hdv_rw
o_mediach:	dc.l	0		; old hdv_mediach

;+
;  Sign-on message
;
;-
message:

TMP	set	ramdisk_size
DIV	set	1000
ZFLAG	set	0
    .REPT 4				; loop to generate decimal number
	.IF TMP > DIV
ZFLAG	set	1
	dc.b	TMP / DIV + '0'
TMP	set	TMP % DIV
	.ELSE
	.IIF ZFLAG, dc.b '0' 
	ENDIF
DIV	set	DIV / 10
    .ENDR

	dc.b	'K RAMDISK installed as M:\r\n'
	dc.b	'version 9-Sep-1987 lmd.\r\n',0

    even
ramdisk:	dc.w	0		; beginning of Ramdisk

*---------------- end of ramdisk.s
-- 
Landon Dyer		{ames,hoptoad,imagen,sun}!atari!mudhut!dyer
Cupertino, CA		_____				____________________
			     \_________________________/
I speak for me.		YOW! I am waiting for my warranty-expired interrupt!