
	SUBTTL	'SECTOR I/O'


**	GET - GET SECTOR
**	PUT - PUT SECTOR
**	PUTV - PUT SECTOR WITH VERIFY

GET
PUT
PUTV

;	CALCULATE TRACK AND SECTOR NUMBERS

	MOV	A,PSW
	ANLI	A,$FC
	MOV	PSW,A		;SELECT RETURN TARGET = CTSRT0
	LNGJMP	CTS
CTSRT0
	JNC	SECT1		;IF SUCCESS
	IN	A,P2
	CPL	A
	JB5	SECT2		;IF SECTOR SIZE = 256
	IN	A,P1
	ANLI	A,DDEN
	JZ	SECT2		;IF MFM
	ANLI	P1,$FF-DDEN	;SET TO MFM
	MOV	A,PSW
	ANLI	A,$FC
	ORLI	A,1
	MOV	PSW,A		;SELECT RETURN TARGET = CTSRT1
	LNGJMP	CTS		;TRY AGAIN TO CALCULATE
CTSRT1
	JNC	SECT1		;IF SUCCESS
	ORLI	P1,DDEN		;RETURN SETTING TO FM
SECT2
	LNGJMP	INVCF		;INVALID COMMAND FRAME

;	SEND ACKNOWLEDGE

SECT1
	LNGCAL	SENDAK

;	IN CASE OF PUT, RECEIVE DATA FRAME

	IN	A,P2
	ANLI	A,$FF-ACLR
	XRLI	A,AGET
	JZ	SECT3		;IF GET

	MOVI	R0,$7F		;FOR 128-BYTE SECTOR
	MOV	A,PSW
	ORLI	A,1
	MOV	PSW,A		;SIGNAL NO BUFFER EXPANSION
	IN	A,P2
	JB5	SECT4		;IF SECTOR SIZE IS 128 BYTES
	IN	A,P1
	ANLI	A,SS0
	JNZ	SEC5		;IF SECOND SIDE
	SETREG	RDAT
	MOVX	A,XR0
	JNZ	SEC5		;IF NOT TRACK 0
	SETREG	RSEC
	MOVX	A,XR0
	ADDI	A,$FC
	JC	SEC5		;IF NOT SECTOR 1, 2, OR 3
	MOV	A,PSW
	ANLI	A,$FE		;INDICATE BUFFER EXPANSION
	MOV	PSW,A
	JUMP	SECT4
SEC5
	MOVI	R0,$FF		;FOR 256-BYTE SECTORS
SECT4
	LNGJMP	RECV		;GO RECEIVE DATA FRAME
PUTRR
	MOV	A,PSW
	JB0	SECT3		;IF NO BUFFER EXPANSION
	MOVI	R0,$80
	MOV	A,T		;LAST BYTE OF FRAME
	MOV	XR0,A		;STORE IT IN HIGH RAM
	DECR	R0
SEC6
	MOV	A,XR0		;GET A BYTE OF THE DATA FRAME
	XCH	A,R0
	ORLI	A,$80
	XCH	A,R0
	MOV	XR0,A		;STORE IT INTO HIGH RAM
	XCH	A,R0
	ANLI	A,$7F
	XCH	A,R0
	DJNZ	R0,SEC6		;IF DONE WITH 128 BYTES

;	CHECK TO SEE IF HEAD POSITION IS KNOWN

SECT3
	CLR	F1		;INIT HARD RETRY FLAG
	IN	A,P2
	ANLI	A,HKNOWN
	JNZ	SEC7		;IF HEAD KNOWN, OMIT RESTORE SEQUENCE
	SETREG	RDAT


**	RST - RESTORE SEQUENCE
*
*	ENTRY CONDITIONS:
*		P1 SET UP TO READ REG CONTAINING DESIRED TRACK
*		LAST BYTE OF DATA FRAME IN TIMER

RST

