;-----------------------------------------------------
;
;  DISK DRIVER FOR MICROPOLIS FLEXIBLE DISK SUBSYSTEM
;
;  COPYRIGHT MICROPOLIS CORPORATION 8 JUNE 1977
;
;  Updated 7/14/13 by Mike Douglas to support
;	4MHz or 2MHz timing loop.
;
;-----------------------------------------------------
;
;    1) CALLING SEQUENCE:
;
;	LXI H,UDCB 	POINT HL TO USER
;	CALL DSKIO	DCB & PERFORM
;	JNZ ERROR	OPERATION
;
;	UDCB IS THE USER'S DISK CONTROL
;	BLOCK WHICH DEFINES THE OPERATION
;	TO BE PERFORMED AND IS STRUCTURED
;	AS FOLLOWS:
;
;	UDCB+0 FUNCTION CODE
;	  0 SEEK TRACK ONLY
;	  1 SEEK AND READ SECTOR
;	  2 SEEK AND WRITE SECTOR
;	  3 SEEK AND VERIFY SECTOR
;
;	WRITE OPERATIONS CONSIST OF:
;	1) VERIFY THE TRACK/SECTOR ID
;	   IN THE SECTOR IMMEDIATELY
;	   PRECEEDING THE DESIRED SECTOR
;	2) PERFORM THE WRITE OPERATION
;	3) THE SECTOR WRITTEN IS THEN
;	   VERIFIED BY A READ-AFTER-WRITE
;	   CHECKSUM READ
;	NOTE:THE ID CHECK AND READ AFTER
;	WRITE CHECKS CAN BE OVERRIDDEN
;	BY CONTROL FLAGS IN UDCB+1
;	FOR WRITING ON UNFORMATTED DISKS
;
;	UDCB+1 CONTROL FLAGS/UNIT SELECT
;	  BIT 	FUNCTION
;	  0-1 	UNIT ADDRESS
;	   6 	READ-AFTER-WRITE CHECK
;		CONTROL:0=PERFORM,
;			1=INHIBIT
;	   7 	PRE-WRITE ID CHECK
;		CONTROL: 0=PERFORM,
;			 1-INHIBIT
;	UDCB+2 	   SECTOR ADDRESS (0-15)
;	UDCB+3 	   TRACK ADDRESS (0-76(34))
;	UDCB+4&5   BUFFER ADDRESS
;		BUFFER ADDRESS IS THE START
;		ADDRESS OF THE READ/WRITE
;		BUFFER TO BE USED IN
;		PERFORMING THE OPERATION.
;
;		ALL OPERATIONS
;		REQUIRE A 268 BYTE BUFFER
;		ORGANIZED AS FOLLOWS:
;		BYTE 0 -- TRACK ID
;		BYTE 1 -- SECTOR ID
;		BYTE 2-267 -- DATA
;
;		BYTES 0 AND 1 ARE FILLED
;		IN AS NECESSARY BY THE
;		DRIVER
;
;    2) THE DISK I/O DRIVER RETURNS WITH
;	THE CONDITION CODE SET TO Z IF
;	THE OPERATION WAS SUCCESSFUL AND
;	NZ IF AN ERROR OCCURRED. THE
;	A REGISTER WILL CONTAIN AN ERROR
;	CODE AS FOLLOWS:
;	   1 -- PERMANENT I/O ERROR - AN
;		UNRECOVERABLE DISK ERROR
;		OCCURRED
;	   2 -- PARAMETER ERROR - ONE OF THE
;		PARAMETERS IN THE DCB IS
;		INVALID
;	   3 -- DRIVE NOT UP - THE SELECTED
;		DRIVE IS NOT READY
;	   4 -- WRITE PROTECT - THE SELECTED
;		DRIVE IS WRITE PROTECTED AND
;		A WRITE OPERATION wAS
;		SPECIFIED
;
;    3) INITIALIZATION REQUIREMENTS:
;
;	1) THE DRIVER CONTAINS A TABLE
;	LABLED "TRACK" WHICH CONTAINS
;	THE CURRENT TRACK POSITION FOR
;	EACH DRIVE CONNECTED TO THE
;	CONTROLLER. EACH ENTRY MUST BE
;	INITIALIZED TO FF TO CAUSE THE
;	TRACK POSITION OF EACH DRIVE TO
;	BE RE-CALIBRATED THE FIRST TIME
;	IT IS ACCESSED
;
;	2) THE PARAMETER LABELED "TRKMX"
;	MUST BE SET TO THE HIGHEST
;	TRACK ADDRESS WHICH IS 76 FOR
;	MOD II SUBSYSTEMS AND 34 FOR
;	MOD I SUBSYSTEMS
;
;	3) THE 16 BIT PARAMETER LABELED
;	"DADR"MUST BE SET TO THE ADDRESS
;	OF THE DISK CONTROLLER WHICH IS
;	THE BOOT PROM ADDRESS+200H
;
DSKIO 	DI
	PUSH 	B		;SAVE REGISTERS
	PUSH 	D
	PUSH 	H
	LXI 	H,0		;SAVE STACK POINTER
	DAD 	SP
	SHLD 	STACK
	POP 	H		;GET POINTER TO
	PUSH 	H		;USER'S DCB
	LXI 	D,DCB		;COPY USER DCB TO
	MVI 	B,DCBLEN 	;INTERNAL dcb
