.page
.sbttl	'Physical reads and writes'
rwversion  ==	1
rwrevision ==	0	;last modified 6-Dec-83

;
;	version 0.0 	27-Oct-83	les wilson
;	adopted from hardrom code.  will
;	now have reads and writes included in firmware
;	to allow optimization of settling time
;

.page
.sbttl	'seek and head select routines'

;
;SEEK TRACK 0
HSEEK:
	XRA	A		
	STA	TRKD0
	mvi	b,0ffh		;max tracsk to move
H2:
	IN	HSTATUS
	ANI	4		;TEST TRACK ZERO BIT
	JRNZ	SETUP		;AT ZERO IF SET
	MVI	C,1
	CALL	STEPOUT
	rnz	
	mvi	a,2	;delay in millisecs to allow
	call	dly	;at least partial settling
	djnz	h2
	mvi	a,hdehometimeout
	ora	a
	ret
;
;
;
BADMAP:			;SEE IF SECTOR IS IN BAD SECTOR TABLE
			;IF SO, CHANGE PHYSICAL TRACK, HEAD,
			;SECTOR TO NEW VALUE
			;TABLE IS IN THE FORM SECTOR,HEAD,TRACK

	LHLD	PHYTRACK
	XCHG
	LDA	PHYSEC
	MOV	C,A
	push	psw
	push	d	;save registers while getting
			;indirect badtable in hl
	lda	unitno
	slar	a	;mult by 2
	mov	e,a
	mvi	d,0
	LXI	H,badloc
	dad	d	;now have pointer to table
			;entry
	mov	e,m
	inx	h
	mov	d,m
	xchg		;hl points to bad sector table
			;for selected unit
	pop	d
	pop	psw	
	MVI	B,0		;MAX 256 ENTRIES
BAD4:
	MOV	A,M
;
	ORA	A	;A ZERO IN THE SECTOR FIELD MEANS TABLE 
			;IS NOW EMPTY
	JRZ	SETUP
;
BAD6:
	CMP	C
	JRNZ	INCR3
	INX	H
	MOV	A,M
	CMP	D		;CMP HEAD
	JRNZ	INCR2
	INX	H
	MOV	A,M
	CMP	E		;CMP TRACK
	JRNZ	INCR1
	JMPR	GOTONE
INCR3:	INX	H
INCR2:	INX	H
INCR1:	INX	H
	INR	B
	JRNZ	BAD4
	JMPR	SETUP
;
GOTONE:
;IF WE GOT HERE, THE SECTOR,HEAD,TRACK WAS IN THE TABLE
;	NOTE:  FOLLOWING CODE applies to all drives
;	USE 8 SEC/TRACK FOR SPARES ... 2 TRACK*4 HEAD
;	*8 SEC = 64 ENTRIES
;	or
;	USE 8 SEC/TRACK FOR SPARES ... 2 TRACK*8 HEAD
;	*8 SEC = 128 ENTRIES
	MOV	A,B
	ANI	07H
	INR	A		;0-7 MAPS 1-8
	STA	PHYSEC
	MOV	A,B
	RRC
	RRC
	RRC
	MOV	B,A		;SAVE ROTATED
	ANI	1		;NEXT BIT IS TRK
	lxi	h,disktracks
	add	m
	sui	2		;last or next to last
	STA	PHYTRACK	;track
	MOV	A,B
	RRC			;GET HEAD
	lxi	h,disksize	;head mask
	ANa	m
	STA	PHYHEAD
SETUP:
;
; SEEK TRACK
;
	LDA	TRKD0		;GET CURRENT TRACK
	CPI	0FFH		;SEE IF NEEDS RESTORE
	JRZ	HSEEK
	MOV	B,A
	LDA	PHYTRACK
	MOV	C,A
	CPI	0FFH		;IF FIXED HEADS
	JRZ	SELHEAD
	lxi	h,disktracks
	cmp	m		;LARGEST LEGAL TRACK
	JRNC	badtrack
	STA	TRKD0		;SAVE NEW TRK
	SUB	B		;COMPUTE DIFFERENCE
	JrZ	ontrack		;already on track
	JRNC	SPOS
	MOV	A,B		;CUR TRK
	SUB	C		;DIFFERENCE AGAIN
	MOV	C,A		;PARAMETER=# TRKS TO STEP OUT
	CALL	STEPOUT
	rnz			;error detected
	JMPR	SELHEAD
;
;	if already on track allow settling if last
;	operation was a read and current operation
;	is a write
;
ontrack:
	lda	fullsettleoccurred
	cpi	true
	jrz	selhead
	mvi	a,true
	sta	fullsettleoccurred
	lda	nosettleok
	cpi	true
	jrz	..longdelay
	mvi	a,14	;15 millisec settle on read
	jmpr	..dodelay
..longdelay:
	mvi	a,29		;settle time in
..dodelay:
	call	dly		;millisecs
	jmpr	selhead
;
SPOS:
	MOV	C,A
	MVI	A,10H		;SET DIRECTION IN
	CALL	stepin
	rnz