;	READ IN DESIRED TRACK AND SECTOR

	MOVX	A,XR0		;GET DESIRED TRACK
	MOV	R0,A
	MOV	A,PSW
	XRL	A,R0
	ANLI	A,$F8
	XRL	A,R0
	MOV	PSW,A		;STORE BITS 2-0 OF TRACK IN PSW
	MOV	A,R0
	RL	A
	RL	A
	MOV	R0,A
	SETREG	RSEC
	MOVX	A,XR0		;GET DESIRED SECTOR
	XRLI	A,IMPSEC
	JZ	RST2		;IF 'IMPOSSIBLE' SECTOR
	XRLI	A,IMPSEC
RST2
	XRL	A,R0
	ANLI	A,$1F
	XRL	A,R0		;COMBINE TRACK[5:3] WITH SECTOR[4:0]

;	DO HARD RESET TO THE 1770

	ANLI	P2,$FF-HKNOWN	;INDICATE HEAD POSITION UNKNOWN
	ANLI	P1,$FF-MR	;LOWER RESET
	PAUSE	R0,US500	;500 US DELAY
	ORLI	P1,MR		;RAISE RESET
	PAUSE	R0,US500	;500 US DELAY
	MOV	R0,A
	MOVI	A,FRCINT
	MOVX	XR0,A		;DO FORCED INTERRUPT
	MOV	A,R0
	PAUSE	R0,US200	;200 US DELAY

;	WRITE SECTOR NUMBER INTO SECTOR REG

	MOV	R0,A
	ANLI	A,$1F
	JNZ	RST1
	MOVI	A,IMPSEC	;'IMPOSSIBLE' SECTOR
RST1
	SETREG	WSEC
	MOVX	XR0,A

;	ISSUE RESTORE COMMAND

	MOVI	A,REST
	SETREG	WCMD
	MOVX	XR0,A

;	SET UP COUNTER AND TIMER FOR RESTORE 3-SECOND TIMEOUT

	MOV	A,T		;LAST DATA BYTE
	XCH	A,R0		;PUT DATA BYTE IN R0
	RR	A
	RR	A
	RR	A
	RR	A
	RR	A		;MOVE TRACK[5:3] INTO BITS 2-0
	ANLI	A,$07		;INIT 5-BIT COUNTER

;	DELAY APPROXIMATELY 100 MS

RST3
	MOV	T,A		;INIT TIMER
	STRT	T
RST4
	JTF	RST5
	JUMP	RST4
RST5
	JTF	RST6
	JUMP	RST5
RST6
	JTF	RST7
	JUMP	RST6
RST7
	JTF	RST8
	JUMP	RST7
RST8
	JTF	RST9
	JUMP	RST8
RST9
	JTF	RST10
	JUMP	RST9
RST10
	JTF	RST11
	JUMP	RST10
RST11
	STOP	TCNT

;	SEE IF RESTORE COMMAND IS DONE

	MOV	T,A
	IN	A,P1
	JB2	RST12		;IF RESTORE IS DONE
	MOV	A,T
	ADDI	A,$08
	JNC	RST3		;IF TIME NOT EXPIRED
	RL	A
	RL	A
	RL	A
	ANLI	A,$38
	XCH	A,R0
	MOV	T,A		;PUT LAST DATA BYTE IN TIMER
	MOVI	A,FRCINT
	SETREG	WCMD
	MOVX	XR0,A		;INITIATE FORCED INTERRUPT
	MOV	A,PSW
	XRL	A,R0
	ANLI	A,$F8
	XRL	A,R0		;RECONSTRUCT TRACK NUMBER
	PAUSE	R0,US200	;DELAY 200 US
	SETREG	WTRK
	MOVX	XR0,A		;WRITE DESIRED TRACK INTO TRACK REG
	JUMP	HRT		;GO DO HARD RETRY

;	COME HERE IF RESTORE COMPLETE
;	AT THIS POINT, LAST DATA BYTE IS IN R0

RST12
	SETREG	RSTA
	MOVX	A,XR0		;READ STATUS REG TO CLEAR INTRQ
	IN	A,P2
	CPL	A
	JB5	RST13		;IF SS/DD OR DS/DD

