;**********************************************
; COPY OF EINSTEIN DISK DRIVERS FOR MODIFYING.
; PB 850830    INCLUDE IN EDISK.GEN
;**********************************************
;
; RDSECT: ACTUAL SECTOR READ ROUTINE:
; WRSECT: ACTUAL SECTOR WRITE ROUTINE
;
STEPR:	EQU	0FBB0H		; STEP RATE, DEF. 1 = 12mS
SIDFLG:	EQU	0FBB1H		; SS/DS FLAG (DEF 0 = SINGLE)
SCTSIZ:	EQU	0FB44H		; SIZE OF SECTOR IN 256-BYTE BLOCKS
RWFLAG:	EQU	0FB55H		; R/W FLAG
STATS:	EQU	0FB56H		; ERROR STATUS VALUE 
ERCNT:	EQU	0FB57H		; RETRY ERROR COUNT
TRKTBL:	EQU	0FB58H		; STOR TRACK COUNT FOR <= 4 DISKS
;
NSECT:	EQU	10		; 10 SECTORS/TRACK
STPRAT:	EQU	1		; DEFAULT 12 mS;
RDMEM:	EQU	0FB14H		; MEMORY READ
;
RSTPRT:	EQU	00H		; RESET PORT,FDC/PSG
CMDPRT:	EQU	18H		; FDC COMMAND/STATUS REGISTER
TRKPRT:	EQU	19H		; FDC TRAC REGISTER
SCTPRT:	EQU	1AH		; FDC SECTOR REGISTER
DATPRT:	EQU	1BH		; FDC DATA I/O REGISTER
DSCPRT:	EQU	23H		; DISK SELECT PORT
;
RDSECT:	XOR	A
	JR	RW1
;
WRSECT:	LD	A,01H		; SET RWFLAG
RW1:	LD	(RWFLAG),A
	LD	A,10		; 10 RETRIES
	LD	(ERCNT),A
RW2:	CALL	CALDSC		; GET DISC ENABLE LINE
	OUT	(DSCPRT),A
	CALL	MOTON		; CHECK MOTOR ON?
	JP	NZ,RWERR
	CALL	DEFTRK		; (TRACK) <- HL
	LD	A,(HL)		; NEW ?
	OUT	(TRKPRT),A	; SEND TRACK TO FDC
	LD	A,(HSTTRK)	; GET REQUESTED TRK
	CP	(HL)		; CP W. CURRENT
	JR	Z,RW3		; SKIP SETUP IF SAME
	LD	(HL),A		; ELSE SET UP NEW
	OUT	(DATPRT),A	; O/P TO FDC DATA
	LD	A,10H		; SEEK???
	CALL	STPCMD		; DO A TYPE 1 FDC CMND.
	CALL	Z,CHKST		; CHECK FOR COMPLTED
	LD	DE,0A0B9H	; STATUS AND TEST MASK 
	CALL	Z,DELTST	; WAIT FOR HEAD SETTLE AND TEST:
	JR	NZ,RWERR	; MO(1),SPINUP(1),RNF(0),CRC(0),BUSY(0)
RW3:	LD	A,(HSTSEC)	; GET NO. SECTORS
	OUT	(SCTPRT),A	; SEND TO FDC
	LD	A,(SCTSIZ)	; FB44H FOR EINSTEIN:SIZE IN 100H BLOCKS
	LD	D,A		; SET UP D (= 2 ; 512 = 256 * 2)
	LD	C,DATPRT	; => FDC DATA PORT
	LD	HL,(HSTDMA)	; HOST BUFFER, NORM. FE00H
	LD	A,(RWFLAG)	; CHECK R/W FLAG
	OR	A
	DI			; NO INTERRUPTS NOW!
	JR	NZ,DWRSCT	; WRITE IF REQUIRED
;
DRDSCT:	LD	A,80H		; READ A RECORD COMMAND
	LD	B,0
	CALL	COMND		; SEND TO FDC CMND
	JR	NZ,RB3		; CHECK?
RB1:	IN	A,(CMDPRT)	; GET FDC STATUS
	RRCA			; TEST BUSY FLAG
	JR	NC,RB2		; BUSY? NO = ERROR
	RRCA			; TEST DRQ FLAG
	JR	NC,RB1		; WAIT
	INI			; INPUT W. INCR., <C>
	JP	NZ,RB1		; GO BACK IF REQD.
	DEC	D		; SECTRS - 1
	JP	NZ,RB1		; DO AGAIN IF NOT 0
RB2:	CALL	CHKST		; COMMAND DONE?
RB3:	EI			; YES, INTS. OK NOW
	JR	NZ,RWERR	; GOT AN ERROR
	IN	A,(CMDPRT)	; GET FDC STATUS
	AND	0BFH		; MASK UNUSED READ BITS
	JR	RWDUN		; FINISHED