;
SELHEAD:
;
;VALID HEAD CHECK 
;
	lda	disksize	;effectively headmask
	cma
	lxi	h,phyhead
	ana	m
	jrz	..headok	;no bits outside of mask
	mvi	a,hdebdhead
	ret
..headok:
	mov	a,m
	OUT	HEADSPORT
	XRA	A		;ZERO FLAG
	RET

;
;	select the physical drive
;
selunit:
	lda	unitno		;get drive number in 
				;head select bits
	cma			;compliment bits
	ani	3h		;keep only 3 low bits
	ori	fltclrbit
	out	fccomd
	xri	fltclrbit
	out	fccomd		;toggle fault clear
	ret

	
;
badtrack:
	MVI	A,hdebdtrack
	ORA	A	;SET FLAG
	RET
;
STEPOUT:
;	tracks to step(seek) passed in c
;	to step in set a reg to 10h and enter at
;	stepin
;DESTROYS A AND C
	XRA	A
stepin:	OUT	HEADSPORT	;OUTPUT DIRECTION
ST1:	ORI	20H		;SET STEP BIT
	OUT	HEADSPORT
	ANI	01FH		;RESET STEP BIT
	OUT	HEADSPORT
	DCR	C		;STEP COUNT
	JRNZ	ST1		;LOOP
	push	d
	lxi	d,0ffffh	;wait a long time
WAIT:	IN	HSTATUS
	ANI	2		;TEST SEEK COMPLETE
	jrnz	..seekcomplete
	dcx	d
	mov	a,d
	ora	e
	jrnz	wait
	pop	d
	adi	hdeseektimeout	;error type
	ret
..seekcomplete:
	pop	d
	lda	readflag ;settle specific time for
	cpi	true	;writes, until good sector
	jrnz	..dodelay ;for reads
	mvi	a,false
	sta	fullsettleoccurred
	lda	nosettleok
	xri	true
	rz		;no settle needed
	mvi	a,15	;delay 15 millisec
	jmpr	dly
;
;	do a fixed delay for writes
;
..dodelay:
	mvi	a,true
	sta	fullsettleoccurred
	MVI	A,30		;DELAY 30 MSEC
	;specification for fujitsu 8 inch drives
DLY:	PUSH	B		;SAVE REGS
DLY2:	MVI	C,223		;ADJUST FOR 1 MSEC
DLY3:	DCR	C	;4 t states + 1 wait state
	JRNZ	DLY3	;12 t states + 1 wait state
			;18 tstates for loop
	DCR	A
	JRNZ	DLY2
	POP	B
	RET
	.page
	.sbttl	'read or write sector routines'
;
;
;	READ OR WRITE SECTOR ROUTINES
;
;
READSEC:
	lxi	h,readflag
	mvi	m,true		;flag as read operation
	call	selunit		;talk to right unit
	CALL	BADMAP
	RNZ
	CALL	FINDS1
	RNZ
	CALL	READW	;ACTUALLY READ THE SECTOR
	RNZ		;RETURN IF ERROR
;THE READ ROUTINE DID NOT HAVE PROBLEMS
;WE WILL NOW VERIFY THE HEADER FIELD FOR THE
;SECTOR THAT WAS READ IN
	CALL	CHKHDR	;CALCULATE THE CHECKSUM
	JRZ	READS2
	MVI	A,hdechecksum	;HEADER CHECKSUM ERROR
	RET
READS2:
	LDA	PHYSEC	;CHECK THE SECTOR THAT WAS DESIRED
	MOV	B,A
	LDA	RDSEC	;WITH THE ONE THAT WAS READ
	SUB	B
	JZ	CHKTRKHD      ;IF THEY MATCH, GO VERIFY
				;THE TRACK AND HEAD
	JMP	X3		;ELSE SET ERROR CODE 22
;
;
WRITESEC:
	lxi	h,readflag    ;flag as write operation
	mvi	m,false
	call	selunit		;talk to right unit
	CALL	BADMAP
	RNZ
	LXI	H,wrtbuff	;SET UP DISK BUFFER AREA
	LXI	B,14		;INITIAL ZEROES
	XRA	A
	CALL	FILL
	MVI	M,0FH		;SYNC CHAR
	INX	H
	LDA	PHYTRACK		;CYLINDER #
	MOV	M,A
	INX	H
	MOV	B,A
	LDA	PHYHEAD		;HEAD #
	MOV	M,A
	INX	H
	ADD	B
	MOV	B,A
	LDA	PHYSEC		;SECTOR #
	MOV	M,A
	INX	H
	ADD	B
	MOV	B,A
	LDA	TAG0
	MOV	M,A
	INX	H
	ADD	B
	MOV	B,A
	LDA	TAG1
	MOV	M,A
	INX	H
	ADD	B
	MOV	B,A
	XRA	A	;SET CON0 AND CON1 TO 0
	MOV	M,A
	INX	H
	MOV	M,A
	INX	H
	SUB	B		;CHECKSUM TO 0
	MOV	M,A
	LXI	H,BUFECC
	XRA	A
	LXI	B,32
