; *****************************************************
; *						      *
.Title	'apposite designs CP/M cbios  --  vers 2.21t'
; *						      *
; *	Copyright 1983 by	apposite designs      *
; *				Berkeley, Ca.	      *
; *	All rights reserved			      *
; *						      *
; *	   	- biosvers.asm -		      *
; *						      *
; *****************************************************

  .ident	AD4DMS
	.pabs
	.phex

	.loc	100h


version		==	22	; CP/M  version
level		==	01	; CBIOS version
rev		==	't'	; CBIOS revision


;	last modified>	28nov83	   joel wittenberg


.page
; *****************************************************
; *		system equates			      *
; *		- system  .equ -		      *
; *****************************************************

false		==	0
true		==	#false

bell		==	07
cr		==	0Dh
lf		==	0Ah

WarmVec		==	0000	; warm boot vector
BdosVec		==	0005	; bdos entry vector
 
RecSize		==	128

;	-- temporary equates --

SysMode		==	0000
MoveData	==	0000
PrtMsg		==	0000
PrtBuf		==	0000
Wait4user	==	0000
WrUnAlloc	==	0000

;	-- Page Zero Definitions --

ccpDSK		==	4	; address of cur disk
DefaultBuf	==	80h	; default record buffer
.page
; ***********************************************
; *		disk  constants			*
; *		- blocki/o.equ -		*
; ***********************************************

;	Disk Input / Output port assignments

flpBase		==	0C0h		; FDC Base port
flpStatus	==	flpBase		; Status reg
flpData		==	flpBase+1	; Data register
flpDmaAdr	==	flpBase+2	; set Dma adr
flpIntPort	==	flpBase+2	; read Status

;	Flop Controller function definitions

flpSpec		==	03	; Specify
flpSDS		==	04	; Sense Drive status
flpWRdata	==	05	; Write data
flpRDdata	==	06	; Read data
flpRecal	==	07	; recalibrate
flpSIS		==	08	; Sense Interrupt status
flpRDid		==	10	; Read ID
flpSeek		==	15	; Seek
flpMFM		==	40h	; double density bit

lenSpec		==	3	; length of flop cmds
lenSDS		==	2
lenMax		==	9
lenReCal	==	2
lenSIS		==	1
lenRdId		==	2
lenSeek		==	3
lenStatus	==	7

;	Disk drive constants

MaxRetry	==	10	; disk retry count

OneSided	==	0
TwoSided	==	1

dsk128		==	0	; the NEC 765 returns
dsk1024		==	3	; these for the density

s128dsm		==	((77-2)   *26)/08
d128dsm		==	((77-2)*2 *26)/16
s1024dsm	==	((77-2)   *64)/16
d1024dsm	==	((77-2)*2 *64)/16
.page
; *****************************************************
; *		XTL, DPH, DPB, TABLES		      *
; *		- tables  .dsk -		      *
; *****************************************************

xltMap:	
	.word	xlt128		; FM 128  b/sec
	.word	0		; not used
	.word	0		; not used
	.word	xlt1024		; MFM 1024 b/sec



; **
; **		Sector Translation Tables
; **		-------------------------
; **

xlt128:	
	.byte	01,07,13,19,25,05,11,17,23,03,09,15,21
	.byte	02,08,14,20,26,06,12,18,24,04,10,16,22



xlt1024:	
	.byte	01,02,03,04,05,06,07,08
	.byte	25,26,27,28,29,30,31,32
	.byte	49,50,51,52,53,54,55,56
	.byte	09,10,11,12,13,14,15,16
	.byte	33,34,35,36,37,38,39,40
	.byte	57,58,59,60,61,62,63,64
	.byte	17,18,19,20,21,22,23,24
	.byte	41,42,43,44,45,46,47,48
.page
; **
; **		Disk Parameter Headers
; **		----------------------
; **

ndisks	=	0	; number of disks

dphBase:

;	--------	drive A:	--------	;

	.word	xlt1024		; sector translate adr
	.word	0,0,0		; bdos workspace
	.word	DirBuf		; dir buf adr
	.word	s1kdpb		; dpb adr
	.word	CkVec0		; dir check vector adr
	.word	AlVec0		; block alloc vector

ndisks	=	ndisks+1



;	--------	drive B:	--------	;

	.word	xlt1024		; sector translate adr
	.word	0,0,0		; bdos workspace
	.word	DirBuf		; dir buf adr
	.word	s1kdpb		; dpb adr
	.word	CkVec1		; dir check vector adr
	.word	AlVec1		; block alloc vector

ndisks	=	ndisks+1


.page
; **
; **		Disk Parameter Blocks
; **		---------------------
; **

dpbMap:
	.word	s128dpb		; single sided
	.word	d128dpb		; double sided
	.word	0,0		; not using 256 b/sec
	.word	0,0		; not using 512 b/sec
	.word	s1kdpb		; single sided
	.word	d1kdpb		; double sided


; ++	Disk Parameter Tables

  ; Single density, single sided --  128 b/sec
	.byte	OneSided	; 1 or 2 sided value
	.byte	dsk128		; disk density
s128dpb:
	.word	26		; records/track
	.byte	3,7,0		; bsh,blm,exm
	.word	s128dsm-1	; dsm
	.word	64-1		; drm
	.byte	0c0h,0		; size of alloc vector
	.word	(64+3)/4	; size of check vector
	.word	2		; track offset

  ; Single density, double sided --  128 b/sec
	.byte	TwoSided	; 1 or 2 sided value
	.byte	dsk128		; disk density
d128dpb:
	.word	26		; records/track
	.byte	3,7,0		; bsh,blm,exm
	.word	d128dsm-1	; dsm
	.word	128-1		; drm
	.byte	0f0h,0		; size of alloc vector
	.word	(128+3)/4	; size of check vector
	.word	4		; track offset

  ; Double density, single sided -- 1024 b/sec
	.byte	OneSided	; 1 or 2 sided value
	.byte	dsk1024		; disk density
s1kdpb:
	.word	8*8		; records/track
	.byte	4,15,0		; bsh,blm,exm
	.word	s1024dsm-1	; dsm
	.word	128-1		; drm
	.byte	0c0h,0		; size of alloc vector
	.word	(128+3)/4	; size of check vector
 	.word	2		; track offset

  ; Double density, double sided -- 1024 b/sec
	.byte	TwoSided	; 1 or 2 sided value
	.byte	dsk1024		; disk density
d1kdpb:
	.word	8*8		; records/track
	.byte	4,15,0		; bsh,blm,exm
	.word	d1024dsm-1	; dsm
	.word	256-1		; drm
	.byte	0f0h,0		; size of alloc vector
	.word	(256+3)/4	; size of check vector
 	.word	4		; track offset

.page
; *****************************************************
; *	    S E L E C T   D I S K   D R I V E	      *
; *		   - selfuncs.asm -		      *
; *****************************************************
;
;	Select a disk drive for subsequent data
;	transfers and return the appropriate DPH adr.
;	This routine determines the correct format and
;	initializes the DPB with the appropriate values
;	for the format type.
;
; entry>	 c = drive number
;	    de lsb = 0, must find type
;	    de lsb = 1, type is known
; exit>		hl = 0 if drive not selectable
;		hl = dph(xlt) if selectable
; used>		all
selDSK:
	mov	a,c
	cpi	ndisks
	jc	getDph	; legal drive request
;
SelErr:
	lxi	h,0	; - no such drive
	xra	a	; force drive 0
	sta	ccpDSK	; since selection
	ret		; is in error
;
getDph:
	sta	cpmDisk
	push	d	; save selection request
	mov	l,c
	mvi	h,0	
	dad	h	; *2
	dad	h	; *4
	dad	h	; *8
	dad	h	; *16
	lxi	d,dphBASE
	dad	d	; hl = .dph(xlt)