DS010	MOV 	A,M
	STAX 	D
	INX 	H
	INX 	D
	DCR 	B
	JNZ 	DS010

; VALIDATE DCB PARAMETERS

	LXI 	H,DCB		;FUNCTION MUST BE
	MOV 	A,M		;3 OR LESS
	CPI 	4
	JNC 	PARMER 		;PARAMETER ERROR
	INX 	H
	MOV 	A,M		;UNIT ADDRESS MUST
	ANI 	03FH		;BE LESS THAN 4
	CPI 	4
	JNC 	PARMER
	INX 	H
	MOV 	A,M		;SECTOR MUST BE
	CPI 	16		;15 OR LESS
	JNC 	PARMER
	INX 	H
	LDA 	TRKMX 		;TRACK MUST BE LESS
	SUB 	M		;THAN OR EQUAL TO
	JM 	PARMER 		;MAX TRACK

; ENSURE DRIVE IS OPERATIONAL

	CALL 	SLCT

; SEEK TO DESIRED TRACK

	CALL 	SEEK

; GET FUNCTION PARAMETER FROM DCB
; AND PERFORM ANY OTHER REQUIRED
; FUNCTION

	LDA 	DCBFN		;DONE IF FUNCT=
	ORA 	A		;SEEK ONLY (0)
	JZ 	DS100		;DONE

; PERFORM READ/WRITE FUNCTION
;
; RETRY CONTROL FOR READ/WRITE
; OPERATIONS. A 3 LEVEL RETRY STRUCTURE IS
; PROVIDED AS FOLLOWS:
;
;   1 - IF AN ERROR OCCURS, UP TO 5
;	RETRYS OF THE OFFENDING OPERATION
;	WILL BE PERFORMED
;
;   2 - IF THE LEVEL 1 RETRYS ARE NOT
;	SUCCESSFUL,THE POSITIONER WILL
;	BE STEPPED OFF TRACK AND BACK
;	AND THE LEVEL 1 RETRYS WILL BE
;	PERFORMED. THE LEVEL 2 RETRYS
;	WILL BE PERFORMED UP TO 4 TIMES
;
;   3 - IF THE LEVEL 2 RETRY
;	PROCEDURE IS NOT SUCCESSFUL,THE
;	UNIT WILL BE DESELECTED TO UNLOAD
;	THE HEAD THEN THE UNIT WILL BE
;	RESELECTED,THE POSITIONER WILL
;	BE RECALIBRATED AND MOVED BACK
;	TO THE DESIRED TRACK AND THE
;	LEVEL 1 AND 2 RETRY PROCEDURES
;	WILL BE PERFORMED. THIS WILL BE
;	DONE UP TO 3 TIMES. IF NOT
;	SUCCESSFUL, A PERMANENT I/O
;	ERROR WILL RESULT
;
DS020	MVI 	A,3		;PRESET RETRY
	STA 	L3RTRY 		;COUNTERS
