	.title	'hard disk format program'
	.ident	hardform
version	==	0
revision	==	1
;last changed 19-May-82
	.PABS
	.PHEX

;
;hardform IS DESIGNED TO RUN AT 4100 IN THE HDC 
;USER MEMORY AREA. IT IS ENTERED VIA THE HDC ROM
;WITH THE COMMAND BLOCK AS FOLLOWS.
;
;BYTE 0= 09 (PERFORM THIS PROGRAM)
;BYTE 1= STARTING TRACK
;BYTE 2= NUMBER OF MOVEABLE HEADS
;BYTE 3= STARTING SECTOR
;BYTE 4= FF FOR FIXED HEADS , 00 FOR NO FIXED HEADS
;BYTE 5= STARTING HEAD
;BYTE 6= NO OF SECTORS/TRK
;BYTE 7= MAX TRACK NUMBER
;
;
;
;	it uses the common set of
;	equates to describe memory and ports etc
;


;
;		TABLE OF CONTENTS		PAGE
;	1. equates
;	2. formate code
;
	.insert	hardequ		;equates


	.page
	.sbttl	'format code'


	.LOC	usrprog
	LDA	COMMBUFF
	CPI	09
	JNZ	03EEH		;RET IF NOT PROPER COMD
	CALL	hfsetup		;MOVE TO STARTING TRACK
	LXI	H,TAG0
	LXI	D,FIXFLG
	LXI	B,4
	LDIR			;SAVE INPUT PARAMS
	LXI	H,WRTBUFF	;FORMAT LEADING ZEROS
	LXI	B,14
	XRA	A
	CALL	FMTFILL
	LXI	H,WRTBUF	;SOURCE OF 0'S
	LXI	D,TAG0
	LXI	B,4
	LDIR			;FILL TAG0+  WITH 0
	LXI	H,BUFDATA	;FORMAT DATA WITH E5'S
	LXI	B,400H
	MVI	A,0E5H
	CALL	FMTFILL
	LXI	H,BUFECC	;FORMAT TRAILING ZEROS	 	
	LXI	B,100
	XRA	A
	CALL	FMTFILL
WRTCYL:	MVI	A,01		;BEGINNING OF WRITE
	STA	PHYSEC		;CYLINDER LOOP.
	CALL	FHEADER		;FORMAT THE HEADER.
WRTRACK:			;START OF WRITE TRACK
				;LOOP.
	LDA	TEMPHEAD	;SELECT PROPER HEAD.
	OUT	HEADSPORT
	CALL	hffinds1		;USE INDEX MARKER FOR
				;FIRST SECTOR.	
WRTSEC:				;START OF WRITE SECTOR
				;LOOP.
	MVI	A,40H		;DELAY TO FINISH PREV
..2:	DCR	A
	JRNZ	..2
	MVI	A,96H		;ISSUE WRITE COMD TO HD	
	OUT	COMMAND
	MVI	C,0FFH		;INITIALIZE TIMEOUT
				;COUNTER.
hfwl2:	IN	CSTATUS		;SAMPLE CONT. STATUS
	RAL			;AND STOP WITH EITHER 
	RAL			;DONE, WRITE FAULT, OR
	RAL			;A TIMEOUT.
	JRC	hfwl3		;JUMP IF NOT DONE.
	IN	HSTATUS		;DONE,TEST FOR WRTFAULT.
	ANI	8H
	JRNZ	hfwfault	 	;JUMP ON WRTFAULT
	MVI	A,40H
..2:	DCR	A
	JRNZ	..2
	OUT	COMMAND
	JMPR	CONTMAIN	;JUMP AROUND TIMEOUT
				;COUNTER.
hfwl3:	DCR	C		;DEC. TIMEOUT COUNTER.
	JRNZ	hfwl2
	XRA	A		;TIMEOUT ERROR, STOP.
	ADI	13H
	STA	ERRSTAT
	JMP	STOP