;
	lxi	d,10	; adrDPB is DPH+10
	xchg		; de = .dph(xlt)
	dad	d	; hl = .dph(dpb)
	mov	a,m
	inx	h
	mov	h,m
	mov	l,a	; hl = .dpb
	xchg		; de = .dpb, hl = .dph(xlt)
	dcx	d	; de = .dpb(type)
	ldax	d	; density
	sta	cpmDens
	dcx	d
	ldax	d	; 1 or 2 sided flag
	sta	cpm2side
	pop	d	; drive selection request
	mov	a,e
	rrc		; lsb = selection bit
	rc		; type is known so return

;
;    ++  disk type must be determined  ++
;    ------------------------------------

	push	h	; hl = .dph(xlt)
	call	FindType;  a = disk type
;
	mov	e,a
	mvi	d,0
	lxi	h,dpbMap
	dad	d
	dad	d
	mov	e,m
	inx	h
	mov	h,m
	mov	l,e	; hl = .dpb(sel)
	xchg		; de = .dpb(curType)
;
	pop	h
	push	h	; hl = .dph(xlt)
	lxi	b,10
	dad	b	; hl = .dph(dpb)
	mov	m,e
	inx	h
	mov	m,d	; set new dph(dpb)
	ani	06	; a = type, lsb = 2 sided bit
	mov	e,a
	mvi	d,0
	lxi	h,xltMap
	dad	d	; hl = adr of new xlt table
	xchg		; de = adr of new xlt table
	pop	h	; hl = .dph(xlt)
	ldax	D
	mov	m,a
	inx	h	; set new translate table adr
	inx	d	; into the DPH
	ldax	d
	mov	m,a
	dcx	h
	ret
.page
;
;-------
;	set cpmTRK to zero and flush the disk buffers.
Home:
	lxi	h,0
	shld	cpmTRK
;
FlushBufs:
	call	flushACT
	lxi	h,ActDisk
	mvi	m,0ffh	; mark buffer as invalid
	ret
;
;-------
; entry>	bc = track number
; exit>		none
setTRK:
	mov	l,c
	mov	h,b
	shld	cpmTRK
	ret
;
;-------
; entry>	bc = record number
; exit>		none
setREC:
	mov	a,c
	sta	cpmREC		; sector to seek
	ret
;
;-------
; entry>	bc = dma address
; exit>		none
setDMA:
	mov	h,b
	mov	l,c
	shld	adrUSRdma
	ret
;
;-------
;	Translate sector number from logical to physical.
; entry>	de = 0, no translation required.
;		de = translation table address.
;		bc = sector number to translate.
; exit>		hl = translated sector.
secTRAN:
	mov	a,d
	ora	e
	jnz	trans
;		
	inx	b	; bdos rec# is relative to zero
	mov	l,c	; physical sectors start w/one
	mov	h,b
	ret	
;
trans:
	xchg
	dad	b
	mov	l,m
	mvi	h,0
	ret
.page
; *****************************************************
; *		deblocking routines		      *
; *		- deblock .asm -		      *
; *****************************************************
;
;-------
; entry>	none
; exit>		a  = read flag
read:
	mvi	a,0ffh	; mark transfer as read
	jmp	transfer
;
;-------
; entry>	c  = write type
; exit>		a  = write flag
write:
	mov	a,c	; bdos passes write type in 'c'
	sta	WrType
	xra	a	; mark transfer as write
;
;-------
; entry>	a = transfer direction
; exit>		xfer primitive
transfer:
	sta	RDorWR		; store transfer flag
	lxi	h,RetryCnt
	mvi	m,MaxRetry	; init retry counter
;
	call	CheckAct	; see if it's in a buf
	jz	InActBuf
;
	call	FlushAct
	lhld	cpmType		; selected dens/2sided
	lda	cpmTrk		; check for track zero
	ora	a
	jnz	SetType
;
	lxi	h,0		; track 0 is FM, 1sided
SetType:
	shld	CurType		; select -> physical
	call	SetAct		; cp/m desc -> act desc
	call	qReadReq	; read/write/unalloc'd
	cnz	ReadFlop	; read unless unAlloc