DS030	MVI 	A,4
	STA 	L2RTRY
DS040	MVI 	A,5
	STA 	L1RTRY

; SELECT DESIRED FUNCTION AND PERFORM

DS050	LHLD 	DCBAD		;PRESET BUFFER
	SHLD 	BUFADR 		;ADDRESS
	LDA 	DCBFN		;GET FUNCTION
	DCR 	A
	JNZ 	DS060

; READ SECTOR

	CALL 	READAL 		;READ SECTOR
	JMP 	DS090		;CHECK FOR ERROR
DS060	DCR 	A
	JNZ 	DS080

; WRITE SECTOR

	LDA 	DCBUN		;IF HEADER CHECK
	ANI 	HCI		;INHIBIT SET SO
	JNZ 	DS070		;WRITE
	LDA 	DCBSC		;BACKSPACE SECTOR
	DCR 	A		;COUNT MOD 16
	ANI 	0FH
	MOV 	B,A
	CALL 	READCK 		;DO PRE-WRITE HDR
	JNZ 	DS090		;CHECK - ABORT ERR
DS070	CALL 	WSECT		;GO WRITE
	LDA 	DCBSC		;DO RAW CHECKSUM
	MOV 	B,A		;READ CHECK
	LDA 	DCBUN		;UNLESS INHIBITED
	ANI 	RAFI
	XRI 	RAFI
	CNZ 	READCK
	JMP 	DS090		;GO CHECK FOR ERR
DS080	DCR 	A
	JNZ 	PARMER 		;TRAP-JUST IN CASE

; VERIFY SECTOR

	LDA 	DCBSC
	MOV 	B,A
	CALL 	READCK 		;DO CHECKSUM READ

; CHECK FOR ERROR

DS090 	JZ 	DS100		;NO ERROR-EXIT
	LDA 	L1RTRY 		;LEVEL 1 — RETRY
	DCR 	A		;UP TO 5 TIMES
	STA 	L1RTRY
	JNZ 	DS050

; RETRIED 5 TIMES - STEP OFF TRACK
;    AND BACK AND REPEAT

	CALL 	RESTEP
	LDA 	L2RTRY 		;PERFORM UP TO 4
	DCR 	A		;TIMES
	STA 	L2RTRY
	JNZ 	DS040

; STEPPED OFF 4 TIMES - DESELECT
;    DRIVE TO UNLOAD HEAD THEN
;    SELECTsRESTORE AND RE-SEEK

	CALL 	RESLCT
	LDA 	L3RTRY 		;PERFORM UP TO 3
	DCR 	A		;TIMES
	STA 	L3RTRY
	JNZ 	DS030

; UNSUCCESSFUL — ABORT WITH
;    PERMANENT I/O ERROR

	JMP 	PERMER

; END OF OPERATION

DS100 	LHLD 	STACK		;RESTORE STACK PTR
	SPHL
	POP 	H		;RESTORE REGISTERS
	POP 	D
	POP 	B
EIADR	NOP			;SPACE FOR EI
	RET

; SEEK TO DESIRED TRACK

SEEK	CALL 	SLCT		;ENSURE DPIVE SLTD
	PUSH 	H		;AND READY
	CALL 	LDTRK		;POINT HL TO TRACK
	MVI 	A,0FFH	 	;SEE IF DRIVE HAS
	CMP 	M		;BEEN INITIALIZED
	JNZ 	SEEK1		;YES-CONTINUE
	CALL 	RESTOR 		;CALIBRATE POSITION
