;
;	gramdisk #1.1 (wiz.) 91-11-25
;

		.model	tiny
		.code
		locals	@@


gramsize	equ	98304			; 96K bytes
gramseg		equ	0a800h
BANK		equ	0a6h

secsize		=	512			; 512 bytes/sector
sectors		=	gramsize/secsize
entries		=	96			; maxfiles in root directory
MDB		=	0ffh


header		dd	-1
		dw	0010000000000000b
		dw	strategy
		dw	interrupt
		db	1

id		db	13,10
		db	'gramdisk #1.1 (wiz.)'
		db	'$',0

BPB		dw	secsize
clstsec		db	1			; [cluster] = [sector]
bootsec		dw	0
FATs		db	1
		dw	entries
		dw	sectors
		db	MDB
FATsec		dw	1

packet		struc
leng		db	?
unit		db	?
command 	db	?
status		dw	?
		db	8 dup (?)
media		db	?
address 	dd	?
count		dw	?
start		dw	?
drive		db	?
packet		ends

pBPB		dw	offset BPB
ppacket 	dd	?

cmdtable	dw	init, mediacheck, buildBPB, cmderror
		dw	read, cmderror, cmderror, cmderror
		dw	write, write, cmderror


strategy	proc far
		mov	word ptr cs:ppacket,bx
		mov	word ptr cs:ppacket[2],es
		ret
strategy	endp


interrupt	proc far
		irp	reg,<ax bx cx dx si di ds es>
		push	reg
		endm
		pushf

		cld
		les	bx,cs:ppacket
		mov	dx,es:[bx.start]
		mov	cx,es:[bx.count]
		lds	si,es:[bx.address]
		mov	al,es:[bx.command]
		mov	word ptr es:[bx.status],100h	; done
		cmp	al,10
		jb	@@1
		mov	al,10
@@1:
		cbw
		shl	ax,1
		mov	di,ax
		call	word ptr cs:cmdtable[di]

		popf
		irp	reg,<es ds di si dx cx bx ax>
		pop	reg
		endm
		ret
interrupt	endp


cmderror	proc
		mov	word ptr es:[bx.status],8103h
		ret
cmderror	endp


mediacheck	proc
		mov	byte ptr es:[bx.address],1
		ret
mediacheck	endp


buildBPB	proc
		mov	word ptr es:[bx.count],offset BPB
		mov	word ptr es:[bx.count][2],cs
		mov	byte ptr es:[bx.media],MDB
		ret
buildBPB	endp


read		proc
		jcxz	@@2
		push	ds
		pop	es
		mov	di,si
@@1:
		cmp	dx,sectors
		jae	nosector
		push	cx
		push	dx
		call	open
		mov	ds,ax
		mov	si,0
		rep	movsw
		call	close
		pop	dx
		inc	dx
		pop	cx
		loop	@@1
@@2:
		ret
read		endp


write		proc
		jcxz	@@2
@@1:
		cmp	dx,sectors
		jae	nosector
		push	cx
		push	dx
		call	open
		mov	es,ax
		mov	di,0
		rep	movsw
		call	close
		pop	dx
		inc	dx
		pop	cx
		loop	@@1
@@2:
		ret
write		endp


nosector	proc
		les	bx,cs:ppacket
		sub	es:[bx.count],cx
		mov	word ptr es:[bx.status],8108h
		ret
nosector	endp


open		proc
		mov	cx,secsize/2
		cli
		mov	al,1
		out	BANK,al
		mov	ax,secsize/16
		mul	dx
		add	ax,gramseg
		ret
open		endp


close		proc
		mov	al,0
		out	BANK,al
		sti
		ret
close		endp


		align	16


breakaddress	=	$


msg		db	'  drive '
drvname 	db	'A:  96k bytes'
		db	13,10,'$'


init		proc
		mov	word ptr es:[bx.address],offset breakaddress
		mov	word ptr es:[bx.address][2],cs
		mov	byte ptr es:[bx.media],1
		mov	al,es:[bx.drive]
		add	cs:drvname,al
		mov	word ptr es:[bx.count],offset pBPB
		mov	word ptr es:[bx.count][2],cs

		mov	dx,sectors
@@1:
		dec	dx
		push	dx
		call	open
		pop	dx
		mov	es,ax
		mov	ax,0
		mov	di,ax
		rep	stosw
		call	close
		or	dx,dx
		jnz	@@1

		call	open
		mov	di,0
		mov	al,MDB
		stosb
		stosb
		stosb
		call	close

		mov	ax,cs
		mov	ds,ax
		mov	ah,9
		mov	dx,offset id
		int	21h
		mov	dx,offset msg
		int	21h
		ret
init		endp


		end