InActBuf:
	lhld	AdrUsrDma
	xchg			; de = .user buffer
	call	GetBufDisp	; bc = byte offset
	lhld	AdrCurBuf	; hl = .dsk buf
	dad	b		; hl = .dsk buf(offset)
	lxi	b,RecSize	; bc = record size
	lda	RDorWR		; read/write flag
	ora	a
	jz	WriteBuf

ReadBuf:
	call	MoveData
	xra	a		; ret success to cp/m
	ret

WriteBuf:
				; hl = adr(user buf)
	xchg			; de = adr(disk buf)
	call	MoveData
	mvi	a,0ffh
	sta	ActDirty
	xra	a		; ret success to cp/m
	ret

;
;-------
; entry>	none
; exit>		Z set if request is in the buffer
CheckAct:
	lxi	h,ActDisk
	lxi	d,cpmDisk
	ldax	d	; de = adr cpm disk
	cmp	m
	rnz
;
	inx	h	; hl = adr act(x)track
	inx	d	; de = adr cpm trk(low)
	ldax	d
	cmp	m
	rnz
;
	inx	h	; hl = adr act(x)sec
	inx	d	; skip cpm track(high)
	inx	d	; de = adr cpm sec
;
	lda	CurDens
	ora	a
	ldax	d	; a = cpmSec
	jz	ckSec
;
	dcr	a	; force to 8 rec boundary
	ani	0f8h
	inr	a
;
ckSec:
	cmp	m
	ret
;
;-------
; entry>	none
; exit>		flushes all dirty bufs
FlushAct:
	lxi	h,ActDirty
	mov	a,m		; ActDirty says
	ora	a		; 'do nothing till
	rz			;  you hear from me'
;
	mvi	m,0		; clear dirty flag and
	jmp	WriteFlop	; write buffer to disk
;
;-------
; entry>	none
; exit>		Z set if read is not req'd
qReadReq:
	lda	RDorWR		; reads all require 
	ora	a		; filling the buffer
	rnz
;
	lda	curDens		; don't pre-read on
	ora	a		; single density writes
	rz
;
	lda	WrType		; don't pre-read on
	cpi	WrUnAlloc	; writes to previously
	ret			; unallocated blocks
;
;-------
; entry>	none
; exit>		none
SetAct:
	lhld	cpmDisk
	shld	ActDisk	; set disk and track
	lxi	h,cpmRec
	lda	CurDens
	ora	a	; check current density
	mov	a,m	; a = cpmRec
	jz	SetSec	; if single density
;
	dcr	a	; if double density then
	ani	0f8h	; set to 8 rec boundary
	inr	a
SetSec:
	sta	ActRec	; set sec
	ret
;
;------
; entry>	none
; exit>		bc = byte offset into disk buffer
GetBufDisp:
	lxi	h,ActRec
	lda	cpmRec
	sub	m
	rar
	mov	b,a
	mvi	c,0
	rnc
;
	mvi	c,80h
	ret
.page
; *************************************************
; *	CompuPro Disk1 specific routines	  *
; *	      - flopdrvr.asm -			  *
; *************************************************

;-------
; entry>	none
; exit>		retry upon error
ReadFlop:
	call	StartFlop	; setup and seek
	mvi	c,flpRdData
	call	ExecFlop
	rz			; function successful
;
	call	FindErr		; parse error
	jmp	ReadFlop
;
;-------
; entry>	none
; exit>		retry upon error
WriteFlop:
	call	StartFlop	; setup and seek
	mvi	c,flpWrData
	call	ExecFlop
	rz			; function successful
;
	call	FindErr		; parse error
	jmp	WriteFlop
;
;-------
; entry>	c = read/write opcode
;		used by warm,Read,Write
; exit>		Z set if transfer good
ExecFlop:
	lda	curDens
	ora	a
	mov	a,c
	jz	setOpCode
;
	ori	flpMFM
setOpCode:
	lxi	h,flopCmd
	mov	m,a
	mvi	b,lenMax
	call	command	; send flop disk command
	call	wait4int; wait for status available
	call	results	; and get the results
