
; HOME THE HEADS TO TRACK 0

HOME:	LD	A,(HSTWRT)	; CHECK WRITE PENDING DATA IN BUFFER
	OR	A
	JR	NZ,HOMED	; IF WRITE DATA PENDING THEN SKIP

	LD	(HSTACT),A

HOMED:	XOR	A
	LD	(SEKTRK),A	; RESET SEEK TRACK TO ZERO
	RET

; DISK SELECT ENTRY ROUTINE
; ACCEPTS: C = DRIVE SELECT (WITH C=0 FOR SELECT DRIVE"A")
; RETURNS: HL = DPB POINTER OF DRIVE SELECT (IF C=VALID DRIVE NUMBER)
;          HL = 0H IF (C=INVALID DRIVE NUMBER)

SELDSK:	LD	HL,0		; SET HL = ERROR RETURN CODE
	LD	A,C
	LD	(SEKDSK),A	; SAVE DRIVE NUMBER
	CP	MAXDRV+1	; CHECK FOR VALID DRIVE
	RET	NC		; EXIT WITH HL = 0H

; DRIVE NUMBER IS IN PROPER RANGE

	LD	L,A
	LD	H,0
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL		; MULTIPLY BY 16
	LD	DE,DPBASE	; BASE OF PARAMETER BLOCK
	ADD	HL,DE		; HL=.DPB(CURDSK)
	RET

; SETTRK -- SET READ/WRITE TRACK
; ACCEPTS: C = TRACK NUMBER

SETTRK:	LD	A,C
	LD	(SEKTRK),A
	RET

; SETSEC -- SET READ/WRITE SECTOR
; ACCEPTS: C = SECTOR NUMBER

SETSEC:	LD	A,C
	LD	(SEKSEC),A
	RET

; SETDMA -- SET READ/WRITE DMA BUFFER ADDRESS

SETDMA:	LD	(DMAADR),BC
	RET

; SECTRAN -- TRANSLATE SECTOR
; ACCEPTS: BC = LOGICAL SECTOR
;	   DE = TRANSLATIN TABLE ADDRESS	
; RETURNS: HL = PHYSICAL SECTOR

SECTRN:	LD	H,B
	LD	L,C
	RET

; READ CP/M SECTOR ENTRY POINT
; THIS ROUTINE READ THE SELECTED CP/M SECTOR
; INTO SELECTED DMA BUFFER POINTER

READ:	XOR	A	
	LD	(UNACNT),A
	LD	A,1
	LD	(READOP),A		; SET READ OPERATION
	LD	(RSFLAG),A		; MUST READ DATA
	LD	A,WRUAL
	LD	(WRTYPE),A		; TREAT AS UNALLOC
	JP	RDWTCM			; PERFORM THE READ

; WRITE ROUTINE ENTRY POINT
; THIS ROUTINE WRITE THE SELECTED DMA BUUFER POINTER
; INTO SELECTED CP/M SECTOR

WRITE:	XOR	A
	LD	(READOP),A	; SET OPERATION TO WRITE
	LD	A,C		; SAVE WRITE TYPE
	LD	(WRTYPE),A
	CP	WRUAL		; WRITE UNALLOCATED?
	JR	NZ,WRIT10	; CHECK FOR UNALLOC

; WRITING TO AN UNALLOCATED BLOCK

	LD	A,BLKSIZ/128	; NUMBER OF SECTORS/BLOCK
	LD	(UNACNT),A	; UNALLOCATED SECTORS REMAINING
	LD	A,(SEKDSK)	; CP/M DRIVE.
	LD	(UNADSK),A	; TO UNALLOCATED DISK
	LD	A,(SEKTRK)	; CP/M TRACK NO.
	LD	(UNATRK),A
	LD	A,(SEKSEC)	; CP/M SECTOR NO.
	LD	(UNASEC),A

; CHECK FOR WRITE TO UNALLOCATED SECTOR

WRIT10:	LD	A,(UNACNT)	; ANY UNALLOCATED SECTOR REMAIN?
	OR	A
	JR	Z,WRIT30	; SKIP IF NOT

; MORE UNALLOCATED SECTORS IN THIS BLOCK

	DEC	A		; UNACNT = UNACNT-1
	LD	(UNACNT),A
	LD	A,(SEKDSK)	; GET SEEK DISK INTO A
	LD	HL,UNADSK
	CP	(HL)		; SEEK.DSK = UNALL.DSK?
	JR	NZ,WRIT30	; SKIP IF NOT

; DISKS ARE THE SAME

	LD	A,(SEKTRK)	;  CP/M TRACK NO.	
	LD	HL,UNATRK	;  UNALLOCATED TRACK NO.
	CP	(HL)		; SEEK.TRK = UNALL.TRK?
	JR	NZ,WRIT30	; SKIP IF NOT

