;********************************************************
;*							*
;*	DISK I/O DRIVER FOR BETTERBOARD	24-JUNE-82	*
;*							*
;********************************************************
;
;
;	EQUATES FOR DISK CONTROLLER PORTS AND COMMAND CODES
;
STSREG	EQU	WD179X+0	;STATUS REGISTER
CMDREG	EQU	WD179X+0	;COMMAND REGISTER
TRKREG	EQU	WD179X+1	;TRACK REGISTER
SECREG	EQU	WD179X+2	;SECTOR REGISTER
DATREG	EQU	WD179X+3	;DATA REGISTER
;
;
RDCMD	EQU	10001000B	;READ COMMAND
RIDCMD	EQU	11000000B	;READ ID COMMAND
WRTCMD	EQU	10101000B	;WRITE COMMAND
SKCMD	EQU	00011100B	;SEEK COMMAND
RSTCMD	EQU	00001000B	;RESTORE COMMAND
FINCMD	EQU	11010000B	;FORCE INTERRUPT COMMAND
STEPOUT	EQU	01100000B	;STEP OUT COMMAND
STEPIN	EQU	01000000B	;STEP IN COMMAND
;
;
;
;
SELECT:
	LD	A,C		;GET UNIT# PASSED IN C AND
	CP	4		; CHECK FOR MAXIMUM VALID#
	RET	NC		;ERROR IF UNIT# > 3

	CALL	DSEL		;DERRIVE NEW DRIVE SELECT BIT PATTERN
	CALL	READY		;EMIT NEW SELECT BITS AND TEST READY
	JR	NZ,SELX		;JUMP IF DRIVE NOT READY

	LD	HL,UNIT
	LD	D,0
	LD	E,(HL)		;LOAD DE WITH LAST SELECTED DRIVE UNIT#
	LD	(HL),C		;THEN STORE NEW UNIT# PASSED IN C

	LD	HL,TRKTAB
	ADD	HL,DE		;INDEX INTO HEAD POSITION TABLE
	LD	A,(TRACK)
	LD	(HL),A		;STORE PREVIOUS DRIVE'S TRACK NUMBER
	LD	E,4
	ADD	HL,DE		;NOW INDEX TO DENSITY BYTE FOR UNIT
	LD	A,(DSKTYP)
	AND	00000001B
	LD	(HL),A		;REMEMBER CURRENT DENSITY CONTROL BIT

	LD	HL,TRKTAB
	LD	E,C		;INDEX INTO TABLE TO GET LAST KNOWN
	ADD	HL,DE		; HEAD POSITION OF NEW DRIVE
	LD	A,(HL)
	OUT	(TRKREG),A	;OUTPUT THE DRIVE'S CURRENT HEAD
	LD	(TRACK),A	; POSITION TO THE 179X AND SAVE
	LD	E,4
	ADD	HL,DE		;INEDX TO NEW DRIVE'S DENSITY SETTING
	LD	A,(DSKTYP)
	AND	11111110B	;MERGE IN NEW DENSITY CONTROL BIT
	OR	(HL)
	CALL	SETDENS		;SET DENSITY CONTROLS
	XOR	A		;INDICATE SELECT WAS SUCCESSFUL

SELX:	CALL	SETTIMER	;RESET DRIVE TURN-OFF TIMER
	RET
;
;
;
;
DSEL:
	LD	HL,SELTAB	;POINT TO DRIVE SELECT BITS TABLE
	AND	00000011B
	LD	D,0
	LD	E,A
	ADD	HL,DE		;ADD UNIT# TO HL TO INDEX INTO TABLE
	LD	A,(HL)
	LD	(SELCPY),A	;STORE NEW STATE OF SELECT/MUX PORT
	RET

SELTAB:	DEFB	10001010B	;BITS FOR UNIT #0
	DEFB	01001010B	;BITS FOR UNIT #1
	DEFB	00101010B	;BITS FOR UNIT #2
	DEFB	00011010B	;BITS FOR UNIT #3
;
;
;
;
;
HOME:
	LD	C,0		;TREAT HOME AS SEEK TO TRACK ZERO