;
	lda	flopStat
	ani	0f8h
	cpi	40h	; return if not possibly
	rnz		; an End of Track error 
;
	lda	flopStat+1
	cpi	80h	; xfer was good if err
	ret		; is end of track error
;
;-------
; entry>	none
; exit>		none
StartFlop:
	call	adr2fdc	; set Disk1 dma address
	call	SetParams
;			; fall through to seek
;-------
; entry>	none
; exit>		none
Seek:
	lxi	h,flopCmd
	mvi	m,flpSeek
	mvi	b,lenSeek
	call	command
	call	sense	; rets a = status code
	ani	0f8h	; mask head and unit
	cpi	20h	; seek done bit
	rz		; seek successful
;
	call	ReHome	; recalibrate
	jmp	Seek	; re-seek
;
;-------
; entry>	none
; exit>		none
adr2fdc:
	lda	dmaBANK
	out	flpDmaAdr	; msb first
	lhld	AdrCurBuf
	mov	a,h		; middle next
	out	flpDmaAdr
	mov	a,l		; lsb last
	out	flpDmaAdr
	ret
;
;-------
; entry>	none
; exit>		none
SetParams:
	lxi	h,ActTrk	; hl = .ActTrk
	lda	cur2side	; 1 or 2 sided flag
	ora	a
	mov	a,m		; a = ActTrk
	mvi	b,0		; default to side 0
	jz	SetTrack	; not double-sided
;
	rar			; flopTrk = cpmTRK/2
	jnc	SetTrack	; side = 0 if track even
;
	inr	b		; side = 1 if track odd
SetTrack:
	sta	flopTrk		; set track
	mov	a,b
	sta	flopSide	; set side
;
	rlc
	rlc			; head bit of drive byte
	dcx	h		; hl = .ActDsk
	ora	m		;  a = Side <OR> ActDsk
	sta	flopDsk
	inx	h
;
	inx	h		; hl = .ActRec
	lda	curDens		;  a = cur density(0-3)
	sta	flopDen		; set flop cmd(density)
	ora	a
	mov	a,m
	jz	SetFlopSec
;
	dcr	a		; 8 cp/m records
	rar			; per physical sector
	rar			; so divide cpmRec by 8
	rar			; - cpmRec starts w/1
	inr	a		; due to SecTrans
;
SetFlopSec:
	ani	1fh
	sta	flopSec
	sta	flopMax
;				; fall thru to GPL,DTL
;-------
; entry>	none
;		- used by warm boot code
; exit>		none
setGPLDTL:
	lxi	h,GapDataLen
	lda	curDens
	mov	e,a
	mvi	d,0
	dad	d
	dad	d
	lxi	d,flopGap
	mov	a,m
	stax	d	; GPL
	inx	d
	inx	h
	mov	a,m
	stax	d	; DTL
	ret
;
;-------
;	recalibrate selected drive
; entry>	none
; exit>		retry upon error
ReHome:
	lxi	h,flopDsk
	lda	cpmDisk
	mov	m,a
	dcx	h		; hl = .flopCmd
	mvi	m,flpReCal
	mvi	b,lenReCal
	call	command		; send calibrate cmd
	call	sense		; rets a = status code
	ani	0f8h		; mask head and unit
	cpi	20h		; seek done bit
	rz			; reCalibrate was good
;
	lxi	h,RetryCnt
	dcr	m		; try again for 
	jnz	ReHome		; MaxRetry times
;
	lxi	h,badHOME	; admit failure
	lda	flopDsk
	adi	'A'		; make drive# printable
	sta	HomeDsk
	call	DoPrompt
	jmp	ReHome
;
;-------
; entry>	none
; exit>		a = flop status
Sense:
	call	wait4int	; no status till int
	lxi	h,flopCmd
	mvi	m,flpSIS
	mvi	b,lenSIS
	call	command		; send sense int cmd
	call	results		; get the results
;
	lda	flopStat
	mov	b,a		; save st0 (status byte)
	lxi	h,flopDsk	; ensure status is
	xra	m		; for current disk
	ani	3		; only check unit#
	jnz	sense		; retry if not current