;	FOR SS/SD AND SS/2D, DO READ ADDRESS TO DETERMINE DENSITY

	ANLI	P1,$FF-DDEN	;SELECT MFM
	MOV	A,R0		;LAST BYTE TO A
	PAUSE	R0,US500	;DELAY 500 US
	MOV	R0,A		;LAST BYTE TO R0
	MOVI	A,RDADR
	SETREG	WCMD
	MOVX	XR0,A		;ISSUE READ ADDRESS COMMAND
	CLR	A
	MOV	T,A		;INIT TIMER
	MOVI	A,MS240		;TRIP COUNT FOR 240 MS DELAY
	JTF	RST16		;CLEAR TIMER OVERFLOW FLAG
RST16
	STRT	T
	SETREG	RDAT		;PREPARE TO READ DATA REG

RST17
	JTF	RST18
RST34
	JNDRQ	RST17
	JNDRQ	RST17		;FILTER DRQ GLITCHES

;	READ SIX BYTES FROM THE 1770

RST19
	MOVX	A,XR0		;READ FIRST BYTE
	CLR	A
	MOV	T,A		;INIT TIMER
	JTF	RST20		;CLEAR TIMER OVERFLOW FLAG
RST20
	JDRQ	RST21
RST22
	JTF	RST25
	JNDRQ	RST22
RST21
	MOVX	A,XR0		;READ SECOND BYTE
RST23
	JTF	RST25
	JNDRQ	RST23
	MOVX	A,XR0		;READ THIRD BYTE
RST24
	JTF	RST25
	JNDRQ	RST24
	MOVX	A,XR0		;READ FOURTH BYTE
RST29
	JTF	RST25
	JNDRQ	RST29
	MOVX	A,XR0		;READ FIFTH BYTE
RST30
	JTF	RST25
	JNDRQ	RST30
	MOVX	A,XR0		;READ SIXTH BYTE

RST31
	JTF	RST25
	IN	A,P1
	CPL	A
	JB2	RST31		;IF 1770 STILL BUSY

	SETREG	RSTA
	MOVX	A,XR0		;READ STATUS REG
	ANLI	A,$1C		;RELEVANT STATUS BITS FOR READ ADDRESS
	JNZ	RST25		;IF READ ADDRESS FAILED
	JUMP	RST26		;IF READ ADDRESS IS SUCCESSFUL

;	HANDLE TIMER TRIPS WHILE WAITING FOR FIRST BYTE

RST18
	JNDRQ	RST32
	JDRQ	RST19		;FILTER DRQ GLITCHES
RST32
	DECR	A
	JNDRQ	RST33
	JDRQ	RST19		;FILTER DRQ GLITCHES
	JNZ	RST34		;IF NOT TIMED OUT

;	COME HERE IF READ ADDRESS FAILS
;	AT THIS POINT, LAST DATA BYTE IS IN R0

RST25
	MOVI	A,FRCINT
	SETREG	WCMD
	MOVX	XR0,A		;DO FORCED INTERRUPT
	MOV	A,R0
	PAUSE	R0,US200	;DELAY 200 US
	ORLI	P1,DDEN		;SELECT FM
	PAUSE	R0,US500	;DELAY 500 US
	MOV	R0,A

;	FINISH UP READ ADDRESS
;	AT THIS POINT, LAST DATA BYTE IN R0

RST26
	STOP	TCNT
	MOV	A,R0
	MOV	T,A		;LAST DATA BYTE TO TIMER
	MOV	A,PSW
	ANLI	A,$FC
	ORLI	A,2
	MOV	PSW,A		;SELECT RETRUN TARGET = CTSRT2
	LNGJMP	CTS		;CALCULATE TRACK AND SECTOR
CTSRT2
	JNC	SEC7		;IF SUCCESS
	CLR	F1
	CPL	F1		;FORCE HARD RETRY TO FAIL
	JUMP	HRT		;GO DO HARD RETRY

;	RECONSTRUCT TRACK NUMBER