SEEK1	LDA 	DCBTK		;GET TRACK FROM DCB
	MOV 	C,A		;SAVE IN C
	SUB 	M		;ALREADY AT TRACK?
	JZ 	SEEKR		;YES-RETURN

; NOT AT TRACK — ISSUE THE
;    APPROPRIATE NUMBER OF STEPS TO
;    MOVE TO THE DESIRED TRACK

	JM 	SEKOUT
SEKIN	CALL 	STEPIN
	DCR 	A
	JNZ 	SEKIN
	JMP 	SEEKR1
SEKOUT	CALL 	STPOUT
	INR 	A
	JNZ 	SEKOUT
SEEKR1	CALL 	SETTLE 		;WAIT HEAD SETTLE
SEEKR	MOV 	M,C		;STORE TRACK
	POP 	H
	RET

; STEP POSITIONER IN 1 TRACK

STEPIN	PUSH 	PSW
	PUSH 	D
	PUSH 	H
	XRA 	A		;SET DIRECTION FLAG
	STA 	DIRCTN
	LHLD 	DADR		;STEP IN ONE TRK
	MVI 	M,STEP+1
STP1	LXI 	D,30		;WAIT STEP TIME
	CALL	TIMER
	POP 	H
	POP 	D
	POP 	PSW
	RET

; STEP POSITIONER OUT 1 TRACK

STPOUT	PUSH 	PSW
	PUSH 	D
	PUSH 	H
	MVI 	A,0FFH	 	;SET DIRECTION FLAG
	STA 	DIRCTN
	LHLD 	DADR
	MVI 	M,STEP 		;STEP OUT ONE TRK
	JMP 	STP1 		;GO WAIT STEP TIME

; WAIT HEAD SETTLE TIME

SETTLE	PUSH 	D
	LXI 	D,10 		;10 MILLISECONDS
	CALL 	TIMER
	POP 	D
	RET

; STEP OFF TRACK ONE AND BACK TO CORRECT
;    POSSIBLE MARGINAL TRACK POSITION
;    OF DRIVE WHICH WROTE THE DISK
;    IF TRACK 0 SUBSTITUTE RESTOR

RESTEP	CALL 	LDTRK		;GET CRNT TRK ADDR
	MOV 	A,M 		;GET CRNT TRK
	ORA 	A
	JNZ 	RSTPA
	CALL 	RESTOR 		;USE RESTOR IF TK 0
	RET

RSTPA 	LDA 	DIRCTN
	ORA 	A
	JNZ 	RSTPB
	CALL 	STEPIN
	CALL 	SETTLE
	CALL 	STPOUT
	CALL 	SETTLE
	RET

RSTPB 	CALL 	STPOUT
	CALL 	SETTLE
	CALL 	STEPIN
	CALL 	SETTLE
	RET

; RETRY ROUTINE TO RESTORE TO 0 THEN
;    LIFT HEAD; LOVER HEAD AND RESEEK

RESLCT	PUSH 	H
	LHLD 	DADR
	MVI 	M,RESET 	;RESET CONTROLLER
	LXI 	D,200
	CALL 	TIMER
	CALL 	SLCT 		;RESELECT, LOWR HEAD
	POP 	H
	CALL 	RESTOR
	JMP 	SEEK 		;GO RE-SEEK

; RESTORE POSITIONER TO TRACK 0
;    POSITIONER MUST BE STEPPED OUT
;    UNTIL THE TRACK 0 SWITCH IS MADE
;    TO CALIBRATE TRACK POSITION

RESTOR	PUSH	H
	PUSH 	B
	CALL 	LDTRK		;POINT HL TO TRACK
	MVI 	M,0FFH	 	;PRESET TO BAD TRK
	CALL 	RESTR1 		;RESTORE TO TK 0
	MVI 	M,0		;SET TRACK=0
	POP	B
	POP 	H
	RET

; RESTORE TO TK 0