;
DWRSCT:	LD	A,0A0H		; WRITE A RECORD COMMAND
	LD	B,0		; 256 BYTES
	CALL	COMND		; SEND TO FDC
	JR	NZ,WB3		; CHECK 
	CALL	RDMEM		; SET UP DATA TO WRITE?
	LD	E,A		; SAVE DATA 
WB1:	IN	A,(CMDPRT)	; GET STATUS
	RRCA			; TEST BUSY
	JR	NC,WB2		; ERROR 
	RRCA			
	JR	NC,WB1		; WAIT
	OUT	(C),E		; SEND THE BYTE
	INC	HL		; => TO NEXT
	CALL	RDMEM
	LD	E,A		; SAVE BYTE
	DJNZ	WB1		; UNTIL ALL DONE
	DEC	D		; NEXT LOT OF 256
	JP	NZ,WB1
WB2:	CALL	CHKST		; STATUS
WB3:	EI			; INTS. OK
	JR	NZ,RWERR	; GOT AN ERROR
	IN	A,(CMDPRT)	; STAT.
;
RWDUN:	CP	80H		; CHECK MOTOR ONLY SET
	RET	Z		; RET. IF OK, ELSE :
;
RWERR:	CALL	STCNV		; CONVERT STATUS CODE
	LD	HL,ERCNT	; ERROR COUNT
	CP	4		; NOT READY?
	JR	NC,RWER0
	CP	2		; WRITE PROTECT?
	JR	NZ,RWER1
RWER0:	LD	(HL),1		; STRAIGHT OUT IF SO
RWER1:	LD	A,0D0H		; SET UP STOP
	OUT	(CMDPRT),A	; TERMINATE FDC CMND.
	DEC	(HL)		; ERCNT - 1
	JR	Z,RWER3		; DONE ALL?
	MCAL	ZHMDSC		; DO A HOME DISK
	JP	Z,RW2
RWER3:	MCAL	ZFDRST		; RESET DISKS
	LD	A,(STATS)	
	OR	A
	RET
;
; CALDSC - WORK OUT DRIVE SELECT LINE
;
CALDSC:	PUSH	HL
	CALL	DSCBIT		; GET 1,2,4 OR 8
	LD	L,(HL)		; GOT LINE
	LD	A,(HSTSEC)	; REQD. SECTR NO.
	SUB	NSECT		; CHECK SIDE !
	JR	C,CLD1		; THIS SIDE
	SET	4,L		; ELSE SET OTHER
CLD1:	LD	A,L		; GET IN A
	POP	HL
	RET			; DONE.
;
; GNSECT - CHECK SIDEFLAG
;
GNSECT:	PUSH	HL		; SAVE NSECTRS
	CALL	DSCBIT		; GET BIT 
	LD	A,(SIDFLG)
	AND	(HL)		; CHECK IT
	POP	HL
	LD	A,NSECT
	RET	Z		; SINGLE SIDED
	ADD	A,A		; SECTRS * 2 IF D/S
	RET
;
DSCBIT:	LD	A,(HSTDSC)	; DRIVE BIT
	LD	HL,BITS		; => BITS
	AND	3		; FILTER
	ADD	A,L
	LD	L,A		; BITS IN L
	RET
;
MOTON:	XOR	A		; SET Z FLAG
	IN	A,(CMDPRT)	; STATUS
	RLA			; GET MOTOR-ON BIT
	RET	C		; RETURN IF ON, ELSE:
;
HOMDSC:	LD	A,04H		; VERIFY/HOME TO TK 0
	CALL	STPCMD		; TYPE 1 TO FDC
	CALL	Z,CHKINX	; CHECK FOR INDEX PULSES
	CALL 	Z,CHKST		; COMPLETED?
	LD	DE,0A4BDH	; STATUS + MASK 
	CALL	Z,DELTST	; SETTLE + TEST FOR TK 0
	JR	NZ,STCNV	; CONVERT ERROR 
	CALL	DEFTRK		; GET DEFAULT TRACK LOCN.
	XOR	A		; SET TO 0
	OUT	(TRKPRT),A	; SEND TRK
	LD	(HL),A		; CLEAR SCRP IMAGE
	RET	
;
; STCNV - CONVERT DISK ERROR STATUS CODE
;	01 = BAD DATA / CHECKSUM
;	02 = WRITE PROTECTED DISK
;	03 = TRACK/SECTOR NOT FOUND
;	04 = DRIVE NOT READY
;	05 = NO DRIVE.
;
STCNV:	PUSH	DE		; SAVE MASKS
	CP	0FEH		; NO DRIVE?
	LD	E,5		; SET ERROR CODE
	JR	Z,STC1		; AND END
	DEC	E		; NEXT CODE READY
	CP	0FFH		; NOT READY?
	JR	Z,STC1
	DEC	E
	BIT	4,A		; SECTOR NOT FOUND?
	JR	NZ,STC1
	DEC	E
	BIT	6,A		; WRITE PROTECTED?
	JR	NZ,STC1
	DEC	E		; ELSE ITS BAD DATA