RST13
	MOV	A,T
	RL	A
	RL	A
	RL	A
	ANLI	A,$38
	XCH	A,R0
	MOV	T,A		;PUT LAST DATA BYTE INTO TIMER
	MOV	A,PSW
	XRL	A,R0
	ANLI	A,$F8
	XRL	A,R0		;RECONSTRUCT TRACK NUMBER
	SETREG	WDAT
	MOVX	XR0,A		;WRITE DESIRED TRACK INTO DATA REG
	CLR	A
	SETREG	WTRK
	MOVX	XR0,A		;UPDATE TRACK REG TO ZERO

;	END OF RESTORE SEQUENCE

;	ISSUE SEEK COMMAND
;	AT THIS POINT, LAST DATA BYTE IS IN TIMER

SEC7
	ANLI	P2,$FF-HKNOWN	;INDICATE HEAD POSITION UNKNOWN
	MOVI	A,SEEK
	SETREG	WCMD
	MOVX	XR0,A		;ISSUE SEEK COMMAND
	MOV	A,T		;FETCH LAST DATA BYTE
	MOV	R0,A		;STORE IT
	CLR	A
	MOV	T,A		;INIT TIMER
	MOV	A,PSW
	ANLI	A,$3F
	ORLI	A,$07		;INIT 5-BIT COUNTER WITHIN PSW
	STRT	T

;	WAIT FOR SEEK COMMAND TO BE COMPLETE

SEC8
	MOV	PSW,A
SEC10
	JTF	SEC11
	IN	A,P1
	JB2	SEC9		;IF SEEK DONE
	JUMP	SEC10
SEC11
	JTF	SEC12
	IN	A,P1
	JB2	SEC9		;IF SEEK DONE
	JUMP	SEC11
SEC12
	JTF	SEC13
	IN	A,P1
	JB2	SEC9		;IF SEEK DONE
	JUMP	SEC12
SEC13
	JTF	SEC14
	IN	A,P1
	JB2	SEC9		;IF SEEK DONE
	JUMP	SEC13
SEC14
	JTF	SEC15
	IN	A,P1
	JB2	SEC9		;IF SEEK DONE
	JUMP	SEC14
SEC15
	JTF	SEC16
	IN	A,P1
	JB2	SEC9		;IF SEEK DONE
	JUMP	SEC15

;	HANDLE POSSIBLE SEEK TIMEOUT

SEC16
	MOV	A,PSW
	DECR	A
	JB3	SEC8		;IF NOT TIMED OUT
	ADDI	A,$48
	JNC	SEC8		;IF NOT TIMED OUT
	STOP	TCNT
	MOV	A,R0
	MOV	T,A		;PUT LAST DATA BYTE IN TIMER
	MOVI	A,FRCINT
	SETREG	WCMD
	MOVX	XR0,A		;DO FORCED INTERRUPT
	PAUSE	R0,US200	;DELAY 200 US
	SETREG	RDAT
	MOVX	A,XR0		;READ IN TARGET TRACK
	SETREG	WTRK
	MOVX	XR0,A		;WRITE IT INTO TRACK REG
	JUMP	HRT		;GO DO HARD RETRY

;	COME HERE FOR SUCCESSFUL SEEK

SEC9
	ORLI	P2,HKNOWN	;INDICATE HEAD POSITION KNOWN
	SETREG	RSTA
	MOVX	A,XR0		;READ STATUS REG TO CLEAR INTRQ
	MOV	A,PSW
	ANLI	A,$F8
	ORLI	A,2

;	COME HERE TO EXECUTE SOFT RETRY

SEC18
	MOV	PSW,A		;INIT SOFT RETRY COUNTER
	STOP	TCNT
	JTF	SEC17		;CLEAR TIMER OVERFLOW FLAG
SEC17
	CLR	A
	MOV	T,A		;INIT TIMER FOR ID FIELD TIMEOUT


**	HANDLE GET COMMAND

	IN	A,P2
	ANLI	A,$FF-ACLR
	XRLI	A,AGET
	JNZ	PUT1		;IF NOT A GET COMMAND

;	INITIALIZATION FOR GET

GET1
	IN	A,P2
	MOVI	R1,$7F		;INIT INDEX FOR 128-BYTE SECTORS
	JB5	GET2		;IF SECTOR SIZE IS 128
	MOVI	R1,$FF		;INIT INDEX FOR 256-BYTE SECTORS