RESTR1 	PUSH 	H
	CALL 	SLCT		;ENSURE UNIT SLCTD
	PUSH 	D 		;AND READY
	PUSH 	B
	LHLD 	DADR		;POINT TO STATUS
	INX 	H		;BYTE
	MOV 	A,M		;ALREADY AT
	ANI 	TK0		;TRACK 0 ?
	JZ 	REST3		;NO - PRESS ON

; ALREADY AT TRACK 0 - STEP
;    IN 8 TIMES THEN RESTORE
;    TO ENSURE GOOD POSITION

	MVI 	A,8
REST2	CALL 	STEPIN 		;STEP IN 8
	DCR 	A		;TRACKS
	JNZ 	REST2
	CALL 	SETTLE 		;WAIT SETTLE TIME

; STEP OUT UNTIL TRACK 0 SWITCH
;    IS ACTUATED OR UNTIL 85 STEPS
;    HAVE BEEN ISSUED SO THAT WE
;    DONT BANG AGAINST THE STOP
;    FOREVER IF TK0 SWITCH IS
;    BROKEN

REST3	MVI	C,85		;LOAD MAX STEPCNT
REST3A	MOV	A,M		;TRACK 0?
	ANI	TK0
	JNZ	REST4		;YES- PRESS ON
	CALL	STPOUT		;STEP OUT ONE TK
	DCR	C		;MAX STEPS ?
	JNZ 	REST3A 		;NO - TRY AGAIN

; MAXIMUM NUMBER OF STEPS HAVE
;    BEEN ISSUED - ERROR ABORT

	JMP	PERMER

; FOUND TRACK 0 - WAIT
;    SETTLE TIME THEN EXIT

REST4	CALL 	SETTLE		;WAIT HEAD SETTLE
	POP 	B
	POP 	D
	POP 	H
	RET

; LOAD ADDRESS OF CURRENT TRACK ON
;    CURRENT UNIT INTO HL

LDTRK 	PUSH	D
	LDA	DCBUN
	ANI	03		;MASK OUT UNIT
	MOV	E,A
	MVI	D,0
	LXI	H,TRACK 	;POINT HL INTO
	DAD	D		;TRACK TABLE
	POP	D
	RET

; ERROR EXITS

PERMER 	MVI	A,1
	ORA	A
	JMP	DS100
PARMER 	MVI	A,2
	ORA	A
	JMP	DS100
DRIVER 	MVI	A,3
	ORA	A
	JMP	DS100
PROTER 	MVI	A,4
	ORA	A
	JMP 	DS100

;***************************************
;	REGISTER DEFINITIONS AND
;	FLAG EQUATES FOR MICROPOLIS
;	FLEXIBLE DISK CONTROLLER B
;***************************************

BPROM 	EQU 	0F800H
DIADR	EQU 	BPROM+0200H

; DATA REGISTERS

WDATA	EQU 	DIADR+2
RDATA 	EQU 	WDATA

; STATUS REGISTERS

DSECTR	EQU 	DIADR
;     0-3 SECTOR COUNT
;	4 SPARE
;	5 SPARE
;	6 SCTR INTERRUPT FLAG
;	7 SECTOR FLAG
;
;	FLAG BITS

SIFLG	EQU 	040H
SFLG	EQU 	080H
DTMR	EQU 	020H


DSTAT	EQU 	DIADR+1
;     0-1 UNIT ADDRESS
;	2 UNIT SELECTED (LOW TRUE)
;	3 TRACK 0
;	4 WRITE PROTECT
;	5 DISK READY
;	6 PINTE
;	7 TRANSFER FLAG
;
;	FLAG BITS

TFLG	EQU 	80H
INTE	EQU 	40H
RDY	EQU 	20H
WPT	EQU 	10H
TK0	EQU 	08H
USLT	EQU 	04H

; COMMAND REGISTER

DCMND	EQU 	DIADR
; (ALSO	WILL RESPOND TO DISK+1)
;
;	0-1 COMMAND MODIFIER
;	5-7 COMMAND
;
;	COMMANDS

SLUN	EQU 	020H		;SELECT UNIT
;  MODIFIER CONTAINS UNIT ADDRESS

