;
;	FLOPPY VERIFIER for DJ/DMA 5 INCH MEDIA
;	- INITIAL CODING  -  7/20/83  -  BJG
;
;	- V1.1-  change the read track verify to include
;		 table chaecking for errors, added TSTAT.  
;		 	8/1/83 - BJG

	ORG	0100H

BIOS	EQU	0F600H

BDOS	EQU	0005H

TSTCNT  EQU	1			;NUMBER OF PASSES 


;********************
CHANNEL	EQU	050H
TRACK	EQU	CHANNEL + 1
HEAD	EQU	CHANNEL + 2
DRIVE	EQU	CHANNEL + 3
HEAD0	EQU	0
HEAD1	EQU	080H

; ROUTINE IS TO PERFORM A SWAP LOGICAL TO FORCE 5 INCH DRIVE 0
; SAVES OLD LOGICAL SETUP FOR RETURN


	MVI	A,4
	STA	LOG			   ;INITALIZE LOG CONSTANT
	CALL	SWAPLOG
	CALL	SAVIT
	JMP	CHECK

SWAPLOG:
	LXI 	H,CHANNEL
	MVI	A,02EH			    ;SWAP LOGICAL COMMAND
	MOV	M,A
	INX	H
	LDA	LOG			    ;FORCE 5 INCH TO BE 0
	MOV 	M,A
	INX	H
	MVI	A,0
	MOV	M,A			    ;ZERO THE STATUS BYTE
	SHLD	RSTAT			    ;SAVE LOCATION FOR LATER
	INX	H
	CALL	HALT	
	OUT	0EFH			    ;KICK CONTROLLER
        LHLD	HSTAT
	LXI 	B,0			;TIMEOUT COUNTER
	MVI 	D,20H		;NUMBER OF TIMES THROUGH LOOP
SPLOOP:	DCX 	B
	MOV 	A,B
	ORA 	C
	JZ  	SLOOP1
	MOV 	A,M
	CPI 	00H			;CHECK FOR O.K		
	JZ  	SPLOOP
	CPI	040H		
	JNZ	TIMEOUT
	RET

SLOOP1:	DCR D
	JZ  TIMEOUT
	JMP SPLOOP

; STORE OLD LOGICAL CONFIGURATION FOR CORRECT RETURN

SAVIT:	LHLD	RSTAT
	MOV 	A,M		         ;GET SWAP LOG STATUS
	ANI	04			 ;MASK OFF EXTRA BITS
	STA	LOG			 ; SAVE FOR RETURN
	RET

	

CHECK:  LDA	082H			    ;PICK UP DRIVE NUMBER	
	ANI	04FH			    ;UPPER CASE CONVERT	
	CPI	'M'
	JZ	SELECTM
	CPI	'C'
	JNZ	BADPAR

; SELECT THE DISK SIZE    MICRONIX = 40 TRACKS
;			  CP/M	   = 35 TRACKS
			  
SELECTC:
	MVI	A,34
	STA	SIZE
	JMP	BEGIN
	
SELECTM:
	MVI	A,39
	STA	SIZE
	

; PRINT THE SIGNON MESSAGE

BEGIN:	LXI	SP,1000H
	MVI	C,02
	MVI	E,0CH
	CALL	COUT	                    ;PRINT FORM FEED
	LXI	D,SIGNON
	CALL	PMSG
	CALL	CRLF
	MVI	A,TSTCNT  		     ;NUMBER OF PASSES
	STA	PASS	Š
;  WAIT FOR THE USER TO TYPE A 'CR'

WAIT: 	LXI	D,WAITMSG
	CALL	PMSG
WAIT1:	MVI	C,0BH			;CHECK KEY PRESSED
	CALL	BDOS
	CPI	0
	JZ	WAIT1			;WAIT 'TILL KEY PRESSED
	MVI	C,01
	CALL	BDOS			;GET CHARACTER

; 			EXECUTE ONCE 
; ROUTINE HANDLES THE INITIALIZATION AND PREP OF THE DJDMA


INIT0:  CALL DMADDR		;SETUP THE DMA ADDRESS
	CALL HALT		;LAY DOWN A HALT COMMAND
	MVI  A,0		;CLEAR BYTE FOR STATUS
	CALL DOIT0		;ISSUE COMMAND AND CHECK
	CALL RTRACK		;LAY DOWN THE READ TRACK COMMAND
	CALL HALT		;LAYDOWN THE HALT COMMAND




;  THIS IS THE MAIN PROGRAM LOOP WHERE ALL THE WORK GETS DONE

START:	MVI	A,0		;INITIALIZE THE FIRST TRACK
	STA	FIRST
	LDA 	SIZE
	STA	LAST		;INITIALIZE LAST TRACK