;
	CALL	FILL
	CALL	FINDS1
	RNZ
	jmp	WRITEW
		;RETurn from there
;
;
;
;
FILL:	MOV	E,A
FILL2:	MOV	M,E
	INX	H
	DCX	B
	MOV	A,B
	ORA	C
	JRNZ	FILL2
	RET
	.page
	.sbttl	'actual hardware read and write'
;
;
;
;	THE ACTUAL HARDWARE READ AND WRITE ROUTINES
;
;
READW:	CALL	HRD
	JMPR	HRWWAIT		;READ AND WAIT FOR IOF
HRD:	MVI	A,0C5H		;READ COMMAND BITS
	OUT	COMMAND
	RET
;
HWRT:	MVI	A,96H		;WRITE AND RAMD BITS
	OUT	COMMAND
	RET
WRITEW:	CALL	HWRT		;WRITE AND WAIT FOR IOF
HRWWAIT: MVI	C,0FFH		;TIMEOUT CONSTANT
WL2:	IN	CSTATUS		;TEST FOR I/OF
	RAL
	RAL
	RAL			;TEST BIT 5 - DONE
	JRC	WL3
	RAR
	RAR			;DONE - TEST ERROR
	jrnc	..noerr
	mvi	a,hdeunprocessederr	;incase
	ora	a		;no firmware
	jmp	procrderr		;process err 
..noerr:
	IN	HSTATUS
	ANI	8
	JRNZ	WFAULT
	mvi	b,0fh
..stall:djnz	..stall
	OUT	COMMAND		;TURN ON MEMORY AGAIN
	RET
WL3:	DCR	C		;TEST FOR TIMEOUT
	NOP
	NOP
	JRNZ	WL2
	XRA	A
	OUT	COMMAND		;GET RAM BACK
	ADI	hdetimeout	;SET TIMEOUT ERROR CODE
	RET
;
WFAULT:
	XRA	A
	OUT	COMMAND		;terminate command
	call	selunit		;strobe fault clear
	xra	a
	ADI	hdewritefault	;SET WRITE FAULT ERROR CODE
	RET
;
;
;
FINDS1:				;FIND SEC=AC-1
	LDA	PHYSEC
	DCR	A
	JRNZ	FScek		;JUMP IF NOT SECTOR ONE
	lxi	d,0fffh	;for time to wait count
	IN	clearindex
FSLP4:	IN	HSTATUS		;WAIT FOR INDEX MARKER
	ANI	10H
	jrnz	indexfound
	dcx	d
	mov	a,e
	ora	d
	jrnz	FSLP4		;keep trying
	adi	hdenoindex	;time out error
	ret
indexfound:
	XRA	A
	RET
fscek:			;check that valid sector
	lxi	h,disktype	;effectively sec/track
	cmp	m
	jrc	fslp3		;ok
	mvi	a,hdebdsector
	ora	a
	ret
FSLP3:
	MOV	D,A		;SAVE FOR COMPARE
	MVI	E,0		;FOR ERROR COUNT
FSL1:	PUSH	D
	CALL	READA		;READ AND ABORT
	POP	D
	JRNZ	NOTIT		;IF CHECKSUM ERROR RETRY
	LDA	RDSEC
	SUB	D		;COMPARE
	JRZ	CHKTRKHD	;VERIFY TRACK AND HEAD
				;DO A JMP INSTEAD OF CALL
				;TO SAVE CODE ON RETURN
NOTIT:	inr	E		;NO OF SECTORS CHECKED
	mov	a,e
	SUI	60		;2+REVOLUTIONS
	JRNZ	FSL1
	ADI	hdepreviousgone		;CAN NOT FIND SECTOR ERROR CODE
	RET
;
CHKTRKHD:		;VERIFY THAT WE ARE ON CORRECT TRACK AND HEAD
	LXI	H,RDCYL
	LDA	PHYTRACK
	CMP	M
	JRZ	X2
X3:			;ERROR!
	MVI	A,hdeheaderbad
	ora	a
	RET
X2:
	INX	H
	LDA	PHYHEAD
	SUB	M
	RZ
	JMPR	X3
;
;
READA:			;READ AND ABORT AFTER 32 BYTES
	CALL	HRD		;READ COMMAND TO DISK
	MVI	B,00	;SET READ AND ABORT COUNTER.
RA2:
	IN	CSTATUS
	ANI	10H		;PCB
	JRNZ	DLYAB		;WAIT FOR BYTE 32
	DJNZ	RA2
DLYAB:	MVI	A,128
RADL:	DCR	A
	JRNZ	RADL		;DELAY .5 MSEC FOR RFSH
	OUT	COMMAND		;GET RAM BACK
CHKHDR:			;CHECKSUM THE HEADER
	LXI	H,RDCK
RA3:	ADD	M
	DCR	L		;CHECKSUM ID FIELD
	JRNZ	RA3
	ORA	A		;SET FLAGS-SHOULD BE 0
	RET

