	title	'MP/M II V2.0   Disk I/O System'

	public	home,seldsk,settrk,setsec
	public	setdma,read,write,sectran
	extrn	swtuser,swtsys,pdisp,xdos,sysdat

false	equ	0
true	equ	not false

	maclib	z80

;	maclib 	diskdef

	cseg

;Banked	equ	false
;Banked	equ	true

df$drv	equ	0		;default drive
sec$sz	equ	80h		;sector size
fmt$sz	EQU	100h		;format buffer size
n$drvs	equ	4		;number of drives(1-4)

dsk$cmd equ 0D0h 
dsk$sts equ 0D0h 
dsk$drv		equ	0D1h ;drv
dsk$trkL	equ	0D2h ;trkLow
dsk$trkH	equ	0D3h ;trkHigh
dsk$secL	equ	0D4h ;secLow
dsk$secH	equ	0D5h ;secHigh
dsk$dmaL	equ	0D6h ;dmaLow
dsk$dmaH	equ	0D7h ;dmaHigh
dsk$sptL	equ	0D8h ;sptLow
dsk$sptH	equ	0D9h ;sptHigh
dsk$dmaB	equ	0dah ;Disk DMA Bank
dsk$order	equ	0dbh ;track order

cmd$read	equ	1
cmd$write	equ	2
cmd$log		equ	4
cmd$fmt		equ	8

log$dpb	equ	20h		;offset to dpb in buffer
log$ddf	equ	31h		;id sec - flags	

;read sector

read:
	mvi	a,cmd$read
	sta	bt$cmd
	jmp	dsk$ex		;perform operation

;write sector

write:	
	mvi	a,cmd$write
	sta	bt$cmd		;fall through to dsk exec

;disk executive

dsk$ex:
	call	dpb$ad		;de points to dpb
	xchg			;hl ->dpb
	mov	a,m		;sptLow
	out	dsk$sptL
	inx	hl
	mov	a,m		;sptHigh
	out	dsk$sptH
	xra	a
	out	dsk$order	;sides
	lda	bt$dma
	out	dsk$dmaL
	lda	bt$dma+1	
	out	dsk$dmaH
	mvi	a,0ffh
	out	dsk$dmaB	;use default bank
	lda	bt$drv
	out	dsk$drv
	lda	bt$trk
	out	dsk$trkL
	lda	bt$sec
	out	dsk$secL
	call	swtuser		;switch to user bank
	lda	bt$cmd
	out	dsk$cmd
	call	swtsys		;switch to system bank
	in	dsk$sts
	ana	a		;set ccr
	ret

;disk login

dsk$log:
	lda	log$buf
	out	dsk$dmaL
	lda	log$buf+1	
	out	dsk$dmaH
	mvi	a,0ffh
	out	dsk$dmaB	;use default bank
	lda	bt$drv
	out	dsk$drv
	mvi	a,cmd$log
	out	dsk$cmd
	in	dsk$sts
	ana	a		;set ccr
	jnz	dsk$er		;exit error
				;fall though to disk ok	
;disk read write format exits and errors

dsk$ok:	
	xra	a		;clear a to indicate OK
	ret

dsk$er:	
	mvi	a,0FFh		;set a to indicate ERROR
	ret

format:	
	mvi	a,cmd$fmt
	sta	bt$cmd
	call	dsk$ex		;perform operation
	jrz	dsk$ok		;normal exit if write ok
	jr	dsk$er		;exit error

seldsk:	lxi	h,0		;hl = zero if error
	mov	a,c		;put drive number in a
	sta	bt$drv		;store drive number
	cpi	n$drvs		;check if legal drive number
	rnc			;ret if illegal

	mov	a,e		;chk if need log on
	sta	log$rq		;save log on req in log$rq
	
retdsk	lda	bt$drv		;get drv number
	mov	l,a		;l=drive number
	mvi	h,0		;clear h
	dad	h		;*2
	dad	h		;*4
	dad	h		;*8
	dad	h		;*16
	lxi	d,d0$dph	;first dph
	dad	d		;hl=dph of drv number in c
	shld	dt$ptr		;store drive table pointer