hfwfault:	MVI	A,40H
	OUT	FCCOMD		;CLEAR WRITE FAULT.
	XRA	A
	OUT	COMMAND		;GET RAM BACK.
	ADI	11H
	STA	ERRSTAT
	JMP	STOP
CONTMAIN:
	LDA	PHYSEC		;SEE WHAT SECTOR WAS
	LXI	H,MAXSEC	;JUST FORMATTED
	CMP	M
	JRNZ	NXSEC
	MVI	A,02H		;START FORMATTING EVEN
	STA	PHYSEC		;SECTORS.
	CALL	FHEADER		;FORMAT HEADER.
	JMP	WRTSEC		;LOOP BACK TO WRITE EVEN
				;SECTORS.
NXSEC:	INR	A		;INC. SECTOR NUMBER BY
	INR	A		;TWO, WRITE NEXT SECTOR.
	LXI	H,MAXSEC
	CMP	M
	JRZ	..2
	JP	NXHEAD
..2:	STA	PHYSEC
	CALL	FHEADER		;FORMAT HEADER.
	JMP	WRTSEC		;LOOP BACK TO FORMAT
				;NEXT SECTOR.
NXHEAD:	LDA	TEMPHEAD	;FORMAT NEXT TRACK.
	LXI	H,PHYHEAD
	CMP	M
	JRZ	NXCYL		;JUMP IF ALL HEADS ON
	INR	A		;CYLINDER ARE FORMATTED.
	STA	TEMPHEAD
	CPI	16		;IF TEMPHEAD=16 THEN
	MVI	A,01		;FIXED HEADS.
	STA	PHYSEC		;INITIALIZE PHYSEC.
	MVI	A,00
	STA	ERRSTAT		;JMP IF FIXED HEADS
	JZ	STOP		;ARE FORMATTED, STOP.
	CALL	FHEADER		;FORMAT HEADER.
	JMP	WRTRACK		;LOOP BACK TO WRT NEXT
				;TRACK.
NXCYL:	LXI	H,PHYTRACK
	LDA	MAXTRACK
	CMP	M
	JRZ	FMFIXHD
	INR	M
	CALL	hfsetup		;MOVE HEADS TO NEXT CYL.
	XRA	A
	STA	TEMPHEAD
	JMP	WRTCYL		;LOOP BACK TO FORMAT
				;NEXT CYLINDER.
FMFIXHD:			;FORMAT FIXED HEADS IF
	LDA	FIXFLG		;NEEDED.
	CPI	0FFH
	JNZ	STOP		;JMP IF NO FIXED HEADS.
	MVI	A,8
	STA	TEMPHEAD	;FIXD HEADS START AT 8.	
	MVI	A,16
	STA	PHYHEAD		;PHYHEAD MUST EQUAL 16
				;FOR FIXED HEADS.
	MVI	A,0FFH
	STA	PHYTRACK	;PHYTRACK=FF FOR FIXED
	MVI	A,01		;HEADS.
	STA	PHYSEC		;INITIALIZE PHYSEC.
	CALL	FHEADER		;FORMAT HEADER
	JMP	WRTRACK	 	;LOOP BACK TO FORMAT
				;FIXED HEADS.
;
STOP:	LXI	D,01H		;SEND BACK ERROR STAT.
	LXI	H,ERRSTAT
	CALL	03FAH		;PWRITE
	JMP	03EEH		;RETURN TO GETCOMMAND.
;
hfsetup:
;SETUP POSITIONS THE HEAD ASSEMBLY TO THE CORRECT 
;CYLINDER POSITION.
	LDA	TRKD0		;GET PRESENT TRACK.
	MOV	B,A
	LDA	PHYTRACK	;GET DESIRED TRACK.	
	MOV	C,A
				;CYLINDER.
	STA	TRKD0		;OLD CYL BECOMES NEW
				;CYLINDER.
	SUB	B		;COMPUTE DIFFERENCE.
	RZ			;RET IF ALREADY THERE.
	JRNC	INSTEP		;JUMP TO STEP IN.
	MOV	A,B
	SUB	C		;COMPUTE DIFFERENCE.
	MOV	C,A		;STEP COUNT IN C.
	JMP	hfstepout