; TRACKS ARE THE SAME

	LD	A,(SEKSEC)	; GET SEEK SECTOR INTO A
	LD	HL,UNASEC
	CP	(HL)		; SEEK.SEC = UNALL.SEC?
	JR	NZ,WRIT30	; SKIP IF NOT

; MATCH, MOVE "UNASEC" TO NEXT SECTOR FOR FUTURE REF.

	INC	(HL)		; UNASEC = UNASEC+1
	LD	A,(HL)
	CP	CPMSPT		; CHECK END OF SECTOR IN CUR.TRACK?
	JR	C,WRIT20	; SKIP IF NO OVERFLOW

; OVERFLOW TO NEXT TRACK

	LD	(HL),0		; RESET SECTOR
	LD	A,(UNATRK)
	INC	A
	LD	(UNATRK),A	; UNATRK = UNATRK+1

; MATCH FOUND, MARK AS UNNECESSARY READ

WRIT20:	XOR	A
	LD	(RSFLAG),A	; SET PRE-READ FLAG = NO
	JR	RDWTCM		; PERFORM WRITE CP/M SECTOR

; NOT AN UNALLOCATED SECTOR, REQUIRES PRE-READ

WRIT30:	XOR	A
	LD	(UNACNT),A	; RESET UNALLOC. COUNTER = 0
	INC	A
	LD	(RSFLAG),A	; SET PRE-READ FLAG = YES.

; COMMON CODE FOR READ AND WRITE ROUTINE

RDWTCM:	XOR	A
	LD	(ERFLAG),A	; RESET ERROR FLAG
	LD	A,(SEKSEC)	; CONVERT SEEEK SECTOR TO HOST SECTOR
	OR	A		; CLEAR CARRY FLAG
	RRA
	LD	(SEKHST),A	; TEMPORARY SECTOR NO.

; ACTIVE HOST SECTOR?

	LD	HL,HSTACT
	LD	A,(HL)
	LD	(HL),1		; ALWAY BECOMES 1
	OR	A
	JR	Z,RDWT20	; FILL BUFFER IN ACTIVE FLAG = 0

; HOST BUFFER ACTIVE, SAME AS SEEK BUFFER?

	LD	A,(SEKDSK)
	LD	HL,HSTDSK
	CP	(HL)		; SAME DISK?
	JR	NZ,RDWT10	; SKIP IF NOT MATCH

; SAME DISK, SAME TRACK?

	LD	A,(SEKTRK)
	LD	HL,HSTTRK
	CP	(HL)		; SAME TRACK?
	JR	NZ,RDWT10	; SKIP IF NOT MATCH

; SAME DISK, SAME TRACK, SAME BUFFER?

	LD	A,(SEKHST)
	LD	HL,HSTSEC
	CP	(HL)
	JR	Z,RDWT40	; SKIP IF MATCH

; PROPER DISK, BUT NOT CORRECT SECTOR

RDWT10:	LD	A,(HSTWRT)	; WRITE DATA PENDING IN BUFFER?
	OR	A
	JR	Z,RDWT20	; NO NEED TO FLUSH BUFFER
	CALL	WRITEHST	; IF YES, THEN WRITE DATA TO DISK
	JP	NZ,RDWT60	; ERROR IN WRITING TO DISK

; MAY HAVE TO PRE-READ DATA TO HOST BUFFER

RDWT20:	LD	A,(SEKDSK)
	LD	(HSTDSK),A
	LD	A,(SEKTRK)
	LD	(HSTTRK),A
	LD	A,(SEKHST)
	LD	(HSTSEC),A
	LD	A,(RSFLAG)	; CHECK BUFFER REQUIRES PRE-READ
	OR	A
	JR	Z,RDWT30	; NO PRE-READ REQUIRED
	CALL	READHST		; IF YES, THEN READ DATA FROM DISK
	JR	Z,RDWT30	; IF NO ERROR, JUMP TO PROCEED
	XOR	A
	LD	(HSTACT),A	; INDICATE DATA IN BUFFER IS NO GOOD
	JP	RDWT60		; DISK FUNCTION COMPLETE WITH ERROR 

RDWT30:	XOR	A		; INTO BUFFER
	LD	(HSTWRT),A	; RESET PENDING WRITE FLAG

; COPY DATA TO OR FROM BUFFER

RDWT40:	LD	A,(SEKSEC)	; COMPUTE RELATIVE HOST BUFFER ADDRESS
	AND	SECMSK
	LD	H,A
	LD	L,0
	SRL	H
	RR	L		; HL = ((SEKSEC)&SECMSK)*128

; HL HAS RELATIVE HOST BUFFER ADDRESS

	LD	DE,HSTBUF
	ADD	HL,DE
	LD	DE,(DMAADR)	; GET/PUT CP/M DATA BUFFER POINTER
	LD	BC,128		; SET BC = LENGTH TO MOVE
	LD	A,(READOP)	; WHICH WAY?
	OR	A
	JR	NZ,RDWT50	; SKIP IF READ OPERATION