GET2
	MOV	A,R1
	MOV	R0,A
	DECR	R0		;INDEX FOR SECOND BYTE
	MOVI	R2,SEC1		;TRIP COUNT FOR 1 SECOND DELAY

;	ISSUE READ SECTOR COMMAND

	SETREG	WCMD
	MOVI	A,RDSEC
	MOVX	XR0,A

;	READ FIRST DATA BYTE

	SETREG	RDAT
GET3
	JTF	GET4
GET6
	JNDRQ	GET3		;WAIT FOR DRQ
	JNDRQ	GET3		;FILTER DRQ GLITCHES
GET5
	MOVX	A,XR0		;BRING IN FIRST BYTE
	CPL	A		;COMPLEMENT IT
	MOV	XR1,A		;STORE IT IN RAM
	CLR	A
	MOV	T,A		;RESET THE TIMER
	JTF	GET18		;RESET TIMER OVERFLOW FLAG
GET18
	JDRQ	GET19

;	READ IN THE MIDDLE BYTES

GET8
	JTF	GET9
GET7
	JNDRQ	GET8
GET19
	MOVX	A,XR0		;READ DATA BYTE
	CPL	A		;COMPLEMENT IT
	MOV	XR0,A		;STORE IT IN RAM
	DJNZ	R0,GET7		;IF MORE BYTES TO DO

;	READ IN THE LAST BYTE

GET10
	JTF	GET9
	JNDRQ	GET10
	MOVX	A,XR0		;BRING IN LAST BYTE
	CPL	A		;COMPLEMENT IT
	MOV	R0,A		;STORE IT IN R0

;	WAIT FOR OPERATION COMPLETE

GET11
	JTF	GET9
	IN	A,P1
	ANLI	A,INTRQ
	JNZ	GET11		;IF NOT COMPLETE
	STOP	TCNT
	MOV	A,R0
	MOV	T,A		;PUT LAST BYTE IN TIMER
	SETREG	RSTA
	MOVX	A,XR0
	MOV	R0,A		;STORE OPERATION STATUS IN R0

;	RECOGNIZE MFM, TRACK 0, SIDE 0, SECTOR 1-3

	IN	A,P1
	ANLI	A,SSO OR DDEN
	JNZ	GET12		;IF FM OR SIDE 1
	SETREG	RTRK
	MOVX	A,XR0
	JNZ	GET12		;IF NOT TRACK 0
	SETREG	RSEC
	MOVX	A,XR0
	ADDI	A,$FC
	JC	GET12		;IF NOT SECTOR 1, 2, OR 3

	IN	A,P2
	JB5	GET13		;IF SS/SD OR SS/2D

	MOV	A,R0
	MOV	T,A		;STORE STATUS IN TIMER
	MOVI	R0,$7F
GET14
	MOV	A,R0
	ORLI	A,$80
	MOV	R0,A		;POINT TO HIGH RAM
	MOV	A,XR0		;FETCH A BYTE FROM HIGH RAM
	XCH	A,R0
	ANLI	A,$7F
	XCH	A,R0
	MOV	XR0,A		;WRITE IT TO LOW RAM
	DJNZ	R0,GET14	;IF MORE BYTES TO COPY
	MOVI	R0,$80
	MOV	A,XR0		;NEW LAST BYTE
	MOV	R0,A
	MOV	A,T
	XCH	A,R0		;PUT STATUS IN R0
	MOV	T,A		;PUT LAST BYTE IN TIMER
	MOVI	A,$7F		;TRANSMIT POINTER
	JUMP	GET15

GET13
	MOV	A,R0
	ANLI	A,$FB		;TURN OFF LOST DATA BIT
	MOV	R0,A

;	INITIALIZE R0 FOR TRANSMISSION

GET12
	IN	A,P2
	RL	A
	RL	A
	ANLI	A,$80
	DECR	A
GET15
	XCH	A,R0		;STATUS TO ACCUMULATOR

