*--------------------------------------------------------------
* FLEX 1.0 (MiniFLEX) disk driver for DC-x controllers
*
* Disassembled by M. Douglas from FLEX 1.0 file "DOS.SYS"
*--------------------------------------------------------------
	org	$7F00

* Disk driver jump table

	jmp	readSec		;read sector
	jmp	wrtSec		;write sector
	jmp	vfySec		;verify sector
	jmp	restore		;restore to track 0
	jmp	drvSel		;select drive

* Local driver data

curDrv	fcb	0		;current drive
	fcb	0
ddSaveX	fdb	0		;X save for disk driver
trkTbl	fcb	0,0,0,0		;table of track # per drive

* FD1771 equates

DRVREG	equ	$8014		;drive select register
CMDREG	equ	$8018		;command register
TRKREG	equ	$8019		;track register
SECREG	equ	$801A		;sector register
DATREG	equ	$801B		;data register

*--------------------------------------------------------------
* readSec - Read Sector
*
* Entry - (X) = Sector Buffer Address
*         (A) = Track Number
*         (B) = Sector Number
* The sector referenced by the track and sector number
* is read into the sector buffer
*--------------------------------------------------------------
readSec	bsr	seek		;seek to track in A
	nop
	sei
	ldaa	#$8C		;FD1771 read sector command
	staa	CMDREG
	jsr	delay		

	ldab	#128		;read 128 bytes

rsLoop	ldaa	CMDREG
	bita	#$02		;data present?
	bne	rsData		;yes
	bita	#$01		;still busy?
	bne	rsLoop		;yes

	tab			;status in B
	bra	rsExit		;exit

rsData	ldaa	DATREG		;retrieve and store next byte
	staa	0,x		;  read from the disk
	inx
	decb
	bne	rsLoop

	bsr	waitBsy		;wait for 1771 to finish

rsExit	bitb	#$1C		;test read error bits
	cli
	rts

*--------------------------------------------------------------
* waitBsy - Wait for the 1771 to indicate command completion
*    (busy bit goes false)
*--------------------------------------------------------------
waitBsy	ldab	CMDREG
	bitb	#$01		;still busy?
	bne	waitBsy		;yes
	rts

*--------------------------------------------------------------
* seek - Seek to track specified in A and give the 1771 the
*    sector number specified in B.
*--------------------------------------------------------------
seek	cmpa	TRKREG		;already on correct track?
	beq	skExit		;yes
	staa	DATREG		;else, set track to seek 
	jsr	delay

	ldaa	#$1B		;1771 seek command, slow step
	staa	CMDREG
	jsr	delay

	pshb			;preserve sector number
	bsr	waitBsy		;wait for seek to complete
	pulb			;restore sector number

skExit	stab	SECREG		;specify sector for upcoming I/O
	jmp	delay		;delay and retrn

*--------------------------------------------------------------
* wrtSec - Write Sector
*
* Entry - (X) = Sector Buffer Address
*         (A) = Track Number
*         (B) = Sector Number
* The content of the Sector Buffer is written to the
* sector specified by the track and sector number
*--------------------------------------------------------------
wrtSec	bsr	seek		;seek to track in A
	nop
	sei
	ldaa	#$AC		;1771 write sector command
	staa	CMDREG
	jsr	delay

	ldab	#128		;write 128 bytes

wsLoop	ldaa	CMDREG
	bita	#$02		;ready for byte?
	bne	wsByte		;yes
	bita	#$01		;still busy?
	bne	wsLoop		;yes

	tab			;status in B
	bra	wsExit		;exit

wsByte	ldaa	0,x		;retrieve next byte to write and
	staa	DATREG		;  give it to the 1771
	inx
	decb
	bne	wsLoop

	bsr	waitBsy		;wait or 1771 to finish

wsExit	bitb	#$5C		;test write error bits
	cli
	rts

*--------------------------------------------------------------
* vfySec - Verify Sector
*    Read the sector just written to verify the CRC
*--------------------------------------------------------------
vfySec	ldaa	#$8C		;read sector
	nop
	sei
	staa	CMDREG
	jsr	delay

	bsr	waitBsy		;wait for sector to be read
	cli
	bitb	#$18		;test read error bits
	rts

*--------------------------------------------------------------
* restore - Restore to track zero
* Entry - (X) = FCB Sector Buffer Address
* Exit - CC, NE, B=$0B if write protected
*	 CS, NE, B=$0F if no drive
*	 CC, EQ for success
* Restore to track zero for the drive in the FCB
*--------------------------------------------------------------
restore	stx	ddSaveX		;preserve X
	bsr	drvSel		;select the drive
	ldaa	#$0B		;1771 restore command
	staa	CMDREG
	bsr	delay

	ldx	#0		;use X for 3 sec timeout

resLoop	jsr	delay2		;(28)
	ldaa	CMDREG		;(4) see if still busy
	bita	#$01		;(2)
	beq	resExit		;(4) operation is complete

	dex			;(4) decrement timer
	bne	resLoop		;(4) not expired yet

	ldx	ddSaveX		;restore X
	ldab	#$0F		;indicate no drive
	sec
	rts

resExit	ldx	ddSaveX		;restore X
	bita	#$40		;write protect?
	bne	wrtProt		;yes
	clc
	rts

wrtProt	ldab	#$0B		;$0B=write protected
	clc
	rts

*--------------------------------------------------------------
* drvSel - Select Drive
* Entry - (X) = FCB Address
* The drive specified in the FCB is selected
*--------------------------------------------------------------
drvSel	ldaa	3,x		;A=drive number from FCB
	anda	#$03		;drives 0-3 only
	bsr	fndTrk		;X->where to save track number
	ldab	TRKREG		;save current track
	stab	0,x

	staa	DRVREG		;change to new drive	
	staa	curDrv
	bsr	fndTrk		;X->track new drive is on
	ldaa	0,x
	staa	TRKREG		;set track in the 1771
	bra	delay

* fndTrk - Return X pointing to the track save location for
*    the drive number in curDrv

fndTrk	ldx	#trkTbl		;X->track number table
	ldab	curDrv		;B=current drive number
	beq	ftExit		;drive 0, X already correct

ftLoop	inx			;update X to point to the correct
	decb			;   drive entry in the table
	bne	ftLoop

ftExit	rts

* delay - Delay 56us including the call to delay

delay	jsr	delay2
delay2	jsr	delay3
delay3	rts

	end	$7100		;FLEX cold start entry