SEEK:
	CALL	READY
	JR	NZ,SEEKX	;EXIT IF DRIVE NOT READY

	LD	A,(TRACK)
	SUB	C		;TEST IF ALREADY AT DESIRED TRACK
	JR	Z,SEEKX		;EXIT WITH ACC=0 IF SO

	LD	A,(TRACK)	;GET CURRENT TRACK# INTO ACC
	CP	255		;TEST IF HEAD POSITION IS
	JR	NZ,SEEK2	; KNOWN GOOD AND JUMP IF SO

	LD	A,RSTCMD+3
	CALL	DISKOP		;EXECUTE RESTORE AT SLOWEST STEP SPEED
	XOR	00000100B	;COMPLIMENT TRK0 STATUS BIT
	AND	10000101B
	JR	NZ,SEEKX	;EXIT IF RESTORE CANNOT BE DONE

SEEK2:	LD	B,A		;PUT STARTING TRACK# INTO B
	CALL	FINDTRK		;GO LOOKING FOR TRACK# IN C
	PUSH	AF
	LD	A,C
	LD	(TRACK),A	;STORE FINAL TRACK# (C=255 IF ERROR)
	OUT	(TRKREG),A	;ALSO PUT IN 179X TRACK REGISTER
	POP	AF

SEEKX:	CALL	SETTIMER	;RESET DRIVE TURN-OFF TIMER
	RET			;RETURN WITH COMPLETION STATUS IN ACC
;
;
;
;
FINDTRK:
	LD	A,7
	LD	(FNDTRY),A	;SET RETRY COUNT FOR HEAD POSITIONING
FTRK2:	PUSH	BC
	CALL	STEP		;HAVE A GO AT STEPPING TO TRACK IN C
	POP	BC
	JR	NZ,FTRK4	;JUMP IF READY/NOT FOUND/CRC/BUSY ERROR

	IN	A,(SECREG)
	LD	B,A		;PUT ACTUAL CURRENT TRACK# INTO B
	SUB	C		;COMPARE IF WE GOT THERE THIS TIME
	RET	Z		;EXIT WITH ACC=0 IF TRACK# VERIFIED

	LD	A,(FNDTRY)
	CP	7
	JR	Z,FTRK3		;JUMP IF ON FIRST OR SECOND RETRY
	LD	HL,SPEED
	INC	(HL)		;ELSE REDUCE STEP SPEED BY 1 MILLISEC
FTRK3:	DEC	A
	LD	(FNDTRY),A	;DECREMENT SEEK RETRY COUNT AND KEEP
	JR	NZ,FTRK2	; TRYING OVER (POSSIBLY AT SLOWER RATE)

	LD	A,00010000B	;INDICATE PERMANENT SEEK ERROR
	OR	A
FTRK4:	LD	C,255		;SET C=255 AS BAD TRACK INDICATOR
	RET			;RETURN WITH SEEK ERROR STATUS IN A
;
;
;
;
;
;
;	STEP FROM TRACK# IN B TOWARDS TRACK# IN C
;
STEP:
	LD	D,STEPOUT	;D WILL CARRY STEP OUT/IN COMMAND
	LD	A,B
	SUB	C		;GET DIFFERENCE BETWEEN TRACK NUMS
	JR	NC,STEP2	;JUMP IF SEEK TOWARDS OUTER TRACKS
	LD	D,STEPIN
	LD	A,C
	SUB	B		;ELSE SWAP DIRECTION AND DIFFERENCE
STEP2:	JR	Z,STEP4		;GO DO VERIFY IF NO STEPS NEEDED

	LD	(STPCNT),A	;ELSE STORE STEP COUNT AND STEP IN/OUT
	LD	A,D		; COMMAND BYTE CARRIED IN D
	LD	(STPCMD),A
	LD	A,1
	LD	(STPDLY),A
	LD	HL,DOSTEP	;START STEPPER FINITE STATE MACHINE
	LD	(STPVEC),HL
	LD	A,(SELCPY)
	RES	3,A		;MAKE 179X TEST INPUT LOW TO DISABLE
	OUT	(SELMUX),A	; INTERNAL OPERATION TIME DELAYS
	LD	A,10000001B
	OUT	(CTCB2),A	;START CTC 1 MILLISECOND INTERRUPT
STEP3:	LD	A,(STPCNT)
	OR	A
	JR	NZ,STEP3	;LOOP UNTIL STEP COUNTER REACHES ZERO
	LD	A,(SELCPY)
	SET	3,A		;TAKE 179X TEST PIN BACK HIGH
	OUT	(SELMUX),A