;
	mov	a,b		; restore st0
	ani	0d8h		; check for sense error
	mov	a,b		;  a = st0 (for caller)
	rz
;
	ani	10h		; ret err if drive or
	rnz			; recalibrate failure
;
	mov	a,b
	ani	08		; give a generic error
	jz	NotKnown	; message unless the
;				; drive is not ready
;-------
DrvNotReady:
	lda	flopDsk
	adi	'A'
	sta	NRdsk
	lxi	h,NotReady
	jmp	DoPrompt
;
;-------
; entry>	none
; exit>		a = curTYPE
FindType:
	call	SenseDrive	; sets cpm2side byte
	call	ReHome		; recalibrate drive
;
	mvi	a,1
	sta	flopTrk
	call	Seek
	call	ReadId
	lda	flopStat+6	; density, 0-3
	sta	cpmDens
	rlc
	lxi	h,cpm2side
	ora	m		; ret a = dens/side
	ret
;
;-------
; entry>	none
; exit>		sets cpm double-sided flag
SenseDrive:
	call	IsDrvReady	; the nec 765 sometimes
	cz	IsDrvReady	; falsely reports not
	jnz	get2sided	; ready the 1st time
;
	call	DrvNotReady
	jmp	SenseDrive
;
get2sided:
	mov	a,b
	ani	08		; 2 sided bit
	rrc
	rrc
	rrc
	sta	cpm2side
	ret
;
;-------
; entry>	none
; exit>		Z set if drive is not ready
IsDrvReady:
	lxi	h,flopDsk
	lda	cpmDisk
	mov	m,a
	dcx	h
	mvi	m,flpSDS
	mvi	b,lenSDS
	call	command
	call	results
	lda	flopStat
	mov	b,a
	ani	20h		; drive ready bit
	ret
;
;-------
; entry>	none
; exit>		flopStat buf contains ID info
; Note that for some reason you must try FM mode first
; - else MFM is ok but FM hangs in FDC wait4int
ReadId:
	lxi	h,flopCmd
	mvi	m,flpRdId	; try single density
	call	GetId		; read the ID field
	rz			; this read is good
;
	lxi	h,flopCmd	; try double density
	mvi	m,(flpRdId +flpMFM)
	call	GetId		; read the ID field
	rz			; this read is good
;
	call	FindErr		; tell user about error
	jmp	ReadId		; retry if requested
;
;-------
; entry>	hl = adr of command string
; exit>		Z set if Id read is good
GetId:
	mvi	b,lenRdId
	call	command
	call	wait4int
	call	results
	lda	flopStat+1
	ani	05	; no (data/ID adr mark) mask
	ret
;
;-------
; entry>	hl = adr of command string
;		 b = len of command string
; exit>		sends cmd to flop disk controller
command:
	mov	d,h
	mov	e,l	; save cmd str adr
	push	b	; save command length
start:
	call	wait2xfer
	jc	CmdErr	; FDC wants to send data
;
	mov	a,m
	out	flpData	; send byte to fdc
	inx	h
	dcr	b
	jnz	start
;
	pop	b	; didn't need B again
	ret
;
CmdErr:
	call	results	; get data from FDC
	xchg		; retrieve cmd string adr
	pop	b	; this is why we saved B
	jmp	command	; restart command
;
;-------
; entry>	none
; exit>		FDC status into flopStat
Results:
	lxi	h,flopStat	; adr of result buf
	push	h
	mvi	b,lenStatus	; len of buf
ResFill:
	mvi	m,0ffh		; set buf to all 0ffh
	inx	h
	dcr	b
	jnz	ResFill
;
	pop	h		; adr of buf again
more:
	call	wait2xfer	; wait till FDC ready
	rnc			; no more status bytes
;
	in	flpData		; get a status byte
	mov	m,a
	inx	h
	jmp	more
;
;-------
; entry>	none
; exit>		c set if FDC wants to send data
;		reset if FDC ready to accept data
wait2xfer:
	push	h	; min 12 uSec delay from fdc
	dad	h	; data i/o till valid status
	pop	h