;	CHECK STATUS

	ANLI	A,$3C		;MASK RELEVANT BITS
	JNZ	SRT		;IF ERROR, GO DO SOFT RETRY

;	SUCCESSFUL COMPLETION OF GET

GET17
	CLR	F1		;INDICATE SUCCESS
	LNGJMP	SEND		;SEND DATA FRAME, GO TO IDLE

;	HANDLE GET TIMEOUTS

GET4
	JNDRQ	GET16
	JDRQ	GET5		;FILTER DRQ GLITCHES
GET16
	DJNZ	R2,GET6		;IF TIME NOT EXHAUSTED
	STOP	TCNT
	SETREG	WCMD
	MOVI	A,FRCINT
	MOVX	XR0,A		;DO FORCED INTERRUPT
	PAUSE	R0,US200	;DELAY 200 US
	JUMP	HRT		;DO HARD RETRY

GET9
	STOP	TCNT
	SETREG	WCMD
	MOVI	A,FRCINT
	MOVX	XR0,A		;DO FORCED INTERRUPT
	PAUSE	R0,US200


**	SRT - SOFT RETRY
*
*	ENTRY CONDITIONS:
*		LAST DATA BYTE IN TIMER

SRT
	MOV	A,PSW
	DECR	A
	JB3	SEC18		;IF RETRIES NOT EXHAUSTED


**	HRT - HARD RETRY
*
*	ENTRY CONDITIONS:
*		LAST DATA BYTE IN TIMER

HRT
	JF1	HRT1		;IF RETRIES EXHAUSTED
	CPL	F1		;INDICATE RETRY IN PROGRESS
	SETREG	RTRK
	JUMP	RST		;GO DO RESTORE SEQUENCE

HRT1
	MOVI	R0,CSTAT
	MOVI	XR0,4		;STATUS CODE FOR UNSUCCESSFUL OPERATION
	MOVI	R0,0		;NO DATA FRAME
	IN	A,P2
	ANLI	A,$FF-ACLR
	XRLI	A,AGET
	JNZ	HRT2		;IF PUT
	IN	A,P2
	RL	A
	RL	A
	ANLI	A,$80
	DECR	A
	MOV	R0,A		;DATA FRAME LENGTH
HRT2
	LNGJMP	SEND		;SEND ERROR, GO TO IDLE


**	HANDLE PUT COMMAND
*
*	ENTRY CONDITIONS:
*		LAST DATA BYTE IN R0

PUT1

;	INITIALIZE FOR PUT

	IN	A,P2
	RL	A
	RL	A
	ANLI	A,$80
	DECR	A
	XCH	A,R0
	XCH	A,XR0
	CPL	A		;COMPLEMENT FIRST BYTE
	MOV	R0,A

;	ISSUE WRITE SECTOR COMMAND

	SETREG	WCMD
	MOVI	A,WRSEC
	MOVX	XR0,A
	SETREG	WDAT

;	SEND FIRST DATA BYTE

	MOV	A,R0
	MOVI	R0,SEC1		;TRIP COUNT FOR 1 SECOND TIMEOUT
	STRT	T

PUT2
	JTF	PUT3
PUT4
	JNDRQ	PUT2
	JNDRQ	PUT2		;FILTER DRQ GLITCHES
PUT5
	MOVX	XR0,A		;WRITE FIRST BYTE
	CPL	A		;UN-COMPLEMENT
	XCH	A,R0
	CLR	A
	MOV	T,A		;RESET THE TIMER
	JTF	PUT6		;CLEAR TIMER OVERFLOW FLAG
PUT6
	IN	A,P2
	RL	A
	RL	A
	ANLI	A,$80
	DECR	A
	XCH	A,R0
	XCH	A,XR0		;LAST BYTE TO ACCUMULATOR
	DECR	R0

;	WRITE THE MIDDLE BYTES

PUT7
	XCH	A,XR0		;GET A BYTE FROM RAM
	CPL	A		;COMPLEMENT IT
	JDRQ	PUT13
PUT8
	JTF	PUT9		;IF TIMED OUT
	JNDRQ	PUT8
