	.IDENT	/01/

; THIS PROGRAM IS DESIGNED TO VERIFY THE QUALITY OF TAPES. IT WAS DESIGNED
; WITH THE TU77 IN MIND BUT CAN BE RATHER EASILY MODIFIED TO ADD OR DELETE
; BELLS AND WHISTLES.  THE PROGRAM IN ITS PRESENT FORM UTILIZES READ_REVERSE
; FUNCTIONALITY.  A REWIND WILL HAVE TO BE INSERTED AND THE FOOTAGE COUNTER
; RESET TO USE ON A TAPE DRIVE WITH NO READ_REVERSE CAPABILITY.
;
; THE PROGRAM EXPECTS A TAPE MOUNTED FOREIGN WITH THE LOGICAL NAME "SCRATCH"
;
; SEVERAL PHILOSOPHICAL DECISIONS MADE WERE:
;
;	FOR CONVENIENCE IN FIGURING APPROXIMATE TAPE POSITION, TAPE RECORDS
;	ARE COMPUTED TO COME OUT TO 1 FOOT EACH, INCLUDING RECORD GAP.
;	THIS MEANS ONLY 95.8% OF THE TAPE ACTUALLY GETS DATA WRITTEN ON IT.
;
;	THE DATA PATTERN USED IS A TWO BYTE "CHECKERBOARD". USERS MAY HAVE
;	THEIR OWN FAVORITE DATA PATTERNS. NOTE THAT A SINGLE BYTE PATTERN
;	WOULD DO AWAY WITH THE NEED FOR A COMPARE BUFFER, AS THE DATA COULD
;	BE READ INTO THE INITIAL BUFFER AND EFFICIENTLY CHECKED WITH A 
;	SKPC INSTRUCTION.
;
;	THE PROGRAM AS WRITTEN HERE ALLOWS RETRIES ON WRITES (WITHOUT EXTENDED
;	INTERRECORD GAPS) BUT NO RETRIES ON READS.  THIS IS A MATTER OF 
;	INDIVIDUAL PREFERENCE.  DISALLOWING RETRIES WILL RESULT IN MORE ERRORS
;	BEING REPORTED, POSSIBLY WHEN THERE IS NOTHING WRONG WITH THE TAPE.
;	ALLOWING RETRIES MAY ALLOW MARGINAL SPOTS ON THE TAPE TO GO UNREPORTED.
;
;	THE FACT THAT THE CURRENT VERSION READS BACKWARDS MEANS IT REPORTS
;	ERRORS INVERSELY WITH RESPECT TO POSITION. THIS IS HOW WE LIKE IT, BUT
;	OTHER USERS MAY WISH TO MODIFY THE LOGIC SOMEWHAT.
;
; MACRO DEFINITIONS
;
	$DSCDEF
	$IODEF
	$MTDEF
	$STSDEF
;
; LOCAL CONSTANTS
;
	DENSITY=1600				;USE HIGHEST DENSITY AVAILABLE
	BUFSIZ=<DENSITY/2>*23			;COMPUTE FOR 1 FOOT OF TAPE
						;(ASSUMING 1/2 INCH TAPE GAP)
;
; READ ONLY DATA
;
	.PSECT	RODATA,RD,NOWRT,NOEXE

						;SET MODE DESCRIPTOR BUFFER
SETMOD:	.WORD	0				;UNUSED
	.WORD	BUFSIZ				;BUFFERSIZE IN BYTES
	.LONG	MT$K_PE_1600@MT$V_DENSITY	;1600 BPI PE DEFAULT FORMAT

						;8 BIT BYTE IS WRITTEN TO TAPE
						;WITH BITS ARRANGED: 31765P402
BUFFER:	.REPT	BUFSIZ/2			;BUFFER FULL OF     (101011010)
	.WORD	^XA936				;TWO BYTE PATTERN   (010101101)
	.ENDR					;(WHEN IT REACHES TAPE)

TAPE:	.ASCID	/SCRATCH/			;TAPE LOGICAL NAME
TERM:	.ASCID	/TT/				;TERMINAL LOGICAL NAME

;
;	MESSAGES
;

NOTAPE:	.ASCID	/PLEASE MOUNT TAPE FOREIGN WITH LOGICAL NAME 'SCRATCH'/

LENGTH:	.ASCID	\THE TAPE IS ABOUT !SW FEET LONG!/\

TAPERR:	.ASCID	/A TAPE ERROR OCCURRED AT ABOUT !SW FEET/