;
	in	flpStatus
	rlc		; bit 7 set if ok to transfer
	jnc	wait2xfer
;
	rlc		; bit 6 determines direction
	ret
;
;-------
; entry>	none
; exit>		none
wait4int:
	in	flpIntPort
	rlc		; wait for interrupt
	jnc	wait4int; status bit to be set
	ret
;
;-------
; entry>	none
; exit>		to DoPrompt
FindErr:
	lxi	h,RetryCnt
	lda	flopStat+2
;
	rrc
	jc	NoDataMark ; no data adr mark (st2,b0)
;
	rrc
	jc	BadTrk	; bad track (st2,b1)
;
	rrc
	rrc
	rrc
	jc	BadTrk	; wrong track (st2,b4)
;
	rrc
	jc	dataCRC	; bad data crc (st2,b5)
;
	lda	flopStat+1
;
	rrc
	jc	NoIdMark; no id adr mark (st1,b0)
;
	rrc
	jc	WrProt	; cant write (st1,b1)
;
	rrc
	jc	NoSec	; bad sector (st1,b2)
;
	rrc
	rrc
	jc	OvRun	; over run (st1,b4)
;
	rrc
	jc	idCRC	; bad id crc (st1,b5)
;
NotKnown:
	lxi	h,UnKnown	; should get here only
	jmp	DoPrompt	; from Sense routine
;
;-------
; entry>	hl = .flop retry counter
; exit>		hl = .no data mark string
NoDataMark:
	dcr	m
	rnz
;
	lxi	h,DataMark
	jmp	DoPrompt

;-------
; entry>	hl = .flop retry counter
; exit>		hl = .BadTrack string
BadTrk:
	push	h
	call	ReHome	; recalibrate drive
	pop	h
;
	dcr	m
	rnz
;
BadCyl:
	lxi	h,BadTrack
	jmp	DoPrompt

;-------
; entry>	hl = .flop retry counter
; exit>		hl = .BadData string
dataCRC:
	dcr	m
	rnz
;
	lxi	h,BadData
	jmp	DoPrompt

;-------
; entry>	none used
; exit>		hl = .wrong density string
NoIdMark:
	lda	flopStat+3
	cpi	77		; last legal track +1
	jnc	BadCyl		; illegal track request
;
	lxi	h,IdMark
	jmp	DoPrompt
;
;-------
; entry>	none used
; exit>		hl = .Protected string
WrProt:
		; no point in retrying
	lda	flopDsk
	adi	'A'
	sta	ProtDSK
	lxi	h,Protected
	jmp	DoPrompt
;
;-------
; entry>	none used
; exit>		hl = .BadSec string
NoSec:
	dcr	m
	rnz
;
	lxi	h,BadSec
	jmp	DoPrompt
;
;-------
; --	this is a fatal error	--
; entry>	none used
; exit>		no exit
OvRun:
	lxi	h,overrun
	call	PrtError
	call	PrtStat
	jmp	.	; spin till cold boot

;-------
; entry>	hl = .flop retry counter
; exit>		hl = .badID string
idCRC:
	dcr	m
	rnz
;
	lxi	h,badID
;			; fall thru to DoPrompt
;-------
; entry>	hl = adr of error str
; exit>		query user
DoPrompt:
	call	PrtError; print error string
	lda	SysMode	; check for debug print flag
	rrc		; bit0 is flag
	cc	PrtStat	; print flop statistics
	jmp	wait4user
;
;-------
; entry>	hl = .error string
; exit>
PrtError: 
	push	h	; save error str adr
	lxi	h,ErrHdr
	call	PrtMsg	; print error header
	pop	h	; restore str adr
	jmp	PrtMsg	; print error string
;
;-------
; entry>	none
; exit>		none
PrtStat:
	lxi	h,FlopMsg
	call	PrtMsg	; print 'Flop> ' header
	lxi	h,flopCmd
	mvi	b,lenMax+lenStatus
	jmp	PrtBuf	; print flop cmd/status bufs