STEP4:	CALL	VERIFY		;ELSE READ AN ID-MARK TO VERIFY SEEK
STEPX:	RET
;
;
;
;	.... ROUTINES FOR INTERRUPT DRIVEN SEEK FUNCTION ....
;
DOSTEP:
	LD	HL,STPDLY
	DEC	(HL)		;DECREMENT STEP SPEED DELAY COUNT
	RET	NZ		;EXIT IF NOT TIME TO ISSUE STEP CMD

	LD	A,(STPCMD)
	OUT	(CMDREG),A	;OUTPUT STEP IN/OUT COMMAND TO 179X
	LD	A,(STPCNT)
	DEC	A		;DECREMENT STEP COUNT
	JR	Z,DOSTP2	;JUMP IF LAST STEP TO BE DONE

	LD	(STPCNT),A	;ELSE STORE DECREMENTED COUNT
	LD	A,(SPEED)
	LD	(HL),A		;STORE STEP SPEED FOR NEXT OPERATION
	RET
;
DOSTP2:	LD	A,(SETTLE)
	LD	(HL),A		;STORE HEAD SETTLING TIME PARAMETER
	LD	HL,DOSETTLE
	LD	(STPVEC),HL	;DO SETTLING DELAY ON NEXT INTERRUPT
	RET
;
;
;
DOSETTLE:
	LD	HL,STPDLY
	DEC	(HL)		;DECREMENT SETTLING TIME DELAY COUNT
	RET	NZ

	XOR	A
	LD	(STPCNT),A	;SET STEP COUNT TO ZERO WHEN FINISHED
	LD	HL,SEEKX
	LD	(STPVEC),HL	;PUT SEEK FSM TO SLEEP
	LD	A,00000001B
	OUT	(CTCB2),A	;STOP 1 MILLISECOND INTERRUPT
	RET
;
;
;
;
VERIFY:
	LD	A,RIDCMD
	CALL	DISKOP		;READ NEXT ID-MARK TO VERIFY SEEK
	AND	10011001B
	JR	Z,VERFY2	;JUMP IF ID MARK READ SUCCESSFULLY

	CALL	FLIPDENS	;ELSE SWITCH DISK DENSITY CONFIGURATION
	LD	A,RIDCMD
	CALL	DISKOP		;TRY AGAIN IN NEW DENSITY
	AND	10011001B
VERFY2:	PUSH	AF		;SAVE STATUS OF READ-ID
	CALL	FORCE		;CLEAR OVERRUN AND DRQ BITS IN 179X
	POP	AF
	RET	Z		;EXIT IF AN ID MARK WAS FOUND

	PUSH	AF
	CALL	FLIPDENS	;ELSE GO BACK TO ORIGINAL DENSITY
	POP	AF
	RET			;RETURN WITH ERROR INDICATED
;
;
;
;
FLIPDENS:
	LD	A,(DSKTYP)
	XOR	00000001B	;COMPLIMENT DENSITY BIT OF DRIVE TYPE
SETDENS:
	LD	(DSKTYP),A
	AND	00000011B
	LD	B,0
	LD	C,A
	LD	HL,SMCTAB
	ADD	HL,BC		;INDEX INTO SMC DATA SEPARATOR CONTROL
	ADD	HL,BC		; BYTE TABLE FOR NEW DENSITY SETTING
	ADD	HL,BC
	LD	B,3
	LD	C,PORT0
	OTIR			;OUTPUT 3 BYTES TO SET DISK DENSITY
	RET

SMCTAB:	DEFB	SMC1+ON		;8 INCH SINGLE DENSITY
	DEFB	SMC2+OFF
	DEFB	DDEN+ON
	DEFB	SMC1+OFF	;8 INCH DOUBLE DENSITY
	DEFB	SMC2+OFF
	DEFB	DDEN+OFF
	DEFB	SMC1+OFF	;5 INCH SINGLE DENSITY
	DEFB	SMC2+ON
	DEFB	DDEN+ON
	DEFB	SMC1+ON		;5 INCH DOUBLE DENSITY
	DEFB	SMC2+OFF
	DEFB	DDEN+OFF