PUT13
	MOVX	XR0,A		;WRITE THE BYTE
	CPL	A		;UN-COMPLEMENT IT
	XCH	A,XR0		;PUT IT BACK INTO RAM
	DJNZ	R0,PUT7		;ADVANCE POINTER

;	WRITE THE LAST BYTE

	MOV	R0,A		;SAVE LAST BYTE IN R0
	CPL	A		;COMPLEMENT IT
	JDRQ	PUT14
PUT10
	JTF	PUT11
	JNDRQ	PUT10
PUT14
	MOVX	XR0,A		;WRITE THE LAST BYTE

;	WAIT FOR OPERATION COMPLETE

PUT12
	JTF	PUT11
	IN	A,P1
	ANLI	A,INTRQ
	JNZ	PUT12		;IF NOT COMPLETE
	STOP	TCNT
	MOV	A,R0
	MOV	T,A		;PUT LAST BYTE IN TIMER
	SETREG	RSTA
	MOVX	A,XR0		;READ STATUS REG
	JB6	PUT15		;IF WRITE PROTECT
	ANLI	A,$14		;RELEVANT STATUS BITS
	JZ	PTV1		;IF SUCCESS, GO DO VERIFY
	JUMP	SRT		;FAILURE, GO DO SOFT RETRY

;	HANDLE PUT TIMEOUTS

PUT3
	JNDRQ	PUT16
	JDRQ	PUT5
PUT16
	DJNZ	R0,PUT4		;IF TIME NOT EXHAUSTED
	STOP	TCNT
	CPL	A		;UN-COMPLEMENT
	MOV	R0,A
	IN	A,P2
	RL	A
	RL	A
	ANLI	A,$80
	DECR	A
	XCH	A,R0
	XCH	A,XR0		;RESTORE FIRST BYTE TO RAM
	MOV	T,A		;LAST BYTE TO TIMER
	IN	A,P1
	ANLI	A,INTRQ
	JZ	PUT17		;IF OPERATION NOT COMPLETE
	SETREG	RSTA
	MOVX	A,XR0		;READ STATUS REG
	JB6	PUT18		;IF WRITE PROTECT
PUT17
	SETREG	WCMD
	MOVI	A,FRCINT
	MOVX	XR0,A		;DO FORCED INTERRUPT
	PAUSE	R0,US200
	JUMP	HRT		;GO DO HARD RETRY

PUT9
	CPL	A
	XCH	A,XR0		;PUT BYTE BACK IN RAM
	MOV	R0,A		;SAVE LAST BYTE IN R0
PUT11
	STOP	TCNT
	MOV	A,R0
	MOV	T,A		;PUT LAST BYTE IN TIMER
	IN	A,P1
	ANLI	A,INTRQ
	JZ	PUT19		;IF OPERATION NOT COMPLETE
	SETREG	RSTA
	MOVX	A,XR0		;READ STATUS
	JB6	PUT18		;IF WRITE PROTECT
PUT19
	SETREG	WCMD
	MOVI	A,FRCINT
	MOVX	XR0,A		;DO FORCED INTERRUPT
	PAUSE	R0,US200	;DELAY 200 US
	JUMP	SRT		;GO DO SOFT RETRY

PUT18
	MOVI	R0,CSTAT
	MOVI	XR0,$0C		;STATUS CODE FOR WRITE PROTECT
	MOVI	R0,0		;NO DATA FRAME
	CLR	F1
	CPL	F1		;INDICATE ERROR
	LNGJMP	SEND		;SEND ERROR, GO TO IDLE

**	HANDLE VERIFICATION

PTV1
	IN	A,P2
	ANLI	A,$FF-ACLR
	XRLI	A,APUTV
	JNZ	PTV10		;IF VERIFY NOT REQUIRED

;	SHIFT AND COMPLEMENT INTERNAL RAM

	IN	A,P2
	RL	A
	RL	A
	ANLI	A,$80
	MOV	R0,A		;INDEX TO FIRST DATA BYTE
	DECR	R0
	RLC	A		;SET CARRY FOR LATER USE
	MOV	A,T		;LAST DATA BYTE TO ACCUMULATOR
	CPL	A		;COMPLEMENT IT
	XCH	A,XR0		;FIRST DATA BYTE TO ACCUMULATOR
	CPL	A		;COMPLEMENT IT
	DECR	R0
