*------------------------------------------------------
* FLEX 2 Disk I/O Drivers for Percom LFD-400 FDC
*
* Mike Douglas 3/8/2020
*------------------------------------------------------

* MINDOS EQUATES

RESTORE	equ	$C006		;restore to track 0
RDSEC	equ	$C00C		;read a sector
WTSEC	equ	$C00F		;write a sector
SLTDRV	equ	$C012		;select drive, seek
INITRK	equ	$C027		;init track registers
PRCNT	equ	$AC34		;print spooler flag

* Page 0 data maintained by MiniDOS

	org	0
drvNum	rmb	1		;drive number in MS 2 bits
trk	rmb	1		;desired track
sctr	rmb	1		;desired sector

bakLnk	rmb	2		;file backward link
fwdLnk	rmb	2		;file forward link
bytCnt	rmb	1		;sector byte count
addres	rmb	2		;data address vector
filTyp	rmb	1		;file type code	
ckSum	rmb	2		;sector checksum
postAm	rmb	2		;post amble

crnTrk	rmb	1		;current track
trkTbl	rmb	4		;track each drive is on
wrtAddr	rmb	2		;write buffer address
rdAddr	rmb	2		;read

*------------------------------------------------------
* Disk driver jump table
*------------------------------------------------------
	org	$BE80		;disk I/O vector table
	jmp	read		;read a sector
	jmp	write		;write a sector
	jmp	verify		;verify a sector
	jmp	seek0		;restore to track zero
	jmp	drvSel		;select drive
	jmp	check		;drive ready check
	jmp	check		;quick drive ready check
	
saveX	rmb	2		;temp storage for X reg

*------------------------------------------------------
* System unique vectors. FLEX startup initialization
*   uses the following system-specific information to 
*   initialize various jump vectors and data structures
*   in FLEX.
*------------------------------------------------------
	org	$BEA3		;console I/O vector table
INVEC	fdb	$E1AC		;input character routine
OUTVEC	fdb	$E1D1		;output character routine
ACIA	fdb	$8004		;base of ACIA
TIMER	fdb	$8012		;timer board base
IRQ	fdb	$A000		;IRQ vector
SWI	fdb	$A012		;SWI vector
MON	fdb	$E0D0		;monitor entry address
PCV	fdb	$A048		;monitor PC location

*------------------------------------------------------
* read
* Entry - (X) = FCB Sector Buffer Address
*         (A) = Track Number
*         (B) = Sector Number
* The sector referenced by the track and sector 
* number is to be read into the Sector Buffer
* area of the indicated FCB.
*------------------------------------------------------
read	bsr	initHdr		;init MiniDOS header

	tst	PRCNT		;print spooler running?
	beq	rdNoPr		;no, continue

	swi			;swap out of print spooler

rdNoPr	nop			;needed for SWI routine?
	jsr	RDSEC		;read sector in MiniDOS
	bcs	retErr		;error, return it

	clrb			;status clear, zero true
	rts

*------------------------------------------------------
* write
* Entry - (X) = FCB Sector Buffer Address
*         (A) = Track Number
*         (B) = Sector Number
* The content of the Sector Buffer area of the 
* indicated FCB is to be written to the sector
* referenced by the track and sector number.
*------------------------------------------------------
write	bsr	initHdr		;init MiniDOS header

	tst	PRCNT		;print spooler running?
	beq	wrNoPr		;no, continue

	swi			;swap out of print spooler

wrNoPr	nop			;needed for SWI routine?
	jsr	WTSEC		;write sector in MiniDOS
	bcs	retErr		;error, return it

	clrb			;status clear, zero true
	rts

*------------------------------------------------------
* initHdr - Initialize header fields used by MiniDOS
*------------------------------------------------------
initHdr	stx	rdAddr		;give buffer address to MiniDOS
	stx	wrtAddr		;  for either read or write

	staa	trk		;give track number to MiniDOS

	ldx	#skewTbl-1	;X->sector skew table w/1-index

	tstb			;logical sector zero?
	bne	notZero		;no

	incb			;treat as sector 1

