	title 'pc1440 diskette handler'

;    CP/M-80 Version 3     --  Modular BIOS

;	Disk I/O Module for zemu based diskette systems

	dseg

    ; Disk drive dispatching tables for linked BIOS

	public	fdpc0,fdpc1,fdpc2,fdpc3

    ; Variables containing parameters passed by BDOS

	extrn	@adrv,@rdrv
	extrn	@dma,@trk,@sect
	extrn	@dbnk

    ; System Control Block variables

	extrn	@ermde		; BDOS error mode

    ; Utility routines in standard BIOS

	extrn	?wboot	; warm boot vector
	extrn	?pmsg	; print message @<HL> up to 00, saves <BC> & <DE>
	extrn	?pdec	; print binary number in <A> from 0 to 99.
	extrn	?pderr	; print BIOS disk error header
	extrn	?conin,?cono	; con in and out
	extrn	?const		; get console status


    ; Port Address Equates

	maclib ports

    ; CP/M 3 Disk definition macros

	maclib cpm3

    ; Z80 macro library instruction definitions

	maclib z80

    ; common control characters

cr	equ 13
lf	equ 10
bell	equ 7

	;disk constants
dsk.cmd 	equ 	&HD0 
dsk.sts 	equ 	&HD0 
dsk.drv		equ	&HD1 'drv
dsk.trkL	equ	&HD2 'trkLow
dsk.trkH	equ	&HD3 'trkHigh
dsk.secL	equ	&HD4 'secLow
dsk.secH	equ	&HD5 'secHigh
dsk.dmaL	equ	&HD6 'dmaLow
dsk.dmaH	equ	&HD7 'dmaHigh
dsk.sptL	equ	&HD8 'sptLow
dsk.sptH	equ	&HD9 'sptHigh
dsk.dmaB	equ	&hda 'Disk DMA Bank

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

dt.ptr	dw	0
log.buf	dw	eoui
log.dpb	equ	&h20		;offset to dpb in buffer
log.ddf	equ	&H31		;id sec - flags	


    ; Extended Disk Parameter Headers (XPDHs)

	dw	fd$write
	dw	fd$read
	dw	fd$login
	dw	fd$init0
	db	0,0		; relative drive zero
fdpc0	dph     0,dpbpc0,64,91

	dw	fd$write
	dw	fd$read
	dw	fd$login
	dw	fd$init1
	db	1,0		; relative drive one
fdpc1	dph	0,dpbpc1,64,91

	dw	fd$write
	dw	fd$read
	dw	fd$login
	dw	fd$init1
	db	2,0		; relative drive one
fdpc2	dph	0,dpbpc2,64,91

	dw	fd$write
	dw	fd$read
	dw	fd$login
	dw	fd$init1
	db	3,0		; relative drive one
fdpc3	dph	0,dpbpc3,64,91

	cseg	; DPB must be resident

dpbsd	dpb 128,26,77,1024,64,2

dpbpc	dpb 128,72,80,2048,256,2
dpb.sz	equ	$-dpbpc
dpbpc0	dpb 128,72,80,2048,256,2
dpbpc1	dpb 128,72,80,2048,256,2
dpbpc2	dpb 128,72,80,2048,256,2
dpbpc3	dpb 128,72,80,2048,256,2
;id label

id1440	text	"3.5 1440"

jadeid	text	"Jade ID " ;"JADE ID" ?????
id.sze	equ	$-jadeid

	dseg	; rest is banked

sdtran	skew 26,6,1


    ; Disk I/O routines for standardized BIOS interface

; Initialization entry point.

;		called for first time initialization.


fd$init0:
	lxi h,init$table
fd$init$next:
	mov a,m ! ora a ! rz
	mov b,a ! inx h ! mov c,m ! inx h
	outir
	jmp fd$init$next

fd$init1:	; all initialization done by drive 0
	ret

init$table	db 4,p$zpio$1A
		db	11001111b, 11000010b, 00010111b,11111111b
		db 4,p$zpio$1B
		db	11001111b, 11011101b, 00010111b,11111111b
		db 0


; disk READ and WRITE entry points.

		; these entries are called with the following arguments:

			; relative drive number in @rdrv (8 bits)
			; absolute drive number in @adrv (8 bits)
			; disk transfer address in @dma (16 bits)
			; disk transfer bank	in @dbnk (8 bits)
			; disk track address	in @trk (16 bits)
			; disk sector address	in @sect (16 bits)
			; pointer to XDPH in <DE>

		; they transfer the appropriate data, perform retries
		; if necessary, then return an error code in <A>




;disk executive

common:
	sded	dt.ptr
	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
	lda	@dma
	out	dsk.dmaL
	lda	@dma+1	
	out	dsk.dmaH
	lda	@dbnk	
	out	dsk.dmaB
	lda	@rdrv
	out	dsk.drv
	lda	@trk
	out	dsk.trkL
	lda	@trk+1
	out	dsk.trkH
	lda	@sec
	out	dsk.secL
	lda	@sec+1
	out	dsk.secH
	ret

;read sector

fd$read:
	call	common		;perform common
	mvi	a,cmd.read
	out	dsk.cmd
	in	dsk.sts
	ret

;write sector

fd$write:	
	call	common		;perform common
	mvi	a,cmd.write
	out	dsk.cmd
	in	dsk.sts
	ret

;disk read write format exits and errors

;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

fd$login:
		; This entry is called when a logical drive is about to
		; be logged into for the purpose of density determination.

		; It may adjust the parameters contained in the disk
		; parameter header pointed at by <DE>

;read id sector
	sded	dt.ptr
	lda	log.buf
	out	dsk.dmaL
	lda	log.buf+1	
	out	dsk.dmaH
	lda	@rdrv
	out	dsk.drv
	mvi	a,0ffh
	out	dsk.dmaB
	mvi	a,cmd.log
	out	dsk.cmd
	in	dsk.sts
	ana	a		;set ccr
	jrz	log.ck		;id sector got read
	lxi	h,0		;bad log on hl=0(no Drive table)
	jmp	lg1440		;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
looplg	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	looplg		;again
	jmpr	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
loopck	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	loopck		;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	&H04		;test trk1 density
	cz	tr3740		;if single density use 3740
	cnz	trnone		;no sector translation
	ret			;return 

; 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	&h02		;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,dpbpc		;hl points to pc 1440 dpb
;	call	block		;move pc 1440 dpb  to bios dpb
	ldir
	ret			;return 

;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,dpbsd		;hl points to single density dpb 3740
;	call	block		;move single dens dpb  to bios dpb
	ldir
	ret			;return 

;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

	end