;
;
;
;
;
READID:
	CALL	READY		;CLEAR DISK CONTROLLER
	JR	NZ,RDIDX	;EXIT IF DRIVE NOT READY

	LD	B,RIDCMD
	CALL	RDWRT		;READ ID RECORD INTO BUFFER (HL)
	JR	NZ,RDIDX	;EXIT IF DISK ERROR

	LD	HL,(IOPTR)
	LD	DE,6
	ADD	HL,DE		;POINT TO 7TH BYTE AFTER ID RECORD
	LD	A,(DSKTYP)
	LD	(HL),A		;STORE DISK TYPE BYTE THERE
	XOR	A

RDIDX:	CALL	SETTIMER	;RESET DRIVE TURN-OFF TIMER
	RET
;
;
;
;
WRITE:
	CALL	READY		;CLEAR THE DISK CONTROLLER
	JR	NZ,WRITEX	;EXIT IF DRIVE NOT READY

	BIT	6,A
	JR	NZ,WRITEX	;EXIT IF DISK IS WRITE-PROTECTED

	LD	B,WRTCMD
	CALL	RDWRT

WRITEX:	CALL	SETTIMER	;RESET DISK TIMER
	RET
;
;
;
;
READ:
	CALL	READY		;CLEAR DISK CONTROLLER
	JR	NZ,READX	;EXIT IF DRIVE NOT READY

	LD	B,RDCMD
	CALL	RDWRT

READX:	CALL	SETTIMER	;RESET DISK TIMER
	RET
;
;
;
;
;
RDWRT:
	LD	(IOPTR),HL	;STORE DISK I/O DATA POINTER
	LD	A,C
	LD	(SECTOR),A	;STORE SECTOR# FOR READ/WRITE
	LD	A,B
	LD	(CMDTYP),A	;STORE READ/WRITE/READID COMMAND BYTE
	LD	A,(MAXRWT)
	LD	(RWTRY),A	;SET DISK OPERATION RE-TRY COUNT

RW1:	LD	A,(SECTOR)	;OUTPUT SECTOR NUMBER FOR READ/WRITE
	OUT	(SECREG),A
	LD	HL,DMAPGM	;PREPARE TO OUTPUT DMA INITIALIZATION
	LD	B,8
	LD	C,DMA
	OTIR			;FIRST 6 BYTES ARE DMA RESETS
	LD	DE,(BLKSIZ)
	OUT	(C),E		;NEXT TWO BYTES ARE MAX DMA BLOCKCOUNT
	OUT	(C),D
	LD	B,3
	OTIR			;NEXT 3 BYTES ARE CONSTANTS
	LD	DE,(IOPTR)
	OUT	(C),E		;NEXT 2 BYTES ARE TRANSFER ADDRESS
	OUT	(C),D
	OUTI			;NEXT BYTE SETS READY/WAIT/RESTART
	LD	B,4
	LD	A,(CMDTYP)	;GET READ OR WRITE COMMAND BYTE
	CP	WRTCMD
	JR	Z,RW2		;JUMP IF DISK OPERATION IS A WRITE
	INC	HL
	INC	HL		;ELSE SKIP NEXT TWO BYTES IN DMA PGM
	LD	B,2
RW2:	OTIR			;OUTPUT LAST OF DMA PROGRAM BYTES
	CALL	DISKOP		;DO 179X COMMAND AND LOOP TILL INTRQ
	LD	B,4
	OTIR			;DISABLE DMA AND INITIATE READ SEQUENCE
	IN	L,(C)
	IN	H,(C)		;READ BYTECOUNT INTO HL
	AND	10011111B	;MASK READY/RNF/CRC/OVERRUN/DRQ/BUSY
	RET	Z		;RETURN IF NO DISK I/O ERRORS

	LD	(ERRTYP),A
	CALL	RECOVER		;DO READ/WRITE ERROR RECOVERY ROUTINE
	JR	NZ,RW3		;SKIP RETRY IF IRRECOVERABLE ERROR
	LD	HL,RWTRY
	DEC	(HL)
	JR	NZ,RW1		;ELSE DECREMENT RETRY COUNT TILL=0
RW3:	LD	A,(ERRTYP)
	OR	A
	RET			;RETURN ORIGINAL ERROR CONDITION IN ACC