RLOOP:	CALL	READ

	LDA	FIRST		;UPDATE FIRST TRACK COUNTER
	INR	A
	STA	FIRST

	LDA	LAST		;UPDATE LAST TRACK COUNTER
	DCR	A
	STA	LAST
	JNZ	RLOOP

	LDA	PASS		;CHECK FOR ALL PASSES COMPLETED
	DCR	A
	STA	PASS
	JNZ	START
	JMP	SEEKOK


; ROUTINE COMMANDS DJ TO READ TWO TRACKS TO MEMORY
; ONE TRACK IS DETERMINED BY MEMORY LOCATION "LAST"
; OTHER TRACK IS DETERMINED BY MEMORY LOCATION "FIRST"
ŠREAD	LDA     FIRST		;PICK UP TRACK
	STA     TRACK		;SEND TO CHANNEL
	MVI     A,HEAD0
	STA	HEAD
	CALL    DOIT		;ISSUE DJ A COMMAND
	CALL    CHSTAT		;CHECK FOR FINISH OF HALT
	CALL	TSTAT		;CHECK FOR ALL SECTORS OK

; SAME TRACK BUT HEAD 1

	MVI     A,HEAD1
	STA	HEAD
	CALL	DOIT
	CALL    CHSTAT		;CHECK FOR FINISH OF HALT
	CALL	TSTAT		;CHECK FOR ALL SECTORS OK

; READ TRACK DETERMINED BY "LAST"

	LDA     LAST		;PICK UP TRACK
	STA     TRACK		;SEND TO CHANNEL
	CALL 	DOIT		;ISSUE DJ A COMMAND
	CALL 	CHSTAT
	CALL	TSTAT

;  SAME TRACK BUT HEAD 0

	MVI	A,HEAD0
	STA	HEAD
	CALL 	DOIT		;ISSUE DJ A COMMAND
	CALL 	CHSTAT
	CALL	TSTAT		
	RET		

CHSTAT:	LHLD 	RSTAT
	MOV 	A,M
	CPI 	040H
	RZ
	POP	H
	JMP  	DJERR


; Routine makes sure that each sector status in the table
; was OK.  Terminates if the status was other than a 40 (OK)
; or '0' (end of sector table).

TSTAT:	LXI 	H,05000H
	MVI 	B,26		;MAXIMUM SECTORS	
TSTAT1:	MOV 	A,M
	CPI	040H		;OK STATUS
	JZ	TSTAT2
	CPI	0		;END OF TABLE
	JNZ	DJERR		;OTHER THAN 0 THAN ERROR ROUTINE
	RET			;GO BACK -- REACHED END OF TABLE
TSTAT2:	INX H
	DCR B
	JNZ TSTAT1
	RET			;DO IT FOR A MAX OF 26 SECTORS
				;IN CASE OF 8 INCH SINGLE DENSITY


; EXECUTE ONCE TO INITIALIZE - SET DMA BUFFER FOR TRACK READ

DMADDR:	LXI H,CHANNEL		;DJDMA SET ADDR COMMAND 
	MVI A,023H
	MOV M,A
	INX H
	MVI A,0
	MOV M,A
	INX H
	MVI A,20H
	MOV M,A
	INX H
	MVI A,0
	MOV M,A
	INX H
	RET


; EXECUTE ONCE TO INITALIZE
; SECTOR TABLE PLACED AT 5000H

RTRACK: LXI H,050H		;DJDMA READ TRACK COMMAND
	MVI A,029HŠ	MOV M,A			;READ TRACK COMMAND
	INX H
	MVI A,0			;TRACK
	MOV M,A
	INX H
	MVI A,0			;SIDE
	MOV M,A
	INX H
	MVI A,0			;DRIVE
	MOV M,A
	INX H
	MVI A,0
	MOV M,A			;TABLE LOW ADDR
	INX H
	MVI A,050H		;TABLE HIGH ADDR
	MOV M,A
	INX H
	MVI A,0			;TABLE EXTENDED ADDR
	MOV M,A
	INX H
	MOV M,A			;COMMAND STATUS BYTE
	SHLD RSTAT
	INX  H
	RET

HALT:	MVI A,25H		;DJDMA HALT COMMAND
	MOV M,A
	INX H
	MVI A,0
	MOV M,A
	SHLD HSTAT		;STORE THE STATUS ADDRESS
	RET


; EXECUTE ONCE BEFORE EACH TRACK READ

FILTABL: 
	LXI H,05000H
	MVI B,26		;MAXIMUM SECTORS	
	MVI A,0
FTABL1:	MOV M,A
	INX H
	DCR B
	JNZ FTABL1
	RET	

STAT1:	DCR D
	JZ  TIMEOUT
	JMP STAT0