notZero	stab	*+4		;modify the following index offset
	ldab	0,x		;B=physical sector
	stab	sctr		;give sector to MiniDOS

	ldx	#0		;init header
	stx	bakLnk
	stx	fwdLnk

	clra
	staa	bytCnt		;256 byte sectors
	staa	filTyp		;file type

*  To allow booting by using the MiniDOS load command, the boot sector
*  must look like a valid MiniDOS file. The boot loader in sector
*  zero loads at $2400 and executes at $2400. These MiniDOS fields
*  are set here and will be in every sector written by FLEX, but only
*  matter when MiniDOS is used to boot (L 1000 FFFF followed by G).

	ldx	#$2400		;for boot loader
	stx	addres		;load address of $2400
	stx	postAm		;execution address of $2400
	
	rts

* skewTbl maps logical sectors 1-10 to physical sectors 0-9 with
*    a skew of 5. This provides the best performance for loading
*    command and binary files.

skewTbl	fcb	0,5,1,6,2,7,3,8,4,9

*------------------------------------------------------
* retErr - Return a 1771 status code in B based on the 
*    MiniDOS error code in A
*
*    MiniDOS	1771
*     -----	----
*	0	$80	Disk missing (not ready)
*	1	$40	Write protected
*      2,3	$10	Invalid sector, seek error
*	4	$04	Disk overrun (won't occur)
*	5	$08	Read error (CRC error)	
*------------------------------------------------------
retErr	ldx	#errTbl		;X->error table
	staa	*+4		;modify the following index offset
	ldab	0,x		;offset set to value in B
	rts

errTbl	fcb	$80,$40,$10,$10,$04,$08

*------------------------------------------------------
* seek0
* Entry - (X) = FCB Address
* Exit -  CC, NE, &B=$B if write protected
*         CS, NE, &B=$F if no drive
* A Restore Operation (also known as a Seek
* to Track 00) is to be performed on the
* drive whose number is in the FCB.
*------------------------------------------------------
seek0	stx	saveX		;save X
	bsr	drvSel		;select the drive

	clr	trk		;seek to track 0
	jsr	SLTDRV		;call MiniDOS select
	bcs	selErr

	jsr	RESTORE		;call MiniDOS restore
	ldx	saveX		;restore X

seekRts	clrb			;no error
	clc
	rts

selErr	ldx	saveX		;restore X
	ldab	#$0F		;flag drive error
	sec			;set carry
	rts

*------------------------------------------------------
* drvSel
* Entry - (X) = FCB Address
* The drive whose number is in the FCB is
* to be selected
*------------------------------------------------------
drvSel	ldaa	crnTrk		;$B9 means cold start
	cmpa	#$B9		;(from startup RAM test)
	bne	notCold		;not cold start

	jsr	INITRK		;init MiniDOS track table

notCold	ldaa	3,x		;A=drive number 0-3
	inca			;Percom is 1 indexed

	rora			;put in upper two bits
	rora
	rora	
	anda	#$C0		;get drive bits alone
	staa	drvNum		;give drive to MiniDOS

	rts

*------------------------------------------------------
* check drive ready
* Entry - (X) = FCB Address
* Exit -  NE & CS if drive not ready
*         EQ & CC if drive ready
* 2 second delay
*------------------------------------------------------
check	ldaa	3,x		;get drive number from FCB
	cmpa	#1		;drive 0 or 1 only
	bls	seekRts		;exit with carry clear

	ldab	#$80		;else, indicate not ready
	sec
	rts

*------------------------------------------------------
* verify sector
* Entry - (No parameters)
* The sector just written is to be verified to 
* determine if there are CRC errors.
*------------------------------------------------------
verify	clrb			;not supported
	rts
	end