;
;
;
;
RECOVER:
	LD	B,A
	AND	10000111B	;ISOLATE READY/OVERRUN/DRQ/BUSY ERRORS
	JR	Z,RECOV1	; AND JUMP IF NONE OF THOSE IS SET

	CALL	FORCE		;CLEAR ERROR FLAGS IN 179X STATUS REG
	LD	A,B
	OR	A		;RETURN ERROR STATUS IN ACC
	RET
;
;	ARRIVE HERE IF CRC OR RECORD-NOT-FOUND ERROR
;
RECOV1:	BIT	4,B
	JR	NZ,RECOV3	;JUMP IF SECTOR ID RECORD NOT FOUND
;
;	ERROR IS DUE TO BAD CRC IN DATA OR ID FIELD
;
RECOV2:	LD	A,(RWTRY)
	LD	HL,MAXRWT
	SUB	(HL)		;TEST IF THIS IS FIRST CRC ERROR RETRY
	RET	Z		;IF SO EXIT AND ALLOW RETRY TO BE DONE

	IN	A,(TRKREG)	;ELSE PREPARE TO WIGGLE BACK AND FORTH
	LD	B,A		; TO AN ADJACENT TRACK TO RE-CALIBRATE
	OR	A		; AND REMOVE POSSIBLE MEDIA CONTAMINANT
	JR	NZ,RCOV2A
	LD	C, 1		;STEP TO TRACK#1 IF ON TRACK# 0
	JR	RCOV2B
;
RCOV2A:	DEC	A		;STEP TO NEXT OUTER TRACK
	LD	C,A
RCOV2B:	PUSH	BC
	CALL	STEP		;STEP HEAD TO ADJACENT TRACK
	POP	DE
	LD	B,E		;EXCHANGE CONTENTS OF B AND C
	LD	C,D
	CALL	STEP		;STEP BACK TO ORIGINAL TRACK
	RET
