	title 'RAMDISK - Driver for PROF 80'

        page 56

;	COMMON CODE SEGMENT :
;	=====================

	maclib	cdef		; system definitions

	if 	RAMDISK		; logical, isn't it ?

	public	rdsd0		; link into drive table

	extrn	@dma,@trk,@sect	; r/w parameter
	extrn	@dbnk,@cbnk	; disk bank, current bank
	extrn	cdma		; common DMA buffer
	extrn	@date		; actual date in SCB

	extrn	?bank		; bank switch code
	extrn	?time		; get actual time
	extrn	?move,?xmove	; interbank move code

	maclib	cpm3		; use DR macros

	maclib	z80		; use Z80 opcodes


;	eXtended Disk Parameter Header (XPDH) :
;	=======================================

	dseg

	dw	write
	dw	read
	dw	login
	dw	init
	db	12,0		; relative drive M:
rdsd0:	dph	SVT,dpb0,0	; rest by GENCPM


; 	Disk Parameter Block ( DPB ) :
;	==============================

	cseg

dpb0:	dpb	PSS,PST,TN,BSI,ENT,STO,CSS


;	Automatic Init of Ramdisk :
;	===========================

	dseg

init:	lda	dpb0+13		; possibly system tracks
	sta	@trk		; set directory track
	xra	a		; set sector 0, disk bank 0
	sta	@sect
	sta	@dbnk
	lxi	h,cdma		; set common dma address
	shld	@dma
	call	read		; read this sector into buffer

	lxi	d,rtest		; first entry is label RAMDISK
	lxi	h,cdma
	mvi	b,12

initt:	ldax	d		; testbyte
	cmp	m		; label byte
	jrnz	doinit		; if not equal then init ramdisk
	inx	d		; else next byte
	inx	h
	djnz	initt		; until ready
	ret

rtest:	db	' RAMDISK '	; label entry for ramdisk
	db	'   ',61h	; label=on, access=on, update=on

doinit:	mvi	b,128		; clear dma buffer
	lxi	h,cdma
doinic:	mvi	m,0		; all zeros
	inx	h
	djnz	doinic

	mvi	a,0E5h		; set up 3 dir entrys
	sta	cdma
	sta	cdma+32
	sta	cdma+64

	mvi	a,021h		; set up 1 time entry
	sta	cdma+96

	mvi	a,1		; start with sector 1
	sta	@sect
	lhld	dpb0+7		; calc number of dir records
	srlr	h		; 32 bytes / dir entry
	rarr	l
	srlr	h
	rarr	l
	
doinil:	push	h		; save it
	call	write		; write sector back to ramdisk
	lda	@sect		; next one
	inr	a
	sta	@sect
	pop	h
	dcr	l
	jrnz	doinil		; until all directory records written

	xra	a		; now write sector 0
	sta	@sect

	lxi	h,rtest		; set ramdisk label
	lxi	d,cdma
	lxi	b,13
	ldir

	mvi	c,0		; set actual time in SCB
	call	?time

	lxi	h,@date		; set time entries
	lxi	d,cdma+24
	lxi	b,4
	ldir
	lxi	h,@date
	lxi	b,4
	ldir
	lxi	h,@date
	lxi	d,cdma+97
	lxi	b,4
	ldir
	lxi	h,@date
	lxi	b,4
	ldir

	jr	write		; write sector back


;	log in the drive :
;	==================

login:	ret			; nothing to do


;	CODE ONLY FOR KAYSER RAMDISK :
;	==============================

	if	KAYSER

inop	equ	0B2h		; difference between OTIR and INIR
outop	equ	0B3h


;	write a sector :
;	================

write:	mvi	c,RD$BASIS-9	; ramdisk state register address of card 4
	lda	@trk		; which card ?
	rar			; card-number in bit 5,6 of @trk
	rar
	rar
	cma
	ani	00001100b	; now <A> holds Offset to <C>
	add	c
	mov	c,a		; <C> points to state register of ramcard
	inp	a		; ramdisk protected ?
	bit	1,a
	mvi	a,2		; yes : disk is read-only
	rnz
	mvi	a,outop		; OTIR - opcode 2nd byte
	jr	rwcom

;	read a sector :
;	===============


read:	mvi	a,inop		; INIR - opcode 2nd byte


;	common r/w - code :
;	===================

rwcom:	sta	irloc+1		; set transfer direction
	mvi	c,RD$BASIS-11	; ramdisk track register address of card 4
	lda	@trk		; which card ?
	rar			; card-number in bit 5,6 of @trk
	rar
	rar
	cma
	ani	00001100b	; now <A> holds Offset to <C>
	add	c
	mov	c,a		; <C> points to track register of ramcard
	lda	@trk		; set track & sector register
	outp	a
	lda	@sect
	inr	c		; point to sector register
	outp	a
	lhld	@dma		; set DMA address

	lda	@dbnk		; E := disk-bank
	mov	e,a
	lda	@cbnk		; A := cpu-bank
	cmp	e		; equal ?
	push	psw		; save Z-flag and cpu-bank
	mov	a,e		; A := disk-bank
	jmp	rwbank

	cseg			; bank switch code included

rwbank:	cnz	?bank		; set disk-bank
	dcr	c		; point to data register
	dcr	c
	mvi	b,128		; transfer data
irloc:	outir			; also used as INIR
	pop	psw		; need to switch to old bank ?
	cnz	?bank
	xra	a		; no error
	ret


	endif			; end of if KAYSER


;	CODE ONLY FOR TURBO RAMDISK :
;	=============================

	if	TURBO

	dseg			; we only use move routines

write:	lda	@dbnk		; C := source bank
	mov	c,a
	lda	@trk		; B := dest. bank
	adi	2		; = @trk + 2
	mov	b,a
	call	?xmove		; set xmove banks
	call	getadr		; HL := dest.  address
	lded	@dma		; DE := source address
	lxi	b,128		; physical sector size
	call	?move		; transfer data
	xra	a		; no error
	ret

read:	lda	@dbnk		; B := dest. bank
	mov	b,a
	lda	@trk		; C := source bank
	adi	2		; = @trk + 2
	mov	c,a
	call	?xmove		; set xmove banks
	call	getadr		; HL := source address
	xchg			; DE := source address
	lhld	@dma		; HL := dest.  address
	lxi	b,128		; physical sector size
	call	?move		; transfer data
	xra	a		; no error
	ret
	
getadr:	lxi	h,4000h		; offset for turbo ram
	lda	@sect		; + @sect * 128
	srlr	a		; lsb into carry
	rarr	l		; into L as msb
	add	h		; + turbo ram offset
	mov	h,a		; back into h
	ret
	

	endif			; end of if TURBO

	endif			; end of if RAMDISK

	end