DOIT:	CALL FILTABL
	MVI A,0
	LHLD RSTAT
	MOV  M,A
DOIT0:	LHLD HSTATŠ	MOV M,A			;ZERO OUT THE READ TRACK STATUS
	OUT 0EFH		;DJDMA ATTENTION
	LXI B,0			;TIMEOUT COUNTER
	MVI D,20H		;NUMBER OF TIMES THROUGH LOOP
STAT0:	DCX B
	MOV A,B
	ORA C
	JZ  STAT1
	MOV A,M
	CPI 00H			;CHECK FOR O.K		
	JZ  STAT0
	CPI 040H		;O.K. STATUS
	RZ 
	POP H
			
; DJ/DMA status must be in the 'A' register at this point

DJERR:	CPI	082H		;DRIVE NOT READY
	JNZ	ERR0
	LXI	D,NRMSG
	JMP	LEAVE

ERR0:	CPI	084H		;UNREADABLE MEDIA
	JNZ	ERR1
	LXI	D,UMMSG
	JMP	LEAVE

ERR1:	CPI	085H		;IMPROPER SECTOR HEADER
	JNZ	ERR2
	LXI	D,ISHMSG
	JMP	LEAVE

ERR2:	CPI	086H		;CRC ERROR IN HEADER
	JNZ	ERR3
	LXI	D,HCRC
	JMP	LEAVE

ERR3:	CPI	087H		;SEEK ERROR
	JNZ	ERR4
	LXI	D,SERR
	JMP	LEAVE

ERR4:	CPI	08EH		;CRC ERROR IN DATA
	JNZ	ERR5
	LXI	D,DCRC	

LEAVE:  CALL	PMSG

;	PUT CODE HERE FOR SECTOR ERROR IDENTIFICATION ROUTINE

	MVI	E,07H			;BEEP THE TERMINAL
	CALL	COUT
	CALL	CRLF
	JMP	WARM




ERR5:  JMP	TIMEOUT
		



; COME HERE WHEN COMPLETED SUCCESSFULLY

SEEKOK: LXI	D,GDMESS
	CALL	PMSG
	CALL	CRLF

WARM:   LXI	D,RETURN
	CALL	PMSG
	CALL	CRLF
WARM0:	MVI	C,0BH		;CHECK CONSOLE
	CALL	BDOS
	CPI	0		;CHARACTER TYPED??
	JNZ	WARM0
	MVI	C,01
	CALL	BDOS		;GET THE CHAR. 
	CPI	051H		;'Q' TO QUIT?
	JZ	CPM		;GO TO WARM BOOT ON 'Q'
	CPI	071H		;check "q" also
	JZ	CPM
	MVI	A,TSTCNT        ;NUMBER OF PASSES
	STA	PASS	
	LXI	SP,1000H
	JMP     INIT0		;NEXT DISKETTE IF SO

CRLF:	MVI	E,0AH		;PRINT A CR AND LF
	CALL	COUT
	MVI	E,0DH

COUT:	MVI	C,02		;PRINT CHAR IN A
	CALL	BDOS
	RET

; COME HERE IF CONTROLLER NOT RESPONDING

TIMEOUT:
	LXI	D,TOMSG	
	CALL	PMSG
	JMP	0

PMSG:	MVI	C,09H
	CALL	BDOS
	MVI	E,0AH
	CALL	COUT
	MVI	E,0DH
	CALL	COUTŠ	RET

BADPAR: LXI	D,PARAM
	CALL	PMSG
	JMP	CPM


CPM:	CALL	SWAPLOG
	JMP	0


SIGNON: DB	'Decision 1 Floppy disk verification program V1.1  $'

GDMESS: DB	' Floppy verification complete... No errors!! $'


RETURN: DB  ' Type any key to continue ( "Q" to quit and return to CP/M)... $'

PARAM:  DB  'Bad diskette type option, select either  (M)icronix or (C)pm. $'

WAITMSG:
	DB	'Place diskette to test in drive, then press any key... $'

TOMSG:	DB	' DJ/DMA not responding to commands !!  $'

NRMSG:	DB	' Drive not ready ! $'
ISHMSG:	DB	' Improper sector header ! $'
UMMSG:  DB	' Unreadable media ! $'
HCRC:   DB	' CRC error in sector header ! $'
DCRC:	DB	' CRC error in data field ! $'
SERR:	DB	' Seek Error ! $'
FIRST:  DB	0
LAST:	DB	0
SIZE:	DB	0
DSTORE: DB	0
PASS:	DB	5
STATUS: DW	0
HSTAT:  DW	0
RSTAT:  DW	0
LOG:	DB	0
BUFFER	EQU	$

	END