;
;	ARRIVE HERE IF RECORD-NOT-FOUND ERROR
;
RECOV3:	LD	A,(DSKTYP)	;SAVE DENSITY CONTROL BYTE BEFORE
	PUSH	AF		; CALLING TRACK VERIFY ROUTINE
	CALL	VERIFY		;DO A READ-ID COMMAND TO SEE IF ANY
	POP	DE		; SECTOR ON THIS TRACK CAN BE READ
	RET	NZ		;ERROR IF NO ID MARK FOUND

	LD	A,(CMDTYP)
	CP	RIDCMD		;BYPASS TRACK# CHECK IF DOING READ-ID
	JR	Z,RECOV4
	IN	A,(SECREG)	;TEST IF CONTENTS OF TRACK REGISTER
	LD	B,A		; MATCHES TRACK# FROM ID MARK JUST
	IN	A,(TRKREG)	; READ (179X PUTS TRK# IN SECTOR REG)
	LD	C,A
	CP	B
	JR	Z,RECOV4	;JUMP IF HEAD IS ON CORRECT TRACK

	CP	255		;ERROR IF TRKREG SET TO 255 PREVIOUSLY
	JR	Z,RECOV5
	CALL	FINDTRK		;ELSE GO TO TRACK=C FROM TRACK=B
	PUSH	AF
	LD	A,C		;PUT FINAL TRACK# IN 179X TRACK
	OUT	(TRKREG),A	; REGISTER (C=255 IF SEEK ERROR)
	POP	AF
	RET			;RETURN COMPLETION STATUS IN ACC
;
;	ERROR IS DUE TO NON-EXISTENT SECTOR# OR BEING IN WRONG DENSITY
;
RECOV4:	LD	A,(DSKTYP)
	CP	D		;SEE IF DENSITY WAS CHANGED BY 'VERIFY'
	JR	Z,RECOV5	; AND EXIT WITH RNF ERROR IF NOT
	XOR	A		;CLEAR ACC TO INDICATE RETRY SHOULD
	RET			; BE DONE NOW THAT DENSITY IS SET RIGHT
;
RECOV5:	LD	A,00010000B
	OR	A		;INDICATE ERROR DUE TO NON-EXISTENT
	RET			; SECTOR OR INDETERMINATE TRACK#
;
;
;
;
DMAPGM:	DEFB	11000011B	;DMA RESET COMMAND
	DEFB	11000011B
	DEFB	11000011B
	DEFB	11000011B
	DEFB	11000011B
	DEFB	11000011B
	DEFB	01101101B	;XFER A->B, PORT A AND BYTCNT FOLLOWS
	DEFB	DATREG

	DEFB	00101100B	;PORT A IS I/O, FIXED ADDRESS
	DEFB	00010000B	;PORT B IS MEMORY, INCREMENTING ADDRESS
	DEFB	10001101B	;SINGLE BYTE MODE, PORT B FOLLOWS

	DEFB	10001010B	;HIGH=RDY, /CE NOT MUXED, NO RESTART

	DEFB	11001111B	;LOAD DESTINATION ADDRESS
	DEFB	00000001B	;XFER B->A, NOTHING FOLLOWS
	DEFB	11001111B	;LOAD SOURCE ADDRESS
	DEFB	10000111B	;ENABLE DMA

	DEFB	10000011B	;DISABLE DMA
	DEFB	10111011B	;READ MASK FOLLOWS
	DEFB	00000110B	;MASK FOR BYTECOUNT HIGH/LOW
	DEFB	10100111B	;INITIATE READ SEQUENCE
;
;
;
;
;
DISKOP:
	CALL	CMDOUT
	XOR	A		;RESET SECONDS-NOT-READY COUNT FOR
	LD	(RDYCNT),A	; FOR USE AS LOOP EXIT TIMER
DSKOP2:	IN	A,(STSREG)
	BIT	0,A		;TEST DISK CONTROLLER BUSY STATUS BIT
	RET	Z		;EXIT IF BUSY BIT GOES AWAY

	LD	A,(RDYCNT)	;ELSE TEST IF NOT-READY COUNTER HAS
	OR	A		; BEEN BUMPED BY BACKGROUND SCAN
	JR	Z,DSKOP2	;KEEP LOOKING IF STILL READY

	CALL	FORCE		;ELSE ABORT DISK COMMAND
	LD	A,00000001B
	OR	A		;RETURN WITH 179X BUSY ERROR INDICATED
	RET
;
;
;
;
CMDOUT:
	OUT	(CMDREG),A	;OUTPUT DISK CONTROLLER COMMAND BYTE
	LD	A,12
COUT2:	DEC	A
	JR	NZ,COUT2	;DELAY 50 MICROSECONDS
	RET
;
;
;
;
FORCE:
	LD	A,FINCMD	;LOAD FORCE-INTERRUPT-IMMEDIATE CMD
	CALL	CMDOUT		;CLEAR 179X AND LATCH READY/HLD/TK0 ETC
	IN	A,(STSREG)	;READ STATUS REGISTER CONTENTS
	RET
;
;
;
;
;
READY:
	LD	A,1
	LD	(INUSE),A	;SET DISKS-ACTIVE FLAG FOR BACKGROUND
	LD	A,(SELCPY)
	OUT	(SELMUX),A	;OUTPUT CURRENT DRIVE SELECT/MUX BITS
	LD	A,(DSKCNT)
	OR	A		;TEST IF BACKGROUND TIMER EQUALS ZERO
	JR	Z,READY2	;JUMP IF DRIVES HAVE BEEN STOPPED

	CALL	FORCE		;CLEAR CONTROLLER AND TEST DRIVE READY
	BIT	7,A
	RET	Z		;EXIT IF READY

READY2:	CALL	SPINUP		;ELSE START THE DRIVES AND CHECK READY
	RET	NZ		;EXIT IF NOT RUNNING UP TO SPEED

	CALL	FORCE
	BIT	7,A		;ELSE TEST THE DRIVE READY STATUS
	RET			; AND RETURN TYPE 1 STATUS IN ACC
;
;
;
;
SETTIMER:
	PUSH	AF		;SAVE COMPLETION STATUS CARRIED IN ACC
	LD	A,(NSTOP)
	LD	(DSKCNT),A	;SET INDEX COUNTER FOR DISK TIMEOUT
	XOR	A
	LD	(INUSE),A	;CLEAR DISKS-ACTIVE FLAG FOR BACKGROUND
	POP	AF
	RET
;
;
;
;
SPINUP:
	PUSH	BC
	LD	A,MOTOR+ON
	OUT	(PORT0),A	;TURN ON THE MOTOR CONTROL LINE
	LD	A,HLDTIM+ON
	OUT	(PORT0),A	;ACTIVATE THE HEAD LOAD SOLENOIDS
	IN	A,(CTCA1)
	LD	C,A		;PUT CURRENT INDEX PULSE COUNT IN C
	LD	A,(NREVS)
	LD	B,A		;PUT REVS-TO-READY PARAM INTO B
	XOR	A
	LD	(RDYCNT),A	;CLEAR SECONDS-NOT-READY COUNTER
	CALL	FORCE		;RESET 179X SO READY CAN BE TESTED
SPIN2:	LD	A,(RDYCNT)
	CP	4		;TEST IF DRIVES HAVE BEEN NOT-READY
	JR	NC,SPIN4	; FOR MORE THAT 4 SECONDS
	IN	A,(STSREG)
	BIT	7,A
	JR	NZ,SPIN2	;STAY IN INNER LOOP TILL DRIVE READY

	IN	A,(CTCA1)	;READ INDEX PULSE COUNT FROM CTC
	SUB	C		;COMPUTE CHANGE IN INDEX COUNTER CTC
	NEG			;RESULT IS NEGATIVE, SO SWITCH IT
	CP	B
	JR	C,SPIN2		;LOOP UNTIL SPECIFIED NUMBER OF REVS
	XOR	A
	JR	SPIN5 		;EXIT WITH DRIVE READY INDICATED
;
SPIN4:	LD	A,10000000B	;INDICATE DRIVE-NOT-READY ERROR
SPIN5:	POP	BC
	OR	A		;RETURN DRIVE READY STATUS IN A
	RET
;
;
;
;	.... BACKGROUND DISK ACTIVITY MONITOR ....
;
DISKTEST:
	LD	HL,OLDCTC	;POINT TO LAST INDEX COUNTER VALUE
	IN	A,(CTCA1)	;READ INDEX PULSE COUNT FROM CTC
	LD	C,(HL)
	LD	(HL),A		;LOAD C WITH LAST COUNT AND STORE NEW
	LD	A,(INUSE)	;TEST STATE OF DISK ACTIVITY FLAG
	OR	A
	JR	Z,DTST2		;DO DRIVE TURN-OFF STUFF IF NOT IN-USE
;
;
;	ARRIVE HERE IF DISK I/O IS CURRENTLY BEING DONE
;
	LD	A,(HL)
	CP	C		;TEST IF ANY INDEX PULSES IN LAST SEC
	RET	NZ		;EXIT IF DISK IS STILL ROTATING

	LD	HL,RDYCNT
	INC	(HL)		;BUMP SECONDS-NOT-READY COUNT
	RET
;
;
;	ARRIVE HERE IF NO DISK OPERATIONS ARE GOING ON
;
DTST2:	LD	A,C
	SUB	(HL)		;COMPUTE PULSES SINCE LAST INTERRUPT
	JR	Z,DTST3		;TURN DRIVES OFF IF NO INDEX PULSES

	LD	B,A
	LD	A,(DSKCNT)
	SUB	B		;SUBTRACT COUNT DIFFERENCE FROM TIMER
	JR	C,DTST3		;JUMP IF DISK TIMEOUT
	JR	Z,DTST3

	LD	(DSKCNT),A	;ELSE STORE UPDATED VALUE FOR NEXT TIME
	RET
;
DTST3:	LD	A,1		;SET FLAG TO STOP ANY FURTHER ACCESS TO
	LD	(INUSE),A	; THIS POINT UNTIL NEXT DISK OPERATION
	XOR	A
	LD	(DSKCNT),A	;CLEAR COUNTER TO INDICATE DRIVES-OFF
	LD	A,MOTOR+OFF
	OUT	(PORT0),A	;TURN OFF THE MOTOR CONTROL LINE
	LD	A,HLDTIM+OFF
	OUT	(PORT0),A	;DEACTIVATE THE HEAD LOAD LINE
	LD	A,(SELCPY)	;GET CURRENT DATA AT SELECT/MUX PORT,
	AND	00001111B	; MASK ALL DRIVE SELECT BITS TO ZEROS
	OUT	(SELMUX),A	;AND RE-OUTPUT TO DESELECT DRIVES
	RET
;
;
;
;
;