;log on set dpb

log$on	lda	log$rq		;check log on req
	ani	01h		;log on bit test
	jrnz	dsk$ok		;already logged on

;read id sector

	call	dsk$log
	jrz	log$ck		;id sector got read
	lxi	h,0		;bad log on hl=0(no Drive table)
	jmp	dsk$er		;exit error

;check if a JADE disk


log$ck	
	lhld	log$buf		;get address of log buffer
	lxi	d,jadeid	;de points to id value
	mvi	b,id$sze	;label size
loop1	ldax	d		;get label character
	cmp	m		;match?
	jrnz	ck1440		;no - go chk for 1440
;	inx	h		;point to next chars
;	inx	d		;
	dcr	b		;dec count of characters
	jrnz	loop1		;again
	jr	yes$id

;check for pc1440 id (3$5 1440)

ck1440	lhld	log$buf	;hl points to sector(id) buffer
	lxi	d,id1440	;de points to id value
	mvi	b,id$sze	;label size
loop2	ldax	d		;get label character
	cmp	m		;match?
	jrnz	lg$type		;no - go chk drive type(no id)
	inx	h		;point to next chars
	inx	d		;
	dcr	b		;dec count of characters
	jrnz	loop2		;again


;diskette contains JADE id or 3$5 1440 id

yes$id	call	dpb$ad		;get dpb address in de
	lxi	b,log$dpb	;offset to dpb in buffer
	lhld	log$buf		;get address of buffer
	dad	b		;hl points to dpb in sector(id) buffer
	lxi	b,dpb$sz	;size of dpb
;	call	block		;move dpb on dd to bios dpb
	ldir
	lxi	d,log$ddf	;
	lhld	log$buf		;get address of dd
	dad	d		;hl points to dpb in sector(id) buffer
	mov	a,m		;get density flags on dd
	ani	04h		;test trk1 density
	cz	tr3740		;if single density use 3740
	cnz	trnone		;no sector translation
	lhld	dt$ptr		;reload ptr to dph table
	jmp	dsk$ok		;return with drv ptr in hl

; chk drive type - 0 or 1 can be 1440's 2 or 3 can be 3740's

lg$type	
;	ifz 	tSec-8		;if tSec is 8 assemble this else assume 1440
;	 lda	bt$drv		;3740 can be in 2 or 3
;	 ani	02h		;test if drive 2 0r 3
;	 jrnz	lg3740		;must be 2 or 3 
;	endif

;assume 1440

lg1440	call	trnone		;no translate 
	call	dpb$ad		;get dpb address in de
	lxi	b,dpb$sz	;size of dpb
	lxi	h,pc$pbk	;hl points to pc 1440 dpb
;	call	block		;move pc 1440 dpb  to bios dpb
	ldir
	lhld	dt$ptr		;reload ptr to dph table
	jmp	dsk$ok		;return with drv ptr in hl

;assume 3740

lg3740	call	tr3740		;translate for 3740
	call	dpb$ad		;get dpb address in de
	lxi	b,dpb$sz	;size of dpb
	lxi	h,sd$pbk	;hl points to single density dpb 3740
;	call	block		;move single dens dpb  to bios dpb
	ldir
	lhld	dt$ptr		;reload ptr to dph table
	jmp	dsk$ok		;return with drv ptr in hl

;set 3740 sector translation

tr3740	lxi	d,sdtran	;single density translation table
	lhld	dt$ptr		;ptr to dph table
	mov	m,e		;put xlat table pointer into dph at 0
	inx	h		;
	mov	m,d		;
	ret

;set no xlation

trnone	xra	a		;zero
	lhld	dt$ptr		;ptr to dph table
	mov	m,a		;put null xlat table pointer into dph at 0
	inx	h		;
	mov	m,a		;
	ret


;get drv par block address

dpb$ad	lhld	dt$ptr		;ptr to dph table
	lxi	d,10		;
	dad	d		;d points to dpb in dph
	mov	e,m		;get dpb from dph at offset 10
	inx	h		;
	mov	d,m		;
	ret


;home drive

