			SUBTITLE	"< Flash memory Disk Driver.>"
			newpage

;			FD-DVR/ASM - derived from LS-DOS 6.2 study model.

;	 		HL=> buffer address.
;			D=> track desired.
;			E=> sector desired.
;			C=> drive desired.
;			B=> disk primitive command.

;			Disk Driver Entry Point

FDCDVR		JP			FDCBGN				;Branch to entry code
			DW			FDCEND				;Last byte used
			DB			3,"$FD"				;Module name
	
;			Automatic density recognition and retry density switch


PDRIVE		DB			0
TRACK		DB			0
SECTOR		DB			0

PADDRESS	DS			3	
	
SWDEN
			LD			A,3					;Check counter for 2
			CP			B					;tries left after this one
			JP			Z,RESTOR			;If so try a RESTORE
			LD			A,(IY+03h)			;Flip the density bit,
			XOR			40h					;Bit 6, (IY+3)
			LD			(IY+3),A
			LD			BC,2409h			;Set alloc to SDEN
			BIT			6,A					;Test SDEN/DDEN
			JR			Z,SDEN				;Do SDEN if it was DDEN
			LD			BC,4511h			;else set alloc to DDEN
SDEN		LD			(IY+7),C
			LD			(IY+8),B
			RET


;				Driver start



FDCBGN		LD			A,B					; P/u primitive request.
			AND			A					; Test primitive request, is it NOP? If yes, quit and return to caller.
			RET			Z					; Quit if NOP, tell them we here and HELL YES we're ready!
			CP			7
			JR			NZ,TSTBSYnot		; If <> 7 THEN jump TSTBSYnot and continue with driver.
TSTBSY		XOR			A					; FUNCTION 7 TEST BUSY.
			RET								; We are solid state drive, were ready return with Z set!
TSTBSYnot	JP			NC,IORQST			; Jump on I/O request.

			push		bc
			push		de					; Save track / sector.
			push		hl
					
			PUSH		DE					; Push track / sector for quick access.
			PUSH		DE					; Save track / sector for quick access.
			push		bc					; Save function/drive.

			ld			L,b					; Function in B to C and convert to ascii.
			LD			H,0
			LD			DE,dskfun			; Stuff in output statement.
			CALL		zHEXDEC				; Convert.

			pop			bc
			ld			L,c					; DRIVE in C, convert to ascii.
			LD			H,0
			LD			DE,dskdrv			; Stuff in output statement.
			CALL		zHEXDEC				; Convert.
				
			POP			de					; Recover track & sector.
			LD			L,d					; Register D contains track #.
			LD			H,0
			LD			DE,dsktrk			; Stuff in output statement.
			CALL		zHEXDEC
				
			POP			bc					; Get sector #.
			ld			L,c
			LD			H,0
			LD			DE,dsksec			; Stuff in output statement.
			CALL		zHEXDEC				; Convert.
	
 			PUMP		DEVICE.serialnet,dskcmd
 			PUMP		DEVICE.serialnet,dskfun
			PUMP		DEVICE.serialnet,dskdrv
			PUMP		DEVICE.serialnet,dsktrk
			PUMP		DEVICE.serialnet,dsksec
			PUMP		DEVICE.serialnet,dskexe
																	
			pop			hl
			pop			de
			pop			bc

			LD			A,B					; P/u primitive request.
			CP			6
			JR			Z,SEEKTRK			; *6 Jump on track seek
			DEC			A
			JR			Z,SELECT1			; *1 Jump on drive select
			INC			(IY+5)				; Bump current cylinder
			CP			4
			LD			B,58h				; FDC step-in command
			JR			Z,STEPIN1			; *4 

; FUNCTIONS 2 NOT IMPLIMITED.
; FUNCTIONS 3 NOT IMPLIMITED.

RESTOR	; FUNCTION 4. RESTORE.

			LD			(IY+5),0			; Set track to 0
			LD			B,8					; Restore drive
			JR			STEPIN1
			
