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!