STC1:	LD	A,E		; CODE INTO A 
	POP	DE
	LD	(STATS),A	; SAVE CODE 
	OR	A		; SET FLAG
	RET
;
; COMND - O/P A COMMAND TO THE FDC
; STPCMD - O/P A "TYPE 1 " RESTORE OR SEEK TO FDC
;
STPCMD:	PUSH	HL
	LD	HL,STEPR	; STEPRATE FBB0, DEF.=1 (12mS)
	OR	(HL)
	POP	HL
;
COMND:	OUT	(CMDPRT),A	; SEND COMMAND
	PUSH	BC
	LD	B,080H		; "TIMEOUT"?
CMD1:	IN	A,(CMDPRT)	; GET STATUS
	RRCA			; BUSY?
	JR	C,CMD3		; NO CONTINUE
	DJNZ	CMD1		; ELSE WAIT B
CMD2:	POP	BC		; RESTORE
	XOR	A
	DEC	A		; RETURN A=FF IF ERROR
	RET
CMD3:	POP	BC
	XOR	A
	RET			; NORMAL END - NOW BUSY
;
; CHKST - CHECK FDC STATUS FOR TIMEOUT
;
CHKST:	PUSH	BC
	PUSH	DE
	LD	D,3
	LD	BC,0000H
CKS1:	IN	A,(CMDPRT)	; GET STATUS
	RRCA			; CHECK BUSY
	JR	NC,CKS3		; END 
	DEC	BC		; TIMEOUT - 1
	LD	A,B		; CHECK BOTH B/C
	OR	C
	JR	NZ,CKS1		; NOT TIMED OUT YET
CKS2:	POP	DE		; NOW TIMED OUT
	JR	CMD2		; RETURN AN ERROR
CKS3:	POP	DE		; ELSE NORMAL END
	POP	BC
	XOR	A		; A = 0
	RET
;
; DELTST - ALLOW HEAD SETTLING TIME THEN CHECK STATUS
;
DELTST:	PUSH	DE
	LD	DE,1100H	; TIME VALUE
DEL1:	DEC	DE
	LD	A,D		; TEST DE = 0
	OR	E
	JR	NZ,DEL1		; WAIT TILL DONE
	POP	DE		; NOW DO STATUS
	IN	A,(CMDPRT)
	AND	E		; MASK BITS NOT REQD.
	CP	D
	RET
;
; CHKINX - CHECK FOR INDEX PULSES.
;
CHKINX:	PUSH	BC
	LD	BC,0		; TIMEOUT
CX1:	DEC	BC		; SHOULD GET PULSE ABT. 200mS
	LD	A,B		; TEST BC = 0
	OR	C
	JR	Z,CX2		; TIMED OUT
	IN	A,(CMDPRT)	; GET STATUS
	BIT	1,A		; ?
	JR	Z,CX1		; TRY AGAIN
	JR	CMD3		; GOT IT - RETURN OK
CX2:	IN	A,(CMDPRT)	; NO DISK
	RLA			; TEST WRITE - PROTECT
	RLA
	CCF
	SBC	A,A		; IF NOT, NO DRIVE
	DEC	A		; RET. FF
	POP	BC
	RET			; ERROR OUT.
;
; FDRST: RESET FDC AFTER ERROR 
;       (ALSO RESETS PSG?)
;
FDRST:	XOR	A
	OUT	(DSCPRT),A	; SELECT DR 0
	PUSH	BC
	LD	B,20H
FDR1:	OUT	(RSTPRT),A	; RESET FDC,PSG
	EX	(SP),HL		; DELAY FIDDLE
	EX	(SP),HL
	DJNZ	FDR1
	MCAL	ZPINIT		; SET UP PSG 
	POP	BC
	RET
;
; DEFTRK - GET DEFAULT TRACK LOCATION
;
DEFTRK:	LD	A,(HSTDSC)	; GET DISK FROM FB50H
	LD	HL,TRKTBL	; FB58H * 4 LOCNS.
	ADD	A,L		; INDEX
	LD	L,A
	RET	NC
	INC	H		; GOT LOCATION
	RET
;
BITS:	DEFB	01,02,04,08	; BIT MASKS.
;
			

	
	CNS.
	ADD	A,L		; INDEX
	LD	L,A
	RET	NC
	INC	H		; GOT LOCATION
	RET