SUMERR:	.ASCID	/!SW TOTAL TAPE ERROR!%S OCCURRED IN !SW FEET/

;
; READ/WRITE DATA
;
	.PSECT	RWDATA,RD,WRT,NOEXE

IOSB:	.BLKQ	1				;I/O STATUS BLOCK

TTCHAN:	.BLKW	1				;TERMINAL CHANNEL NUMBER
MTCHAN:	.BLKW	1				;TAPE CHANNEL NUMBER

FEET:	.BLKW	1				;FOOTAGE COUNTER

TOTAL:	.BLKW	1				;TOTAL LENGTH

ERROR:	.BLKW	1				;ERROR COUNTER

;
;	HISTORICAL NOTE:	THIS PROGRAM MAY CONTAIN A BUG WHICH CAUSES
;				MEMORY PRECEDING THE FOLLOWING COMPARE BUFFER
;				TO BE DESTROYED.
;
;				ALTERNATIVELY, IO$_READLBLK!IO$M_REVERSE MAY 
;				UNDER SOME CIRCUMSTANCES OVERRUN ITS BUFFER.
;
;				UNTIL I FIGURE OUT WHICH, THE FOLLOWING 
;				FIREWALL IS IN PLACE.  IT IS TESTED AND FOUND
;				TO BE SUFFICIENT. DARING PERSONS MAY REDUCE IT
;				OR REMOVE IT ALTOGETHER.  SORRY I DIDN'T GET 
;				AROUND TO DEBUGGING IT FURTHER.
;
	.BLKB	1000				;FIREWALL
COMPARE:.BLKB	BUFSIZ				;COMPARE BUFFER

MESSAGE:.WORD	80				;TERMINAL MESSAGE DESCRIPTOR
	.BYTE	DSC$K_DTYPE_T
	.BYTE	DSC$K_CLASS_D
	.LONG	TERMBUF
TERMBUF:.BLKB	80				;TERMINAL STRING BUFFER

;
; EXECUTABLE CODE BEGINS
;

	.PSECT	CODE,EXE,RD,NOWRT

TAPECHECK::

	.WORD	^M<R5,R4,R3,R2>

	$ASSIGN_S	DEVNAM=TERM,-		;GET TERMINAL CHANNEL
			CHAN=TTCHAN
	CMPW		#SS$_NORMAL,R0		;OK?
	BEQL		1$			;SKIP IF ALL IS WELL
	BRW		EXIT			;BRANCH IF NOT

1$:	$ASSIGN_S	DEVNAM=TAPE,-		;GET TAPE CHANNEL
			CHAN=MTCHAN
	CMPW		#SS$_NORMAL,R0		;TAPE CHANNEL OK?
	BEQL		SETUP			;BRANCH IF OK

	MOVL		NOTAPE+4,R0		;GET STRING ADDRESS
	$QIOW_S		EFN=#1,-		;SEND
			CHAN=TTCHAN,-		;USER
			FUNC=#IO$_WRITELBLK,-	;THE
			IOSB=IOSB,-		;"NO TAPE
			P1=(R0),-		;MOUNTED"
			P2=NOTAPE,-		;ERROR
			P4=#^A/0/		;MESSAGE
	BRW		EXIT			;AND QUIT

SETUP:	$QIOW_S		EFN=#1,-		;ISSUE REWIND QIO
			CHAN=MTCHAN,-
			FUNC=#IO$_REWIND,-
			IOSB=IOSB

	CMPW		#SS$_NORMAL,IOSB	;MAKE SURE ALL IS WELL
	BEQL		1$			;SKIP IF STATUS NORMAL
	BRW		IOSTAT			;ABORT IF NOT

1$:	$QIOW_S		EFN=#1,-		;ISSUE SETMODE QIO
			CHAN=MTCHAN,-
			FUNC=#IO$_SETMODE,-
			P1=SETMOD,-		;CHARACTERISTICS BUFFER
			IOSB=IOSB

	CMPW		#SS$_NORMAL,IOSB	;CHECK THAT ALL IS WELL
	BEQL		2$			;SKIP IF STATUS NORMAL
	BRW		IOSTAT			;ABORT IF NOT

2$:	CLRW		FEET			;CLEAR FOOTAGE