SELECT1		; FUNCTION 1....
			
			CALL		TSTBSY				; Check drive status
			RLCA
			LD			A,(IY+3)			; <631>P/u SDEN/DDEN/DELAY (DLY chked later)
			PUSH		AF					; <631>Save NOT READY flag
			PUSH		BC					; <631>
			RLA								; Bit 6=>7, bit 4=>4
			SRA			A
			AND			90h					; Keep only DDEN & side 1
			LD			C,A					; Save the bits
			BIT			7,A					; Check if SDEN or DDEN
			JR			Z,NOPCMP			; No precomp if SDEN
			LD			A,(IY+9)			; Set precomp on all
			CP			D					; tracks above DIR
			JR			NC,NOPCMP			; Go if no precomp needed
			SET			5,C					; Request precomp
NOPCMP
			LD			A,(IY+4)			; Get drive sel code
			AND			0Fh					; Keep only sel bits
			OR			C					; Merge in bits 4,5,7
			POP			BC
			
			LD			(PDRIVE),A			; Store drive #.
;			OUT			(DSELCT),A			; Select drive
			LD			(PDRV$),A			; Store port byte
;			OUT			(DSELCT),A			; <631>Re-write Drive select just in case
			POP			AF					; <631>Retrieve Not Ready Bit
			
			RET			NC					; <631>Return if was ready
			BIT			2,A					; <631>Check DELAY=0.5 or 1.0 (IY+3 in A)
			CALL		Z,FDCDLY			; Double delay if 1.0
FDCDLY
			PUSH		BC					; Delay routine
			LD			B,1h
;			CALL		PAUSEz				; No PAUSE, solid state drive must be ready.
			POP			BC
			RET


SEEKTRK;	FUNCTION 6 routine to seek a track

			LD			A,(IY+5)			; P/u current cylinder
			LD			(TRACK),A 
			LD			A,(IY+7)			; P/u alloc data
			AND			1Fh					; Get highest # sector
			SUB			E					; Form req sector minus
			CPL								; max, setting CY flag if
			RES			4,(IY+3)			; init side select to 0
			JR			NC,SETSECT			; Go if sector on side 0
			BIT			5,(IY+4)			; If not 2-sided media,
			JR			Z,FRCSID0			; don"t set side 1
			SET			4,(IY+3)			; Set side 1
			DB			06h					; Ignore next with LD B,n
SETSECT		LD			A,E					; Restore unaltered sec #

FRCSID0	
			LD			(SECTOR),A			;	OUT	(SECREG),A	; Set sector
			LD			A,D
			LD			(TRACK),A			;	OUT	(DATREG),A	; Set desired track
			
			CP			(IY+5)				; If at desired track,
			LD			B,18h				; use seek, else use
			JR			Z,STEPIN1			; seek w/verify
			LD			(IY+5),D			; Update current cylinder
			LD			B,1Ch				; Seek w/verify command.
 
STEPIN1		; FUNCTION 5.

			CALL		SELECT1				; Select drive
			LD			A,(IY+3) 
			AND			3					; Strip all but rate
			OR			B
PASSCMD;	OUT			(FDCADR),A			; Give FDC its command
			XOR			A
FDCRET		RET

;			Read and write init routines track=track.

;RWINIT
			LD			A,D					; Stuff trk reg
			LD			(TRACK),A
			LD			A,(PDRV$)			; Get select code
			OR			40h					; Set WSGEN bit
			LD			D,A					; Save code in D
			AND			10h					; Get side sel bit
			RRCA							; to bit 3
			BIT			1,C					; Check if doing side cmp
			JR			NZ,GETCMD			; Go if so
			XOR			A
GETCMD
			OR			C
			LD			C,0					; DATREG			;Get port into C
;			CALL		FDDINT$				; Interrupts on or off?
			JR			PASSCMD				; Pass command to ctrlr

;			I/O request handler
IORQST
			BIT			2,B					; Write command?
			LD			BC,(RFLAG$-1)		; P/u retry count
			LD			C,82h				; FDC cmd=readsec
			JR			NZ,WRCMD			; Go if write command
			
			CP			10					; Verify sector?
			JR			Z,VERFY
			jp			RDIN
			CALL		GRABNDO				; Grab next code & insert
			DB			1					; Error code start
			DW			RDIN				; Read entry point