INSTEP:	MOV	C,A		;STEPCOUNT IN C.
	MVI	A,10H		;SET DIRECTION IN.
	JMP	hfst2
hfstepout:
	XRA	A		;SET DIRECTION OUT.
hfst2:	OUT	HEADSPORT
hfst1:	ORI	20H		;STEP BIT SET.
	OUT	HEADSPORT
	ANI	1FH		;RESET STEP BIT.
	OUT	HEADSPORT
	DCR	C
	JRNZ	hfst1
hfwait:	IN	HSTATUS		;TEST FOR SEEK COMP.
	ANI	2
	JRZ	hfwait
	MVI	A,40		;DELAY FOR 40 MS.
hfdly:	PUSH	B
hfdly2:	MVI	C,0F8H		;ADJUST FOR 1 MS.
hfdly3:	DCR	C
	JRNZ	hfdly3
	DCR	A
	JRNZ	hfdly2
	POP	B
	RET
hfbadcomMAND:
	MVI	A,80H
	STA	ERRSTAT
	POP	B		;CORRECT STACK.
	JMP	STOP
;
;
FMTFILL:
;FILLS MEMORY STARTING AT (HL) WITH CONTENTS OF A 
;FOR (BC) LOCATIONS.
	MOV	E,A
hffill2:	MOV	M,E
	INX	H
	DCX	B
	MOV	A,B
	ORA	C
	JRNZ	hffill2
	RET
;
;
FHEADER:
;THIS PROGRAM FORMATS THE HEADER FIELD.
	LXI	H,BUFSYNC
	MVI	M,0FH		;INIT SYNC CHAR.
	INX	H
	LDA	PHYTRACK	;INIT CYLINDER CHAR.
	MOV	M,A
	INX	H
	MOV	B,A		;STORE THE SUM IN B.
	LDA	TEMPHEAD	;INIT HEAD CHAR.
	MOV	M,A
	INX	H
	ADD	B
	MOV	B,A
	LDA	PHYSEC		;INIT SECTOR CHAR.
	MOV	M,A
	INX	H
	ADD	B
	MOV	B,A
	XRA	A
	MOV	M,A		;INIT TAG0.
	INX	H
	MOV	M,A		;INIT TAG1.
	INX	H
	MOV	M,A		;INIT CON0.
	INX	H
	MOV	M,A		;INIT CON1.
	INX	H
	SUB	B		;STORE CHECKSUM.
	MOV	M,A
	RET
;
;
hffinds1:
;USES INDEX TO FIND FIRST SECTOR
	IN	0FEH		;CLEAR INDEX
SAMPSTAT:	
	IN	HSTATUS		;WAIT FOR INDEX MARKER.
	ANI	10H
	JRZ	SAMPSTAT
	RET
;
FIXFLG:	.BYTE	0
TEMPHEAD: .BYTE	0
MAXSEC:	.BYTE	0
MAXTRACK: .BYTE	0
ERRSTAT: .BYTE	0
;
;	.LOC	4080H
;COMMBUFF	=	.
;PHYTRACK	=	COMMBUFF+1
;PHYHEAD		=	PHYTRACK+1
;PHYSEC		=	PHYHEAD+1
;TAG0		=	PHYSEC+1
;TAG1		=	TAG0+1
;CON0		=	TAG1+1
;CON1		=	CON0+1	
;	.LOC	COMMBUFF+8
;TRKD0		=	.
;RDAFTW		=	TRKD0+1
;
;WRTBUFF		=	0E000H
;BUFSYNC		=	WRTBUFF+14
;BUFCYL		=	BUFSYNC+1
;BUFHEAD		=	BUFCYL+1
;BUFSEC		=	BUFHEAD+1
;BUFCK1		=	BUFSEC+5
;BUFDATA		=	BUFCK1+1
;BUFECC		=	BUFDATA+1024
;
;
	.END