home:	mvi	c,0		;set track to 0 fall into settrk

;set track

settrk:	mov	a,c		;track no in a from c
	sta	bt$trk		;store track number
	ret

;set sector

setsec:	mov	a,c		;sector no in a from c
	sta	bt$sec		;store sector number
	ret

;set dma

setdma:	mov	l,c		;just save in bt$dma
	mov	h,b
	shld	bt$dma
	ret

;sector translation

sectran:	mov	a,d		;testing tbl addr
	ora	e		;chk if 0
	jrz	notran		;no xlation
	xchg			;hl=xlat tbl
	dad	b		;hl + sec offset
	mov	l,m		;
	mvi	h,0		;assumed 8 bit sector numbers
	ret	
notran	lxi	h,1		;add one to sector number and ret
	dad	b		
	ret	

;3740 parameters

sdtran:	db	01h,07h,0dh,13h,19h,05h
		db	0bh,11h,17h,03h,09h,0fh
		db	15h,02h,08h,0eh,14h,1ah
		db	06h,0ch,12h,18h,04h,0ah
		db	10h,16h

;default drive parametr block for 3$5" pc1440
;		pc1440
;		IBM PC
pc$pbk:	dw	72		;spt
	db	4		;bsh
	db	15		;blm
	db	0		;exm
	dw	710		;dsm
	dw	255		;drm
	db	0f0h		;al0
	db	0		;al1
	dw	64		;cks
	dw	2		;off

;default drive parametr block for 8" IBM3740

sd$pbk:	dw	26		;spt
	db	3		;bsh
	db	7		;blm
	db	0		;exm
	dw	242		;dsm
	dw	63		;drm
	db	0c0h		;al0
	db	0		;al1
	dw	16		;cks
	dw	2		;off

;bios variable storage

bt$cmd	db	0	;dcm command
bt$drv	db	0	;drive number
bt$trk	db	0	;track number
bt$sec	db	0	;sector number
bt$sp0	db	0	;spare
bt$sp1	db	0	;spare
bt$mod	db	0	;mode controls
bt$sts	db	0	;command status

bt$lad	dw	0	;load address
bt$lng	dw	0	;load length
bt$dma	dw	0	;system tranfer address

dt$ptr	dw	0	;drive table pointer
log$rq	db	0	;log on request

log$buf	dw	log$bf

;id label

id1440:	db	'3.5 1440'

jadeid:	db	'Jade ID ' ;"JADE ID" ?????
id$sze:	equ	$-jadeid

;drive parameter area

d0$dph:	dw	0		;xlat table
	dw	0		;scratch area
	dw	0		;scratch area
	dw	0		;scratch area
	dw	dir$bf		;directory buffer
	dw	d0$dpb		;drive parameter block
	dw	d0$chk		;chk for disk change area
	dw	d0$all		;drive allocation table
d1$dph:	dw	0
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	d1$dpb
	dw	d1$chk
	dw	d1$all
d2$dph:	dw	0
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	d2$dpb
	dw	d2$chk
	dw	d2$all
d3$dph:	dw	0
	dw	0
	dw	0
	dw	0
	dw	dir$bf
	dw	d3$dpb
	dw	d3$chk
	dw	d3$all

eob:	equ	$

;Un-initialized data area

;reserve drive parameter block DPB's

dpb$sz	equ	15	;size of drive parameter block

d0$dpb	ds	dpb$sz	;reserve 15 byte for drive 0
d1$dpb	ds	dpb$sz	;reserve 15 byte for drive 1
d2$dpb	ds	dpb$sz	;reserve 15 byte for drive 2
d3$dpb	ds	dpb$sz	;reserve 15 byte for drive 3

; buffers

log$bf	ds	128
dir$bf	ds	128

; drive allocation area

all$sz equ	91

d0$all	ds	all$sz
d1$all	ds	all$sz
d2$all	ds	all$sz
d3$all	ds	all$sz

;changed disk area

chk$sz	equ	64

d0$chk	ds	chk$sz
d1$chk	ds	chk$sz
d2$chk	ds	chk$sz
d3$chk	ds	chk$sz

eoui	equ	$