VERFY		CALL		GRABNDO				; Stuff I/O direction
			DB			1					; Error code start
			DW			VERFIN				; Verify entry point

;			Verify routine

VERFIN
			LD			HL,BUCKET			;Set byte bucket
;			LD			A,2Dh				;Set for DEC L,...
;			DB			1Eh					;Ignore next with LD E,n
	


RDIN;		Read routine

; Read sector from network.		
; HL points to lower 16b destination buffer.

			LD		B,0						; Set counter 0 or MAX count (256).
rd256		SCF								; Set flag telling driver GET function.
;			CALL	U1DVR					; Get a byte.
			LD		(HL),A
			INC		HL
			DJNZ	rd256
;HOLDEM		JP		HOLDEM
			RET		

WRCMD

; If software write protect (WP) active then set WP error & return.

			BIT			7,(IY+03h)			; Software WP?
			JR			Z,SEND256			; Bypass if not
			LD			A,15				; Else set WP error
			RET

SEND256		LD		B,0						; Write sectors to DRIVE.
snd256		XOR		A						; Set counter 0 or MAX count (256).
			LD		C,(HL)					; Get a byte.
			INC		HL
			CALL	U1DVR
			DJNZ	snd256
;HOLDEM		JP		HOLDEM
			RET
			
;			Routine stuffs error start byte & I/O vector

GRABNDO
			EX			(SP),HL				; Save HL & get ret addr
			LD			A,(HL)				; P/u & stuff error code
			INC			HL					; start byte
			LD			(ERRSTRT+1),A
			LD			A,(HL)				; Set up data transfer
			INC			HL					; direction vector
			LD			H,(HL)
			LD			L,A
			LD			(CALLIO),HL			; Stuff CALL vector
			POP			HL					; Restore buffer addr

;			Main I/O handler routine

RETRY		PUSH		BC					; Save retry & FDC command
			PUSH		DE					; Save track/sector
			PUSH		HL					; Save buffer
			BIT			4,C					; Test for track command
			CALL		Z,SEEKTRK			; Seek if not track write
			CALL		TSTBSY				; Wait till not busy
			CALL		0					; Call I/O routine
CALLIO:		EQU			$-2					; Data xfer direction
DISKEI		NOP								; Will be changed to a EI after
												; BOOT has read in SYS0
;			IN			A,(FDCSTAT)			; Get status
			AND			7Ch					; Strip all but 2-6
			POP			HL		
			POP			DE					; Rcvr track & sector
			POP			BC					; Rcvr retry count & cmd
			RET			Z					; Ret if no error
			BIT			2,A					; Lost data?
			JR			NZ,RETRY			; Don"t count this retry
			PUSH		AF
			AND			18h					; Record not found or CRC
			JR			Z,DISKDUN			; No retries if otherwise
			BIT			4,A					; Record not found?
			PUSH		BC					; If so, switch
			CALL		NZ,SWDEN			; density or restore
			POP			BC
			POP			AF
			DJNZ		RETRY				; Count down retry
			DB			6					; Ignore next with "LD B,nn"
DISKDUN	
			POP			AF					; Adjust ret code
			LD			B,A
ERRSTRT
			LD			A,0					; Start with R=1, W=9
ERRTRAN		
			RRC			B
			RET			C
			INC			A
			JR			ERRTRAN
			
dskcmd		DB			"*FD F",CR.asc,ETX.asc
dskfun		DB			"     ",CR.asc,ETX.asc
dskdrv		DB			"     ",CR.asc,ETX.asc
dsktrk		DB			"     ",CR.asc,ETX.asc
dsksec		DB			"     ",CR.asc,ETX.asc
dskexe		DB			"*exe",CR.asc,ETX.asc


;			IF			$&0FFh = 0FFh
;			ERROR		"Warning... BUCKET position error"
;			ENDIF

BUCKET		DB			'S'

FDCEND:		EQU			$-1