PTV11
	XCH	A,XR0		;BRING A DATA BYTE TO ACCUMULATOR
	CPL	A		;COMPLEMENT IT
	INCR	R0
	XCH	A,XR0		;SHIFT IT FORWARD ONE POSITION
	DECR	R0
	XCH	A,XR0		;RESTORE FIRST DATA BYTE TO ACCUMULATOR
	DJNZ	R0,PTV11	;IF MORE BYTES TO DO
	MOV	R0,A		;PUT FIRST DATA BYTE IN R0

;	ISSUE READ SECTOR COMMAND

	STOP	TCNT
	JTF	PTV12		;CLEAR TIMER OVEDRFLOW FLAG
PTV12
	CLR	A
	MOV	T,A		;RESET THE TIMER
	SETREG	WCMD
	MOVI	A,RDSEC
	MOVX	XR0,A
	SETREG	RDAT
	STRT	T
	MOVI	A,SEC1		;TRIP COUNT FOR 1 SECOND TIMEOUT

;	READ THE FIRST TWO BYTES

PTV2
	JTF	PTV3
PTV4
	JNDRQ	PTV2
	JNDRQ	PTV2		;FILTER DRQ GLITCHES
PTV13
	MOVX	A,XR0		;READ FIRST BYTE
	XRL	A,R0		;COMPARE
	JNZ	PTV5		;IF INCORRECT
	MOV	R0,A		;STORE ZERO IN R0
VER9
	JDRQ	PTV6
VER7
	INCR	A
	JDRQ	PTV6
	JZ	PTV5		;IF TIMED OUT
	JNDRQ	PTV7
PTV6
	MOVX	A,XR0		;READ SECOND BYTE
	XCH	A,R0
	RRC	A
	DECR	A		;INDEX TO SECOND BYTE
	XCH	A,R0
	XRL	A,XR0		;COMPARE
	JNZ	PTV5		;IF INCORRECT
	DECR	R0

;	READ AND COMPARE THE REMAINING BYTES

PTV14
	JDRQ	PTV15
PTV16
	INCR	A
	JDRQ	PTV15
	JZ	PTV5		;IF TIMED OUT
	JNDRQ	PTV16
PTV15
	MOVX	A,XR0		;READ BYTE
	XRL	A,XR0		;COMPARE
	JNZ	PTV5		;IF INCORRECT
	DJNZ	R0,PTV14	;IF MORE BYTES TO DO

;	WAIT FOR OPERATION COMPLETE

	CLR	A
	MOV	T,A		;RESET TIMER
	JTF	PTV17		;CLEAR TIMER OVERFLOW FLAG
PTV17
	JTF	PTV5		;IF TIMED OUT
	IN	A,P1
	ANLI	A,INTRQ
	JZ	PTV17		;IF NOT COMPLETE
	STOP	TCNT
	SETREG	RSTA
	MOVX	A,XR0		;READ STATUS
	ANLI	A,$3C		;SELECT RELEVANT STATUS BITS
	JNZ	PTV5		;IF ERROR

;	COME HERE FOR SUCCESSFUL VERIFY

PTV10
	CLR	F1		;INDICATE NO ERROR
	MOVI	R0,0		;NO DATA FRAME TO TRANSMIT
	LNGJMP	SEND		;SEND COMPLETE, GO TO IDLE

;	HANDLE VERIFY TIMEOUTS AND ERRORS

PTV3
	JNDRQ	PTV18
	JDRQ	PTV13
PTV18
	DECR	A
	JNDRQ	PTV19
	JDRQ	PTV13
PTV19
	JNZ	PTV4		;IF 1 SECOND TIME NOT EXHAUSTED

PTV5
	CLR	F1
	CPL	F1		;SO HARD RETRY WILL FAIL
	JUMP	HRT		;SEND ERROR, GO TO IDLE