SINT	EQU 	040H		;SET INTERRUPT
;  MODIFIER = l ENABLE INTERRUPT
;  	      0 DISABLE INTERRUPT

STEP	EQU 	060H		;STEP CARRIAGE
;  MODIFIER = 00 STEP OUT
;  	      01 STEP IN

WTCMD	EQU 	080H		;ENABLE WRITE
;  NO MODIFIER USED

RESET	EQU 	0A0H		;RESET CONTROLLER
;  NO MODIFIER USED

;
SCLEN 	EQU 	134		;SECTOR LNGTH/2

; SELECT DRIVE	SPECIFIED
;    BY UNIT ADDRESS IN DCB

SLCT 	PUSH 	D
	PUSH 	B
	PUSH 	H
	LHLD 	DADR		;GET CONTROLLER ADR
	LDA 	DCBUN		;GET UNIT ADR FROM
	ANI 	3		;DCB
	MOV 	B,A		;AND SAVE
	INX 	H		;POINT TO STATUS
	MOV 	A,M		;AND READ
	MOV 	C,A		;SAVE STATUS
	ANI 	7		;MASK USLD A ADDR
	XRA 	B		;DESIRED UNIT PREV

; NOTE-THIS TEST WILL FAIL IF
;    CONTROLLER IS NOT PLUGGED IN

	MOV 	A,C		;SELECTED?
	JZ 	SL010		;YES-CHECK RDY
	MOV 	A,B		;GET UNIT ADDRESS
	ORI 	SLUN		;BUILD COMMAND
	MOV 	M,A		;OUTPUT COMMAND
				;WAIT 250 MSEC FOR
	LXI 	D,250		;SECTOR CNTR TO
	CALL 	TIMER		;GET IN SYNC
	MOV 	A,M		;GET STATUS
	ANI 	7		;SELECTED NOW?
	XRA 	B
	MOV 	A,M		;GET STATUS AGAIN
	JNZ 	SL020		;ERROR IF NOT SLTD
SL010 	ANI 	RDY		;ENSURE UNIT IS
	XRI 	RDY		;READY
SL020 	POP 	H
	POP 	B
	POP 	D
	RZ			;RETURN IF OK

; DRIVE NOT UP ERROR
	JMP DRIVER

; 1 MILLISECOND TIMER
;    DE=(DELAY) TIME IN MSEC
;
;    A IS DESTROYED

TIMER 	PUSH	B
	PUSH 	H
	LHLD 	DADR
	MOV 	A,M		;2 or 4 Mhz?
	ANI	DTMR
	MVI	A,96		;1MS @2MHZ
	JNZ	TI005		;IF NOT ZERO, 2MHZ
	RLC			;DOUBLE COUNTER FOR 4MHZ
TI005	MOV	B,A		;SAVE COUNTER IN B
TI010 	MOV 	A,B		;COUNT
	SUI 	1		;DELAY LOOP-1.008
	ORA 	A		;MSEC @500 NSEC
	JNZ 	TI010+1

; 1MSEC EXPIRED - DECREMENT DELAY
;    MULTIPLIER & CHECK FOR DONE

	DCX 	D
	MOV 	A,E
	ORA 	D
	JNZ 	TI010
	POP 	H
	POP 	B
	RET

; WRITE 1 SECTOR

WSECT 	CALL 	SLCT		;ENSURE UNIT SLD
	LDA	DCBSC		;AND READY
	MOV 	B,A
	PUSH 	B
	MVI 	C,SCLEN 	;C <- BYTCT/2
	LHLD 	DADR		;GET CONTROLLER ADR
	PUSH 	H
	INX 	H		;READ STATUS
	MOV 	A,M		;ABORT IF
	ANI 	WPT		;WRITE PROTECTED
	JNZ 	PROTER
	LHLD 	BUFADR 		;GET BUFFER ADDR
	PUSH 	H
	POP 	D		;MOVE TO DE
	LDA 	DCBTK		;MOVE TRACK AND
	MOV 	M,A 		;SECTOR ID TO WRITE
	INX 	H 		;BUFFER
	MOV 	M,B
	LHLD 	DADR		;GET CONTROLLER ADR
	CALL 	GETSEC 		;WAIT FOR SECTOR