.page
; *************************************************
; *		M E S S A G E S			  *
; *		- messages.dat -		  *
; *************************************************

FlopMsg:
	.ascii	[cr][lf]'Flop> '
	.ascii	'Cmd Dsk Trk Hd  Sec Den Max Gap '
	.ascii	'Len |-------  Status  -------|'
	.asciz	[cr][lf]'    '

RtryMsg:
	.ascii	[cr][lf]'** A = abort, '
	.asciz	'I = ignore, <CR> = retry '

ErrHdr:
	.asciz	[cr][lf]'** '

IdMark:
	.asciz	'wrong Density'

DataMark:
	.asciz	'no Data Adr Mark'

BadTrack:
	.asciz	'Track not found'

BadSec:
	.asciz	'Sector not found'

BadData:
	.asciz	'bad Data crc'

badID:
	.asciz	'bad Id crc'

Protected:
	.ascii	'disk '
ProtDsk:.byte	0ffh
	.asciz	' is write Protected'

OverRun:
	.ascii	'DMA error '
	.asciz	'- Cold Boot system'

NotReady:
	.ascii	'drive '
NRdsk:	.byte	0ffh
	.asciz	' not Ready'

BadHome:
	.ascii	'cannot Home drive '
HomeDsk:.byte	0ffh,0

UnKnown:
	.asciz	'Unknown error'
.page
; *****************************************************
; *	D A T A    S T O R A G E    A R E A	      *
; *		- storage .dat -		      *
; *****************************************************

;	floppy disk command table

flopCmd:	.byte	0	; opCODE
flopDsk:	.byte	0	; disk
flopTrk:	.byte	0	; track
flopSide:	.byte	0	; side
flopSec:	.byte	0	; sec
flopDen:	.byte	0	; den
flopMax:	.byte	0	; eot
flopGap:	.byte	0	; gpl
flopLen:	.byte	0	; dtl

flopStat:	.blkb	7	; result buffer

RetryCnt:	.byte	MaxRetry    ; retry 10 times

AdrUsrDma:	.word	DefaultBuf  ; cp/mDMA lsw adr
UserBank:	.byte	0	    ; cp/mDMA msb adr
AdrCurBuf:	.word	ActBuf	    ; flopDMA lsw adr
DmaBank:	.byte	0	    ; flopDMA msb adr


;	Command buffer disk type dependent values.

GapDataLen:   ; GPL  DTL
	.byte	007h,080h	; Single den  128 b/sec
	.byte	00eh,0ffh	; Double den  256 b/sec
	.byte	01bh,0ffh	; Double den  512 b/sec
	.byte	035h,0ffh	; Double den 1024 b/sec


;   ++	BDOS disk, track, record, type  ++

cpmDisk:	.byte	0
cpmTrk:		.word	0
cpmRec:		.byte	0
cpmType:	
cpm2side:	.byte	0	; SelDsk 2sided value
cpmDens:	.byte	0	; SelDsk density value

ActDirty:	.byte	0	; are any bufs dirty
RDorWR:		.byte	0	; type of transfer
WrType:		.byte	0	; passed on writes

curType:
cur2side:	.byte	0	; Current 2sided value
curDens:	.byte	0	; Current density value

; ++	actual buffer description	++

ActDisk:	.byte	0	; disk
ActTrk:		.byte	0	; track
ActRec:		.byte	0	; sec

zGenByte	==	. - 1	; last sysgen image byte


; ++	Disk transfer buffers	++

CkVec0:		.blkb	(256/4)		; check storage
CkVec1:		.blkb	(256/4)

AlVec0:		.blkb	(d1024dsm+7)/8	; alloc storage
AlVec1:		.blkb	(d1024dsm+7)/8


DirBuf:		.blkb	128	; Directory buffer

ActBuf:		.blkb	1024	; flop disk buffer

zMemByte	==	. - 1	; last mem loc used

	.end

; *****************************************************
; *						      *
; *	end of apposite designs bios modules	      *
; *						      *
; *****************************************************