WRITER:	$QIOW_S		EFN=#1,-		;ISSUE WRITE LOGICAL
			CHAN=MTCHAN,-		;NOTE RETRIES ALLOWED
			FUNC=#IO$_WRITELBLK!IO$M_INHEXTGAP,-
			IOSB=IOSB,-		;I/O STATUS BLOCK
			P1=BUFFER,-
			P2=#BUFSIZ

	INCW		FEET			;INCREMENT FOOTAGE

	CMPW		IOSB,#SS$_NORMAL	;CHECK WRITE STATUS
	BEQL		WRITER			;KEEP WRITING UNLESS FAIL
	CMPW		IOSB,#SS$_ENDOFTAPE	;HIT END OF TAPE?
	BEQL		EOT			;SKIP IF WAS EOT
	CMPW		IOSB,#SS$_PARITY	;CHECK FOR PARITY ERROR
	BEQL		WRITER			;PICK UP PARITY ERRORS LATER
	BRW		IOSTAT			;ABORT ON ANY OTHER ERROR

EOT:	MOVW		FEET,TOTAL		;STORE TOTAL LENGTH

	MOVW		#80,MESSAGE		;$FAO ONLY SHORTENS LENGTH

	$FAO_S		CTRSTR=LENGTH,-		;COMPOSE
			OUTLEN=MESSAGE,-	;NICE
			OUTBUF=MESSAGE,-	;LENGTH
			P1=TOTAL		;MESSAGE

	$QIOW_S		EFN=#1,-		;SEND
			CHAN=TTCHAN,-		;USER
			FUNC=#IO$_WRITELBLK,-	;THE
			IOSB=IOSB,-		;"TAPE
			P1=TERMBUF,-		;LENGTH
			P2=MESSAGE,-		;IS"
			P4=#^X8D010000		;MESSAGE

	CLRW		ERROR			;CLEAR ERROR COUNT
	
READER:						;WILL READ IN REVERSE

	$QIOW_S		EFN=#1,-		;ISSUE READ LOGICAL
			CHAN=MTCHAN,-
			FUNC=#IO$_READLBLK!IO$M_REVERSE!IO$M_INHRETRY,-
			IOSB=IOSB,-		;I/O STATUS BLOCK
			P1=COMPARE,-
			P2=#BUFSIZ

	DECW		FEET			;DECREMENT FOOTAGE COUNT

	CMPW		IOSB,#SS$_NORMAL	;ANY ERROR?
	BEQL		1$			;SKIP IF NONE
	BITL		#MT$M_BOT,IOSB+4	;SEE IF AT BOT
	BNEQ		BOT			;IF SO WE ARE DONE
	BSBW		ANNOUNCE		;IF NOT ANNOUNCE ERROR
	BRB		READER			;AND CONTINUE READING

1$:	CMPC3		#BUFSIZ,BUFFER,COMPARE	;DO COMPARISON
	BEQL		READER			;CONTINUE IF SAME
	BSBB		ANNOUNCE		;ANNOUNCE ERROR IF NOT
	BRB		READER			;CONTINUE READING

BOT:	MOVW		#80,MESSAGE		;$FAO ONLY SHORTENS LENGTH

	$FAO_S		CTRSTR=SUMERR,-		;PRODUCE
			OUTLEN=MESSAGE,-	;NICE
			OUTBUF=MESSAGE,-	;ERROR
			P1=ERROR,-		;SUMMARY
			P2=TOTAL		;MESSAGE

	$QIOW_S		EFN=#1,-		;SEND
			CHAN=TTCHAN,-		;USER
			FUNC=#IO$_WRITELBLK,-	;THE
			IOSB=IOSB,-		;"TOTAL
			P1=TERMBUF,-		;ERROR
			P2=MESSAGE,-		;COUNT"
			P4=#^X8D020000		;MESSAGE


	BRB		EXIT			;ALL DONE

IOSTAT:	MOVW		IOSB,R0			;LAZY MAN'S DIAGNOSTIC
EXIT:	$EXIT_S		R0

	.PAGE

ANNOUNCE:

	INCW		ERROR			;BUMP ERROR COUNT

	MOVW		#80,MESSAGE		;$FAO ONLY SHORTENS LENGTH

	$FAO_S		CTRSTR=TAPERR,-		;CREATE
			OUTLEN=MESSAGE,-	;NICE
			OUTBUF=MESSAGE,-	;ERROR
			P1=FEET			;MESSAGE

	$QIOW_S		EFN=#1,-		;SEND
			FUNC=#IO$_WRITELBLK,-	;THE
			CHAN=TTCHAN,-		;NICE
			IOSB=IOSB,-		;"TAPE
			P1=TERMBUF,-		;ERROR
			P2=MESSAGE,-		;AT"
			P4=#^X8D010000		;MESSAGE

	RSB					;RETURN

	.END		TAPECHECK