; FOUND DESIRED SECTOR - ENABLE WRITE

	MVI 	M,WTCMD
	INX 	H

; WAIT FOR TRANSFER FLAG

WS010 	ORA 	M
	JP 	WS010

; INSERT SYNC BYTE

	INX 	H
	MVI 	M,0FFH
	XRA 	A		;CLEAR CARRY
	XCHG
	MVI 	B,0		;AND CHECKSUM

; WRITE HEADER & DATA FIELD

WS020 	MOV 	A,M		;GET BYTE FROM MEM
	STAX 	D		;WRITE TO DISK
	ADC 	B		;ADD TO CKSUM
	MOV 	B,A		;SAVE CKSUM
	INX 	H		;NEXT BYTE
	MOV 	A,M		;-ETC-
	STAX 	D
	ADC 	B
	MOV 	B,A
	INX 	H
	DCR 	C
	JNZ 	WS020

; END OF DATA - INSERT CHECKSUM

	MOV 	A,B
	STAX 	D

; WAIT END OF SECTOR

	POP H
	XRA A
WS030 	ORA 	M		;WAIT SCTR FLAG
	JP 	WS030
	LXI 	D,1		;WAIT 1 MSEC FOR
	CALL 	TIMER 		;ERASE DELAY
	POP 	B
	RET

; READ 1 SECTOR
;    VERIFY CHECKSUM AND HEADER
;
;    RETURNS Z=OK
;           NZ=ERROR

READAL 	CALL 	SLCT		;ENSURE UNIT IS
				;RDY + SLTD
	LDA 	DCBSC 		;GET SECTOR ADDR
	MOV 	B,A		;FROM DCB
	PUSH 	B
	MVI 	C,SCLEN 	;C <- BYTCT/2
	CALL 	WTSYNC 		;WAIT DESIRED
				;SECTOR & STRIP
				;SYNC BYTE

; FOUND DESIRED SECTOR - READ

	XCHG
	XRA 	A		;CLEAR CARRY
	MVI 	B,0		;CLR CHECKSUM

; READ LOOP

RDA10 	LDAX 	D		;READ FROM DISK
	MOV 	M,A		;MOVE TO BUFFER
	INX 	H		;NEXT LOC
	ADC 	B		;ADD TO CHECKSUM
	MOV 	B,A		;AND SAVE
	LDAX 	D		;NEXT READ
	MOV 	M,A		;-ETC-
	INX 	H
	ADC 	B
	MOV 	B,A
	DCR 	C		;END OF DATA?
	JNZ 	RDA10		;NO-LOOP

; END OF DATA-READ CHECKSUM

	LDAX 	D
RDA020	CMP 	B		;COMPARE WITH
	POP 	B		;COMPUTED CHECKSUM
	RNZ			;RETURN IF ERROR

; CHECKSUM OK-VERIFY HEADER

	LHLD 	BUFADR 		;POINT DE TO READ
	XCHG			;BUFFER
	CALL 	LDTRK		;POINT TO CURRENT
	LDAX 	D		;TRACK AND COMPARE
	CMP 	M		;WITH TRACK ID READ
	RNZ
	INX 	D
	LDAX 	D		;COMPARE SECTOR ID
	CMP 	B		;WITH DESIRED SCTR
	RET

; VERIFY SECTOR
;
;	READ THROUGH SECTOR WITHOUT
;	MOVING DATA INTO MEMORY AND
;	VERIFY TRACK AND SECTOR ID
;	AND CHECKSUM
;
;	ONLY TRACK AND SECTOR ID ARE READ
;	INTO MEMORY AND CHECKSUM IS
;	VERIFIED
;
;	SECTOR IS SPECIFIED BY B REG
;
;	RETURNS Z=OK
;	       NZ=ERROR