; WRITE OPERATION, MARK AND SWITCH DIRECTION

	LD	A,1
	LD	(HSTWRT),A	; SET WRITE PENDING FLAG ON
	EX	DE,HL		; SOURCE/DESTINATION POINTERS SWAP

; BC INITIALLY 128, DE DESTINATION, HL IS SOURCE POINTER

RDWT50:	LDIR

; DATA HAS BEEN MOVE TO/FROM HOST BUFFER

	LD	A,(WRTYPE)	; CHECK WRITE TYPE OPERATION
	CP	WRDIR		; DIRECTORY WRITE?
	JR	NZ,RDWT60	; IF NOT A DIRECTORY WRITE THEN EXIT

; ALWAYS FLUSH A DIRECTORY BUFFER

	XOR	A
	LD	(HSTWRT),A	; RESET WRITE PENDING FLAG
	CALL	WRITEHST

RDWT60:	LD	A,FDTOUT
	LD	(FDTIME),A
	LD	A,(ERFLAG)
	OR	A
	RET

; HERE ARE THE SECTOR READ/WRITE FUNCTIONS. WE
; WANT TO READ/WRITE TO DISK USING THE PARAMETERS
; SECTOR, TRACK, DMA ADDRESS.

READHST:
	LD	A,RDSCMD	; FDC READ COMMAND
	LD	HL,RDSTAB	; DMA INITIALIZATION TABLE
	JR	RWHSEC		; CODE COMMON TO READ AND WRITE

WRITEHST:
	LD	A,WTSCMD	; FDC WRITE COMMAND
	LD	HL,WTSTAB	; DMA INITIALIZATION TABLE FOR WRITE

RWHSEC:	LD	(COMAND),A
	LD	(DMATAB),HL
	LD	HL,FDTIME
	LD	(HL),0		; DISABLE MOTOR 
	INC	HL
	LD	A,(HL)		; CHECK FLOPPY DISK MOTOR
	LD	(HL),1		; INDICATE FLOPPY DISK MOTOR IS ON
	OR	A
	LD	A,(FDDBYT)
	OUT	(FDD),A		; NOW TURN ON FLOPPY
	JR	NZ,RWHS02	; JUMP IF MOTOR ALREADY ON
; WAIT 250 MS FOR MOTOR TO GET SPEED (38461 EXACT)

	LD	HL,38500
RWHS01:
	DEC	HL
	LD	A,H
	OR	L
	JR	NZ,RWHS01
RWHS02:
	LD	A,(HSTDSK)
	LD	HL,DRIVE	; CURRENT DRIVE
	CP	(HL)		; SAME DRIVE?
	CALL	NZ,SELDRV	; NO, HARDWARE SELECT THE DRIVE 
	CALL	SELSID		; SELECT THE PROPER SIDE	

; READY TO READ OR WRITE A PHYSICAL SECTOR

	LD	A,NOTRYS	; NO. OF RETRIES
	LD	(RETRY),A	; ON DISK I/O OPERATION

RWHS10:	LD	HL,(DMATAB)	; GET DMA INITIALIZE PARAMETER POINTER
	CALL	PRTINI		; DO DMA INITIALIZATION.
	CALL	SEEK		; SEEK THE USER DEFINED TRACK
	JR	NZ,RWHS20	; ADJUST RETRY COUNTER
	LD	A,(COMAND)	; SET UP FDC
	OUT	(FDCCMD),A	; COMMAND REGISTER
	CALL	WAIT		; WAIT FOR CONTROLLER NOT BUSY
	JR	NZ,RWHS20	; ERROR ON READ/WRITE
	LD	A,(ERFLAG)	; RETURN CODE
	OR	A		; SET/CLEAR Z FLAG
	RET			; DISK I/O SUCCESSFUL

; WE HAD AN ERROR ON READ/WRITE OPERATION

RWHS20:	CALL	RESDMA		; RESET THE DMA ON ABORT
	LD	A,(ERFLAG)	; IF DRIVE NOT READY,
	BIT	FDCRDY,A	; DON'T BOTHER WITH RETRIES
	RET	NZ		; RETURN ERROR FLAG IN A

	LD	HL,RETRY	; MORE RETRIES LEFT?
	LD	A,(HL)
	DEC	(HL)		; BUMP DOWN COUNT
	OR	A
	JR	Z,RWHS30	; ALL DONE, WE FAILED.
	CALL	RESTOR		; SEEK TRACK 0.
	JR	RWHS10		; LOOP BACK FOR ANOTHER SHOT.

RWHS30:	CALL	ERRPRT		; PRINT DETAILED ERROR MESSAGE
	LD	A,(ERFLAG)	; RETURN ERROR
	OR	A		; SET/CLEAR Z FLAG.
	RET


; END OF 802FDISK.MAC