READCK 	PUSH 	B		;SAVE SECTOR
	CALL 	SLCT		;ENSURE SLTD&RDY
	MVI 	C,SCLEN-1 	;C <- BYTCT/2-t
	CALL 	WTSYNC 		;WAIT SECTOR & STRP
				;OFF SYNC BYTE
	XRA 	A		;CLEAR CARRY
	MVI 	B,0		;CLR CHECKSUM
	MOV 	A,M		;READ TRACK ID
	STAX 	D		;SAVE IN BUFFR
	ADC 	B		;ADD TO CHECKSUM
	MOV 	B,A		;AND SAVE
	INX 	D
	MOV 	A,M		;READ SCTR ID
	STAX 	D		;AND SAVE
	ADC 	B
	MOV 	B,A
	NOP
	NOP

;READ THROUGH REMAINDER OF SECTOR
;  TO COMPUTE A VERIFY CHECKSUM

RDCK10 	MOV 	A,M		;READ FROM DISK
	ADC 	B		;ADD TO CHECKSUM
	MOV 	B,A		;SAVE CKSUM
	NOP
	NOP
	NOP
	NOP
	MOV 	A,M		;-ETC-
	ADC 	B
	MOV 	B,A
	NOP
	DCR 	C
	JNZ 	RDCK10

; END OF DATA - READ CHECKSUM

	MOV 	A,M
	JMP 	RDA020 		;GO CHECK HDR &
				;CHECKSUM

; WAIT FOR DESIRED SECTOR
;    TO COME AROUND AND STRIP OFF
;    SYNC BYTE FOR READ ROUTINES

WTSYNC 	LHLD 	BUFADR 		;GET BUFFER ADDRESS
	XCHG
	LHLD 	DADR		;AND CONTROLLER ADR
	CALL 	GETSEC 		;WAIT FOR SECTOR
	INX 	H
WTS010 	ORA 	M		;WAIT FOR XFER RDY
	JP 	WTS010 		;FLAG
	INX 	H		;OK-READ IN SYNC
	MOV 	A,M		;BYTE -- THROW IT
	XRA 	A		;AWAY,CLEAR CARRY
	RET			;AND GO READ

; WAIT FOR DESIRED SECTOR TO COME
;    AROUND

GETSEC 	MOV 	A,M		;WAIT FOR SCTR FLAG
	ORA 	A
	JP 	GETSEC
	ANI 	0FH		;OK -IS THIS THE
	XRA 	B		;ONE WE WANT?
	JNZ 	GETSEC 		;NO-WAIT
	RET			;PRESS ON

; RAM STORAGE REQUIRED FOR DRIVER
;
; INTERNAL DISK CONTROL BLOCK

DCB	EQU 	$
DCBFN	DS 	1
DCBUN	DS 	1
DCBSC	DS 	1
DCBTK	DS 	1
DCBAD	DS 	2
DCBLEN	EQU 	$-DCB

HCI	EQU 	080H		;HEADER CHECK INH
RAFI	EQU 	040H		;RAW CHECK INHIBIT
TRKMX	DB 	76		;MODEL 2

;CURRENT TRACK TABLE
;    MUST BE INITIALIZED TO FF
;    AT POWER ON TO CAUSE DISK TO
;    BE RESTORED TO TRACK 0
;    THE FIRST TIME IT IS ACCESSED TO
;    CALIBRATE TRACK POSITION

TRACK	DB	0FFH
	DB	0FFH
	DB	0FFH
	DB	0FFH

BUFADR	DS 	2		;CURRENT BUFFER ADR
;

DADR	DW	 DIADR 		;DISK CTLR ADDR

;	RETRY COUNTERS

L1RTRY	DS 	1
L2RTRY	DS 	1
L3RTRY	DS 	1

DIRCTN	DS 	1
STACK	DS 	2		;SAVED SP

	END
