	.TITLE	TAPESUBS TAPE READ/WRITE MACRO SUBROUTINES.
;
;		SUBROUTINES TO PERFORM READ, WRITE, REWIND,
;		AND SKIP TAPE FUNCTIONS ON UNLABELED TAPES.
;
;		V01.A	T.W.DANFORTH	30-OCT-81
;		V01.A	T.W.D.	1-APR-82	INITIAL RELEASE
;		V02.A	T.W.D.	7-APR-82	CHECK IN SETUPFT TO BE SURE
;			TAPE IS MOUNTED FORIEGN, REMOVE ALL REFERENCE TO THE
;			COMPLETION CODE #8 (OPERATION INCOMPLETE), CHECK FOR
;			BEGINNING-OF-TAPE ON A NEGATIVE SKIP IN SKIPREC.
;		V02.B	T.W.D.	27-APR-82	Decrement counter for negative
;			"SKIPFILE" to compensate for skipping extra file mark.
;			Also, "SS$_NORMAL" instead of the internal status = 2
;			on "SKIPFILE" with NUMB = 0 (skip zero files).  Change
;			tape-not-foreign to $CLI_DEVNOTFOR.
;		V02.C	T.W.D.	2-MAY-82	Set normal status return in
;			SETUPFT to one (1) also make SKIPFILE_VAX stop at the
;			EOV mark and tell how many files skipped.
;		V02.D	T.W.D.	4-MAY-82	Ckeck for zero skip in
;			SKIPFILE_VAX and return if found.  Return proper EOV
;			code if end-of-vol. found on SKIPFILE_VAX if forward
;			direction.  Fix bug in check for foreign tape.
;
	$DEVDEF
	$DIBDEF
	$MTDEF
	$DCDEF
	$IODEF
	$STSDEF
	$SSDEF
;			**  CHANGE  **    V02.B
	$CLIMSGDEF
;
	.PAGE
	.SBTTL	SET UP FORIEGN TAPES ROUTINE.
;
;		CALLING SEQUENCE FOR SETUPFT:
;
;		CALL SETUPFT (LUN,CDEV[0],ISTAT)
;			OR
;		PUSHAL	ISTAT
;		PUSHAL	CDEV 
;		PUSHAL	LUN
;		CALLS	#3,SETUPFT
;
;		ARGUMENTS FOR SETUPFT:
;		LUN	THE ADDRESS OF A LONG WORD WHICH CONTAINS THE LOGICAL
;			UNIT NUMBER FOR THE TAPE DEVICE.  MAX. NUMBER = 99.
;		   OPTIONAL PARAMETER 
;		CDEV	ADDRESS OF A CHARACTER STRING DESCRIPTOR WHICH CONTAINS
;			THE TAPE DEVICE NAME OR LOGICAL NAME WHICH POINTS TO
;			THE TAPE DEVICE.
;			IF THE FIRST CHARACTER OF THE DEVICE NAME IS A SPACE
;			(' ') THE SETUPFT ROUTINE ASSUMES THE USER WISHES TO
;			USE THE DEFAULT FORTRAN LOGICAL NAME FOR THE LOGICAL
;			UNIT NUMBER BEING USED, i.e. FOR0xx.  THIS MAY BE CODED
;			IN FORTRAN AS (LUN,' ',ISTAT).
;			THIS MAY ALSO BE THE ADDRESS OF A ZERO (USE INTEGER OR
;			CODE INTO THE CALL).  IF PASSED A ZERO, THE SETUPFT 
;			ROUTINE ASSUMES, AS ABOVE, THAT THE USER WISHES TO 
;			USE THE TAPE DEVICE ASSIGNED TO THE DEFAULT FORTRAN 
;			LOGICAL NAME.
;		ISTAT	ADDRESS OF A LONG WORD WHICH WILL RECEIVE THE STATUS
;			OF THE LUN-TAPE ASSIGNMENT.
;
	.ENTRY	SETUPFT,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10>
;
	MOVL	@8(AP),R9 		; GET THE DEVICE NAME LENGTH.
	ADDL3	8(AP),#4,R3		; SET UP POINTER TO DEVICE STRING.
	MOVL	(R3),R10
;
	TSTL	@8(AP)			; TEST FOR DEVICE NAME.
	BEQL	FAO_CALL			; IF NOT PRESENT, BRANCH.
	JMP	LENG_NAME
;
FAO_CALL:			; FAO CALL TO BUILD THE FORTRAN LOGICAL
				; NAME FOR0xx USING THE LOGICAL NAME PASSED
				; BY THE USER.
	MOVL	#8,OUT_LOG_NAM			; SET THE MAX. LEN.
	MOVAL	OUT_LOG_NAM+8,OUT_LOG_NAM+4	; SET UP THE LOG NAME CHAR DESC
	$FAO_S	CTRSTR=FAO_LST,OUTLEN=OUT_LOG_NAM,OUTBUF=OUT_LOG_NAM,-
		P1=@4(AP)
	BLBC	R0,10$				; CHECK FOR OK FAO OPERATION
	JMP	LOG_TRAN			; FAO DONE OK - BRANCH.
10$:	MOVL	R0,@12(AP)			; BAD ASCII OUTPUT, SET STATUS
	RET
;
LENG_NAME:			; CALCULATE THE LENGTH OF THE USER'S SUPPLIED
				; LOGICAL NAME AND BUILD A TEMP. CHARACTER
				; DESCRIPTOR BEFORE THE TRANSLATION.
				; ALSO CHECK TO SEE IF THE FIRST CHAR. IS 
				; BLANK AND IF TRUE, GO TO FAO_CALL TO BUILD
				; THE CORRECT LOGICAL NAME.
	MOVL	#1,R3				; SET R3 AS AN INDEX.
	LOCC	#^X20,R9,(R10) 		; LOCATE THE FIRST SPACE CHAR.
;
	TSTL	R0				; TEST THE LOCATE TO SEE IF IT
						; GOT TO THE END OF THE STRING
	BEQL	10$				; BEFORE FINDING <SP>.  BRANCH.
;
	CMPL	R1,@8(AP)[R3]			; CHECK THE START ADDRESS OF
						; THE STRING WITH R1 (THE CHAR.
	BNEQ	5$				; FOUND ADDRESS) AND CONTINUE
						; IF NOT EQUAL.
	JMP	FAO_CALL			; FIRST CHAR. IS BLANK.
;
5$:	SUBL3	R0,@8(AP),OUT_LOG_NAM		; CALCULATE THE LENGTH OF THE
	BRW	20$				; STRING WHEN <SP> FOUND.
;
10$:	MOVL	@8(AP),OUT_LOG_NAM		; MOVE ORIGINAL LENGTH - WHOLE
						; STRING IS LOGICAL NAME.
20$:	MOVL	@8(AP)[R3],OUT_LOG_NAM+4	; PUT THE ADDRESS IN THE DESCR.
						; TO MAKE A COMPLETE DESCRIPTOR
;
LOG_TRAN:		; TRANSLATE THE LOGICAL NAME UNTIL WE GET EITHER
			; AN ERROR OR THE PHYSICAL DEVICE NAME.
	PUSHAL	LOG_TRAN_EQUIV			; TRANSLATE THE CDEV TO GET
	PUSHAL	OUT_LOG_NAM			; THE PHYSICAL DEVICE NAME
	CALLS	#2,TRNALL			; FOR THE TAPE.
;
	BLBS	R0,10$				; CHECK FOR CORRECT TRANSLATION
	MOVL	R0,@12(AP)			; SET STATUS FOR ERROR AND
	RET					; RETURN
;
;				FIND THE ACTUAL LENGTH OF THE LOGICAL NAME.
10$:	LOCC	#^X20,LOG_TRAN_EQUIV,LOG_TRAN_EQUIV+8	; LOCATE 1ST SPACE.
	TSTL	R0			; CHECK FOR = 0 (END OF STRING FOUND)
	BEQL	13$
;
	SUBL3	R0,LOG_TRAN_EQUIV,TMP_LOG	; CALCULATE THE ACTUAL LENGTH.
	JMP	15$
;
13$:	MOVL	LOG_TRAN_EQUIV,TMP_LOG		; USE ORIGINAL LENGTH.
;
;				CHECK FOR A LUN > 99 OR < 0
15$:	CMPL	@4(AP),#99			; CHECK TO FOR LUN TOO BIG.
	BGTR	16$
	TSTL	@4(AP)			; CHECK FOR LUN <= 0.
	BGTR	20$
16$:	MOVL	#SS$_IVLOGNAM,@12(AP)		; BAD LUN - SET STATUS AND
	RET					; RETURN
;
20$:	CLRL	R3				; SET UP INDEX AND GET ADDR. OF
	MOVAL	LUN_NUMBS,R4			; LUN LIST.
;
LOOP_ITAPE:
	CMPW	@4(AP),(R4)[R3]		; CHECK TO SEE IF THE LUN HAS
	BNEQ	INV_LOG_1			; BEEN USED ALREADY.
;
INV_LOG_NAME:				; SET INVALID-LOGICAL-NAME AND RETURN
	MOVL	#SS$_IVLOGNAM,@12(AP)		; LUN ALREADY USED - PUT STATUS
	RET					; AND RETURN.
;
INV_LOG_1:
	TSTW	(R4)[R3]			; TEST FOR ZERO - END OF LIST
	BEQL	45$
;
				; INCREMENT AND TEST FOR END OF THE LUN LIST.
	AOBLSS	LENG_LUNS,R3,LOOP_ITAPE		; BRANCH IF STILL IN LOOP.
;
	JMP	INV_LOG_NAME			; TOO MANY LUNS USED.
;
;
45$:	MOVAL	CHAN_NUMBS,R6			; SET UP THE LOCATION FOR THE
	MULL3	#2,R3,R8			; I/O CHANNEL AND CALL THE
	ADDL3	R6,R8,ITAPE_ASSCHN+ASSIGN$_CHAN	
	$ASSIGN_G	ITAPE_ASSCHN		; GET CHANNEL ROUTINE.
;
	BLBS	R0,CHECK_DEV			; TEST FOR GOOD ASSIGN.
	MOVL	R0,@12(AP)			; PUT IN THE RETURN STATUS AND
	RET					; RETURN
;
CHECK_DEV:				; MOVE THE DESIRED LUN TO
	MOVW	@4(AP),(R4)[R3]		; THE LUN LIST.
			; CHECK THE PHYSICAL DEVICE TO SEE IF IT REALLY
			; IS A TAPE DEVICE.
	MOVL	ITAPE_ASSCHN+ASSIGN$_CHAN,R6
	$GETCHN_S	CHAN=(R6),PRILEN=CHAR_LEN,PRIBUF=GET_DEV_BUF
;
	BLBS	R0,10$			; CHECK FOR OK GET CHANNEL OPERATION.
	MOVL	R0,@12(AP)		; BAD GETCHN - SET STATUS
	RET
;
;
10$:	CMPB	GET_DEV_CHAR+DIB$B_DEVCLASS,#DC$_TAPE	; CHECK FOR TAPE DEVICE
	BEQL	30$
	MOVL	#SS$_IVDEVNAM,@12(AP)		; SET INVALID DEVICE STATUS
	CLRW 	(R4)[R3]		; IF INVALID, CLEAR THE LUN ENTRY.
;
;					; CHECK FOR TAPE MOUNTED FORIEGN
30$:	BBS	#DEV$V_FOR,GET_DEV_CHAR+DIB$L_DEVCHAR,40$;
;			**  CHANGE  **    V02.B
	MOVL	#CLI$_DEVNOTFOR,@12(AP)	; SET DEVICE NOT FORIEGN.
	CLRW	(R4)[R3]
;			**  CHANGE   **    V02.D
	RET
;
;			**  CHANGE  **    V02.C
40$:	MOVL	#SS$_NORMAL,@12(AP)
	RET
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
	.PAGE
;
;		SETUPFT DATA SECTION.
;
GET_DEV_BUF::	.LONG	DIB$K_LENGTH	; BUFFER FOR GET CHANNEL INFO.
		.LONG	GET_DEV_BUF+8
GET_DEV_CHAR::	.BLKB	DIB$K_LENGTH
CHAR_LEN::	.LONG	0		; LENGTH OF THE GET CHAN BUFFER.
;
FAO_LST:	.LONG	7		; FAO ARGUMENT.
		.LONG	FAO_LST+8
		.ASCII	/FOR!3ZB/
;
OUT_LOG_NAM:	.LONG	0		; OUTPUT DESCRIPTOR FOR FAO CALL.
		.LONG	0
		.BLKB	128
;
LUN_NUMBS:	.WORD	0[10]		; 10 LUNS.
CHAN_NUMBS:	.WORD	0[10]
;
LENG_LUNS:	.LONG	<.-CHAN_NUMBS>/2	; THE NUMBER OF LUNS
;
LOG_TRAN_EQUIV:	.LONG	128
		.LONG	LOG_TRAN_EQUIV+8
		.BLKB	128
TMP_LOG:	.LONG	0
		.LONG	LOG_TRAN_EQUIV+8
	.PAGE
;
;		DEFINE THE READ AND WRITE DATA.
;
ITAPE_ASSCHN::	$ASSIGN	DEVNAM=TMP_LOG,CHAN=0
;
SKIP_TAPE::	$QIOW	CHAN=0,FUNC=0,IOSB=TAPE_IOSTB,P1=0
;
REWIND_TAPE::	$QIOW	CHAN=0,FUNC=0,IOSB=TAPE_IOSTB
;
READTAPE::	$QIOW	CHAN=0,FUNC=IO$_READLBLK,IOSB=TAPE_IOSTB,P1=0,P2=0
;
WRITAPE::	$QIOW	CHAN=0,FUNC=IO$_WRITELBLK,IOSB=TAPE_IOSTB,P1=0,P2=0
;
TAPE_IOSTB::	.QUAD	0		; I/O STATUS BLOCK.
;
;******************************************************************************
	.PAGE
	.SBTTL	READ TAPES VIA QIOW.
;
;		CALLING SEQUENCE FOR THE READ TAPE ROUTINES.
;			READ INTEGER (BYTE) DATA.
;		CALL RITAPE (LUN,IBUFF,NBYTE,IBYTE,ISTAT[,MODIF])
;			OR
;		[PUSHAL	MODIF]
;		PUSHAL	ISTAT
;		PUSHAL	IBYTE
;		PUSHAL	NBYTE
;		PUSHAL	IBUFF
;		PUSHAL	LUN
;		CALLS	#5[6],RITAPE
;			READ CHARACTER STRING DATA.
;		CALL RCTAPE (LUN,CBUFF,NBYTE,IBYTE,ISTAT[,MODIF])
;			OR
;		[PUSHAL	MODIF]
;		PUSHAL	ISTAT
;		PUSHAL	IBYTE
;		PUSHAL	NBYTE
;		PUSHAL	CBUFF
;		PUSHAL	LUN
;		CALLS	#5[6],RCTAPE
;
;		ARGUMENTS FOR READ TAPE:
;		LUN	THE ADDRESS OF A LONG WORD WHICH CONTAINS THE LOGICAL
;			UNIT NUMBER FOR THE QIOW CALL.
;		IBUFF	THE ADDRESS OF THE INPUT BUFFER FOR INTEGER (BYTE) DATA
;		CBUFF	THE ADDRESS OF THE CHARACTER DESCRIPTOR TO RECEIVE
;			THE INPUT DATA.
;		NBYTE	THE ADDRESS OF A LONG WORD CONTAINING THE # BYTES
;			TO BE READ FROM THE TAPE.
;		IBYTE	THE ADDRESS OF A LONG WORD CONTAINING THE # BYTES
;			ACTUALLY READ FROM THE TAPE.
;		ISTAT	THE ADDRESS OF A LONG WORD WHICH WILL CONTAIN THE 
;			STATUS RETURNED FROM THE OPERATION.
;		   OPTIONAL PARAMETER - -
;		MODIF	THE ADDRESS OF A LONG WORD WITH ANY READ_LOGICAL
;			MODIFIERS TO BE USED.  A VALUE OF ZERO INDICATES
;			NO MODIFIERS.
;
	.ENTRY	RITAPE,^M<R2,R3,R4,R5,R6,R7,R8>
;
	MOVL	8(AP),READTAPE+QIOW$_P1	; PUT THE ADDRESS FOR THE
						; READ INTO THE QIO
	JMP	RTAPE_ENT2
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
	.ENTRY RCTAPE,^M<R2,R3,R4,R5,R6,R7,R8>
;
	MOVL	#1,R2			; SET UP INDEX AND
	MOVL	@8(AP)[R2],READTAPE+QIOW$_P1	; PUT IN THE ADDRESS FOR READ
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
RTAPE_ENT2:
	PUSHAL	READTAPE+QIOW$_CHAN	; GET THE LUN # AND CALL THE ROUTINE
	PUSHL	4(AP)			; TO GET THE
	CALLS	#2,GET_TAPE_CHAN	; CHANNEL NUMBER.
;
	BLBS	R0,10$			; CHECK FOR GOOD LUN/CHANNEL MATCH.
	MOVL	R0,@20(AP)		; PUT AN INVALID CHANNEL INTO THE
	CLRL	@16(AP)		; STATUS AND CLEAR THE NO. BYTES
	RET				; READ AND RETURN.
;
10$:	CMPL	#6,(AP)			; TEST FOR THE PRESENCE OF MODIFIERS.
	BNEQ	15$			; SKIP IF NOT PRESENT.
	BISL2	@24(AP),READTAPE+QIOW$_FUNC	; PUT THE MODIFIERS IN
;
15$:	MOVL	@12(AP),READTAPE+QIOW$_P2	; PUT THE # BYTES IN
;
	$QIOW_G	READTAPE		; READ TAPE !!!
;
	MOVL 	#IO$_READLBLK,READTAPE+QIOW$_FUNC	; CLEAR MODIFIERS.
	BLBS	R0,20$			; CHECK FOR NORMAL QIO FUNCTION CALL
	MOVL	R0,@20(AP)		; IF NOT OK, PUT IN STATUS AND RETURN.
	CLRL	@16(AP)		; CLEAR THE NO. BYTES READ.
	RET
;
20$:	BLBS	TAPE_IOSTB,30$		; CHECK FOR NORMAL AND IF NOT,
	PUSHAL	TAPE_IOSTB		; PUSH THE IOSTB AND
	CALLS	#1,TAPE_ERROR		; CALL THE INTERNAL TAPE ERR. ROUTINE.
;
30$:	MOVZWL	TAPE_IOSTB,@20(AP)	; PUT THE I/O STATUS INTO THE STATUS
	MOVZWL	TAPE_IOSTB+2,@16(AP)	; WORD AND THE # BYTES INTO THE BYTES.
	RET				; NORMAL END
;******************************************************************************
;
	.PAGE
	.SBTTL	WRITE TAPES VIA QIOW.
;
;
;		CALLING SEQUENCE FOR THE WRITE TAPE ROUTINE.
;			WRITE INTEGER (BYTE) TAPE
;		CALL WITAPE (LUN,IBUFF,NBYTE,IBYTE,ISTAT[,MODIF])
;			OR
;		[PUSHAL	MODIF]
;		PUSHAL	ISTAT
;		PUSHAL	IBYTE
;		PUSHAL	NBYTE
;		PUSHAL	IBUFF
;		PUSHAL	LUN
;		CALLS	#5[6],WITAPE
;			WRITE CHARACTER STRING DATA.
;		CALL WCTAPE (LUN,CBUFF,NBYTE,IBYTE,ISTAT[,MODIF])
;			OR
;		[PUSHAL	MODIF]
;		PUSHAL	ISTAT
;		PUSHAL	IBYTE
;		PUSHAL	NBYTE
;		PUSHAL	CBUFF
;		PUSHAL	LUN
;		CALLS	#5[6],WCTAPE
;
;		ARGUMENTS FOR WRITE TAPE:
;		LUN	THE ADDRESS OF A LONG WORD WHICH CONTAINS THE LOGICAL
;			UNIT NUMBER FOR THE QIOW CALL.
;		IBUFF	THE ADDRESS OF THE OUTPUT BUFF FOR INTEGER (BYTE) DATA
;		CBUFF	THE ADDRESS OF THE CHARACTER DESCRIPTOR FOR WRITING 
;			THE OUTPUT DATA.
;		NBYTE	THE ADDRESS OF A LONG WORD CONTAINING THE # BYTES
;			TO BE WRITTEN TO THE TAPE.
;		IBYTE	THE ADDRESS OF A LONG WORD CONTAINING THE # BYTES
;			ACTUALLY WRITTEN TO THE TAPE.
;		ISTAT	THE ADDRESS OF A LONG WORD WHICH WILL CONTAIN THE 
;			STATUS RETURNED FROM THE OPERATION.
;		   OPTIONAL PARAMETER - -
;		MODIF	THE ADDRESS OF A LONG WORD WITH ANY WRITE_LOGICAL
;			MODIFIERS TO BE USED.
;
	.ENTRY	WITAPE,^M<R2,R3,R4,R5,R6,R7,R8>
;
	MOVL	8(AP),WRITAPE+QIOW$_P1	; PUT THE ADDRESS FOR THE 
						; WRITE INTO THE QIO
	JMP	WTAPE_ENT2
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
	.ENTRY	WCTAPE,^M<R2,R3,R4,R5,R6,R7,R8>
;
	MOVL	#1,R2			; SET UP INDEX AND
	MOVL	@8(AP)[R2],WRITAPE+QIOW$_P1	; PUT IN THE WRITE ADDRESS.
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
WTAPE_ENT2:
	PUSHAL	WRITAPE+QIOW$_CHAN	; GET THE LUN # AND CALL THE ROUTINE
	PUSHL	4(AP)		; TO GET THE CHANNEL
	CALLS	#2,GET_TAPE_CHAN	; NUMBER.
;
	BLBS	R0,10$			; CHECK FOR GOOD LUN/CHANNEL MATCH.
	MOVL	R0,@20(AP)		; PUT AN INVALID CHANNEL INTO THE
	CLRL	@16(AP)		; STATUS AND CLEAR THE NO. BYTES
	RET				; WRITTEN AND RETURN.
;
10$:	CMPL 	#6,(AP)			; CHECK FOR THE PRESENCE OF MODIFIERS
	BNEQ	15$			; SKIP IF NOT FOUND.
	BISL2	@24(AP),WRITAPE+QIOW$_FUNC	; PUT THE MODIFIERS IN
;
15$:	MOVL	@12(AP),WRITAPE+QIOW$_P2	; PUT THE # BYTES IN THE QIO
;
	$QIOW_G	WRITAPE			; WRITE TAPE !!!
;
	MOVL	#IO$_WRITELBLK,WRITAPE+QIOW$_FUNC	; CLEAR MODIFIERS.
	BLBS	R0,20$			; CHECK FOR NORMAL QIO FUNCTION CALL
	MOVL	R0,@20(AP)		; IF NOT OK, PUT IN THE STATUS AND
	CLRL	@16(AP)		; CLEAR THE # BYTES WRITTEN AND
	RET				; RETURN
;
20$:	BLBS	TAPE_IOSTB,30$		; CHECK FOR NORMAL COMPLETION AND -
	PUSHAL	TAPE_IOSTB		; IF NOT PUSH THE IOSTB AND
	CALLS	#1,TAPE_ERROR		; CALL THE INTERNAL ERROR ROUTINE.
;
30$:	MOVZWL	TAPE_IOSTB,@20(AP)	; PUT THE I/O STATUS INTO THE STATUS
	MOVZWL	TAPE_IOSTB+2,@16(AP)	; WORD AND THE # BYTES INTO THE BYTES.
	RET				; NORMAL END
;******************************************************************************
;
	.PAGE
	.SBTTL	CHECK THE TAPE QIO ERRORS.
;
;		ROUTINE TO CHECK TAPE ERRORS AND RETURN A USEABLE CODE TO
;		THE USER.  USED INTERNALLY BY THE TAPE SUBS.
;
;		CALLING SEQUENCE IS:
;
;		CALL	TAPE_ERROR (ISTATUS)
;			OR
;		PUSHAL	ISTATUS
;		CALLS	#1,TAPE_ERROR
;
;		ARGUMENT IS:
;		ISTATUS	THE ADDRESS OF A * WORD * WHICH CONTAINS THE I/O 
;			STATUS RETURNED FROM A TAPE I/O SUBROUTINE.
;			THE TRANSLATED STATUS IS RETURNED IN ISTATUS.
;
;			TRANSLATED VALUES ARE:
;			SS$_NORMAL	= 1
;			SS$_ENDOFFILE	= 2
;			SS$_ENDOFTAPE	= 3
;			SS$_ENDOFVOLUME	= 4
;			SS$_DATACHECK	= 5
;			SS$_PARITY	= 6
;			SS$_DATAOVERUN	= 7
;		REMOVE THE SS$_OPINCOMPL AND THE CODE #8 SINCE THIS WILL MOST
;		LIKELY BE A FATAL ERROR WITH A PROBLEM ON THE TAPE.
;			SS$_OPINCOMPL	= 8
;			BOT_FOUND	= 9	(WHOI ERROR CODE)
;			POSITION_UNKNOWN = 10	(WHOI ERROR CODE)
;
	.ENTRY	TAPE_ERROR,^M<R2,R3,R4,R5,R6,R7,R8>
;
	MOVL	ERR_CODE_LEN,R4		; SET UP THE END OF THE LOOP.
;
	MOVZWL	@4(AP),R5		; GET THE INPUT ERROR CODE.
	CLRL	R2			; SET UP THE INDEX.
	MOVAL	ERR_CODE,R3		; GET THE START OF THE CHECK STRING.
;
TAPE_ER_LOOP:
	CMPW	(R3)[R2],R5		; COMPARE THE ERROR CODE LIST WITH THE
 					; INPUT VALUE.
	BEQL	10$			; IF EQUAL, THEN BRANCH.
;
	AOBLSS	R4,R2,TAPE_ER_LOOP	; INCREMENT THE COUNTER AND CHECK FOR
					; THE END OF THE LIST.
;
			; LOOP COMPLETED - ERROR NOT TRANSLATED - RETURN
			; THE CODE TO THE CALLING ROUTINE AND THEN TO USER.
	RET
;
			; ERROR FOUND - MOVE THE TRANSLATION TO THE USER'S
			; AREA AND RETURN.
10$:	MOVAL	TAPE_CODES,R3		; THE I/O CODE HAS BEEN FOUND.
	MOVW	(R3)[R2],@4(AP)	; MOVE CODE TO THE OUTPUT CODE.
	RET
;
	.PAGE
	.SBTTL	DATA FOR THE ERROR CHECKING ROUTINE.
;
ERR_CODE:	.WORD	SS$_ENDOFFILE
		.WORD	SS$_ENDOFTAPE
		.WORD	SS$_ENDOFVOLUME
		.WORD	SS$_DATACHECK
		.WORD	SS$_PARITY
		.WORD	SS$_DATAOVERUN
;		.WORD	SS$_OPINCOMPL
ERR_CODE_LEN:	.LONG	<.-ERR_CODE>/2
;
TAPE_CODES:	.WORD	2
		.WORD	3
		.WORD	4
		.WORD	5
		.WORD	6
		.WORD	7
;		.WORD	8
;******************************************************************************
;
	.PAGE
	.SBTTL	REWIND TAPE
;
;		ROUTINES TO EITHER REWIND THE TAPE OR REWIND AND TAKE OFFLINE.
;
;		THE OFFLINE ROUTINE IS NOT THE SAME AS A DISMOUNT OF THE TAPE,
;		IT IS TO UNLOAD THE TAPE ONLY.  MOSTLY USEFUL IN MULTITAPE
;		OPERATIONS WHERE A VOLUME SET IS TO REMAIN LOGICALY MOUNTED BUT
;		THE INDIVIDUAL TAPES NEED TO BE UNLOADED TO PROCEDE TO THE
;		NEXT TAPE IN THE SET.
;
;		CALLING SEQUENCE IS:
;				REWIND - NO UNLOAD.
;		CALL REWTAPE (LUN,ISTAT[,NOWAIT])
;			OR
;		[PUSHAL	NOWAIT]
;		PUSHAL	ISTAT
;		PUSHAL	LUN
;		CALLS	#2[3],REWTAPE
;
;				REWIND AND UNLOAD THE TAPE
;		CALL UNLOAD (LUN,ISTAT[,NOWAIT])
;			OR
;		[PUSHAL	NOWAIT]
;		PUSHAL	ISTAT
;		PUSHAL	LUN
;		CALLS	#2[3],UNLOAD
;
;		ARGUMENTS ARE:
;
;		LUN 	THE ADDRESS OF A LONG WORD WHICH CONTAINS THE LOGICAL
;			UNIT NUMBER OF THE TAPE DRIVE.
;		ISTAT	ADDRESS OF A LONG WORD WHICH WILL CONTAIN THE STATUS
;			RETURNED FROM THE OPERATION.
;			**  NOTE  ** - ISTAT WILL BE RETURNED AS SOON AS THE
;			REWIND IS QUEUED FOR THE UNLOAD ENTRY.  IT IS ASSUMED
;			THAT THE REWIND AND UNLOAD WILL COMPLETE BUT IT IS
;			UP TO THE USER TO VERIFY THE COMPLETION.
;		   OPTIONAL PARAMETER - -
;		NOWAIT	THE ADDRESS OF A LONG WORD WHICH INDICATES WHETHER
;			THE OPERATION IS TO BE DONE WITH WAIT OR NOT.  IF = 0,
;			THE OPERATION IS COMPLETED BEFORE CONTROL IS RETURNED
;			TO THE PROGRAM.  IF <> 0, THE OPERATION IS QUEUED AND
;			CONTROL IS IMMEDIATLY RETURNED TO THE PROGRAM.
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
	.ENTRY	REWTAPE,^M<R2,R3,R4,R5,R6,R7,R8>
;
15$:	MOVL	#IO$_REWIND,REWIND_TAPE+QIOW$_FUNC	; SET REWIND.
	JMP	REW_ENT2
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
	.ENTRY	UNLOAD,^M<R2,R3,R4,R5,R6,R7,R8>
;
	MOVL	#IO$_REWINDOFF,REWIND_TAPE+QIOW$_FUNC	; SET REWIND OFF LINE.
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
REW_ENT2:
	PUSHAL	REWIND_TAPE+QIOW$_CHAN		; SET UP THE CALL TO GET THE
	PUSHL	4(AP)				; TAPE I/O CHANNEL
	CALLS	#2,GET_TAPE_CHAN
;
	BLBS	R0,20$				; CHECK THE STATUS.
	MOVL	R0,@8(AP)			; BAD LUN - SET STATUS AND
	RET					; RETURN
;
20$:	CMPL	#3,(AP)				; CHECK FOR A NOWAIT PARAM.
	BGTR	40$				; SKIP IF NOT PRESENT.
;
	TSTL	@12(AP)			; TEST FOR NO-WAIT.
	BEQL	40$
	BISL2	#IO$M_NOWAIT,REWIND_TAPE+QIOW$_FUNC	; SET FOR NOWAIT.
;
40$:	$QIOW_G	REWIND_TAPE			; DO THE REWIND.
;
	BLBS	R0,50$			; TEST FOR OK REWIND.
	MOVL	R0,@8(AP)		; NOT GOOD - PUT STATUS IN ISTAT AND
	RET				; RETURN
;
50$:	BLBS	TAPE_IOSTB,60$		; CHECK FOR NORMAL AND
	PUSHAL	TAPE_IOSTB		; IF NOT, PUSH THE IOSTB
	CALLS	#1,TAPE_ERROR		; AND CALL THE INTERNAL ERROR ROUTINE.
;
60$:	MOVZWL	TAPE_IOSTB,@8(AP)	; SET THE RETURN STATUS
	RET
;******************************************************************************
;
	.PAGE
	.SBTTL	SKIP TAPE RECORDS 
;
;		ROUTINE TO SKIP TAPE RECORDS.
;
;		CALL SKIPREC (LUN,NUMB,NSKIP,ISTAT)
;			OR
;		PUSHAL	ISTAT
;		PUSHAL	NSKIP
;		PUSHAL	NUMB
;		PUSHAL	LUN
;		CALLS	#4,SKIPREC
;
;		ARGUMENTS ARE:
;
;		LUN	THE ADDRESS OF A LONG WORD CONTAINING THE LOGICAL
;			UNIT NUMBER TO  BE USED FOR THE I/O.
;		NUMB	THE ADDRESS OF A LONG WORD CONTAINING THE NUMBER OF
;			UNITS, RECORDS OR TAPE MARKS, TO BE SKIPPED.
;		NSKIP	THE ADDRESS OF A LONG WORD IN WHICH THE NUMBER OF UNITS
;			ACTUALLY SKIPPED WILL BE RETURNED.
;		ISTAT	THE ADDRESS OF A LONG WORD IN WHICH THE I/O STATUS
;			WILL BE RETURNED.
;
	.ENTRY	SKIPREC,^M<R2,R3,R4,R5,R6,R7,R8,R9>
;
	MOVL	#IO$_SKIPRECORD,SKIP_TAPE+QIOW$_FUNC	; SKIP REC
;
	PUSHAL	SKIP_TAPE+QIOW$_CHAN	; SET UP AND CALL
	PUSHL	4(AP)				; THE GET CHANNEL ROUTINE.
	CALLS	#1,GET_TAPE_CHAN
;
	BLBS	R0,10$			; CHECK FOR GOOD LUN/CHANNEL MATCH.
	MOVL	R0,@16(AP)		; LUN INVALID - PUT IN ERROR CODE AND
	CLRL	@12(AP)			; CLEAR THE NO. BYTES TRANSFFERED.
	RET
;
10$:	MOVL	@8(AP),SKIP_TAPE+QIOW$_P1	; PUT IN THE NUMBER OF UNITS.
;
20$:	$QIOW_G	SKIP_TAPE		; SKIP TAPE!!
;
	BLBS	R0,40$			; CHECK FOR DIRECTIVE ERROR AND
	MOVL	R0,@16(AP)		; MOVE THE ERROR INTO THE USER'S SPACE.
	CLRL	@12(AP)			; CLEAR THE NO. UNITS SKIPPED.
	RET
;
40$:	BLBS	TAPE_IOSTB,50$		; CHECK FOR NORMAL I/O.
	PUSHAL	TAPE_IOSTB		; IF NOT, PUSH THE IOSTB AND
	CALLS	#1,TAPE_ERROR		; CALL THE INTERNAL ERROR ROUTINE.
;
50$:	MOVL	SKIP_TAPE+QIOW$_CHAN,R9		; SET UP FOR CHECKING BOT.
	$GETCHN_S	CHAN=R9,PRILEN=CHAR_LEN,PRIBUF=GET_DEV_BUF
					;
	BLBS	R0,55$			; CHECK FOR GOOD GET INFORMATION.
	MOVL	R0,@16(AP)		; BAD GET - PUT ERROR IN STATUS AND
	RET				; RETURN
					; CHECK FOR "BOT" BIT AND
55$:	BBC	#MT$V_BOT,GET_DEV_CHAR+DIB$L_DEVDEPEND,60$	; IF SET -
	MOVL	#9,@16(AP)		; PUT IN "BOT" CODE IN STATUS AND
	JMP	65$ 			; GO TO PUT IN THE NUMBER SKIPPED.
;
60$:	MOVZWL	TAPE_IOSTB,@16(AP)	; PUT THE I/O STATUS INTO THE USER'S
65$:	MOVZWL	TAPE_IOSTB+2,@12(AP)	; SPACE AND THEN THE NUMBER OF RECORDS
	RET				; INTO THE NUMB. COUNT AND RETURN.
;******************************************************************************
;
	.PAGE
	.SBTTL	SKIP FILES AND FIND DOUBLE EOF MARK (EOV).
;
;		CALLING SEQUENCE IS:	SKIP FILES -- SIGMA EMULATION!!!
;
;		CALL SKIPFILE (LUN,NUMB,NSKIP,ISTAT)
;			OR
;		PUSHAL	ISTAT
;		PUSHAL	NSKIP
;		PUSHAL	NUMB
;		PUSHAL	LUN
;		CALLS	#4,SKIPFILE
;
;				FIND DOUBLE EOF (EOV).
;		CALL DBLEOF (LUN,NSKIP,ISTAT)
;			OR
;		PUSHAL	ISTAT
;		PUSHAL	NSKIP
;		PUSHAL	LUN
;		CALLS	#3,DBLEOF
;
;				SKIP FILE -- VAX NORMAL!!!
;		CALL SKIPFILE_VAX (LUN,NUMB,NSKIP,ISTAT)
;			OR
;		PUSHAL	ISTAT
;		PUSHAL	NSKIP
;		PUSHAL	NUMB
;		PUSHAL	LUN
;		CALLS	#4,SKIPFILE_VAX
;
;		ARGUMENTS ARE:
;
;		LUN	THE ADDRESS OF A LONG WORD CONTAINING THE LOGICAL
;			UNIT NUMBER TO  BE USED FOR THE I/O.
;		NUMB	THE ADDRESS OF A LONG WORD CONTAINING THE NUMBER OF
;			UNITS, RECORDS OR TAPE MARKS, TO BE SKIPPED.
;			FOR THE DBLEOF ENTRY, NUMB IS INTERNALLY SET SO A
;			MAXIMUM OF 32767 FILES WILL BE SKIPPED WHILE SEARCHING
;			FOR THE DOUBLE END-OF-FILE.  TAPES WITH MORE THAN
;			32767 FILES BEFORE AN END-OF-VOLUME, WILL NOT BE
;			PROCESSED CORRECTLY.
;		NSKIP	THE ADDRESS OF A LONG WORD IN WHICH THE NUMBER OF UNITS
;			ACTUALLY SKIPPED WILL BE RETURNED.
;		ISTAT	THE ADDRESS OF A LONG WORD IN WHICH THE I/O STATUS
;			WILL BE RETURNED.
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
	.ENTRY	SKIPFILE,^M<R2,R3,R4,R5,R6,R7,R8,R9>
;
	MOVL	@8(AP),R6		; GET THE NUMBER TO BE SKIPPED.
	MOVL	12(AP),R7		; GET THE ADDR OF THE NUMBER SKIPPED.
	CLRL	(R7)			; CLEAR THE COUNTER.
	MOVL	16(AP),R8		; GET THE STATUS ADDR.
	MOVL	#^X100,SKIP_TYPE	; SET UP AN ENTRY INDICATOR.
	TSTL	R6		; CHECK FOR ZERO SKIP AND BRANCH IF TRUE.
	BNEQ	10$
	JMP	ZERO_SKIP
10$:	JMP	DBLEOF_ENT2
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
	.ENTRY	DBLEOF,^M<R2,R3,R4,R5,R6,R7,R8,R9>
;
	MOVL	#32767,R6		; SET UP NUMBER TO BE SKIPPED.
	MOVL	8(AP),R7		; GET THE ADDR. OF THE NUMBER SKIPPED.
	CLRL	(R7)			; CLEAR THE COUNTER
	MOVL	12(AP),R8		; GET THE STATUS ADDR.
	MOVL	#^X1000,SKIP_TYPE	; SET UP AN ENTRY INDICATOR.
	JMP	DBLEOF_ENT2
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
	.ENTRY	SKIPFILE_VAX,^M<R2,R3,R4,R5,R6,R7,R8,R9>
;
	MOVL	@8(AP),R6		; SET UP NUMBER TO BE SKIPPED.
	MOVL	12(AP),R7		; GET THE ADDR. OF THE NUMBER SKIPPED.
	CLRL	(R7)			; CLEAR THE COUNTER
	MOVL	16(AP),R8		; GET THE STATUS ADDR.
	MOVL	#^X10,SKIP_TYPE		; SET UP AN ENTRY INDICATOR.
;			**  CHANGE  **    V02.D
	TSTL	R6			; CHECK TO SEE IF ZERO FILES ARE TO
	BNEQ	DBLEOF_ENT2		; AND IF NOT, BRANCH.
	MOVL	#SS$_NORMAL,(R8)	; SET NORMAL STATUS FOR END AND
	RET				; RETURN.
;
; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;
DBLEOF_ENT2:
	MOVL	#IO$_SKIPFILE,SKIP_TAPE+QIOW$_FUNC	; SKIP FILE FUNCTION
;
	PUSHAL	SKIP_TAPE+QIOW$_CHAN		; SET UP AND CALL LUN
	PUSHL	4(AP)				; TRANSLATION
	CALLS	#1,GET_TAPE_CHAN		; ROUTINE.
;
	BLBS	R0,10$			; CHECK FOR GOOD LUN/CHANNEL MATCH.
	MOVL	R0,(R8)			; LUN INVALID - SET STATUS AND
	CLRL	(R7)			; CLEAR THE NUMBER OF FILES SKIPPED AND
	RET				; RETURN.
;
10$:	BBS	#31,R6,15$		; TEST FOR NEGATIVE SKIP AND BRANCH
	MOVZWL	#1,SKIP_TAPE+QIOW$_P1	; SET QIO FOR POSITIVE TAPE SKIP.
	JMP 	SKIP_LOOP_1
;
15$:	MOVZWL	#-1,SKIP_TAPE+QIOW$_P1	; SET QIO FOR NEGATIVE TAPE SKIP.
	MNEGL	R6,R6			; GET THE NEGATIVE OF THE SKIP COUNT.
;
	BBS	#4,SKIP_TYPE,SKIP_LOOP_1	;IF VAX SKIP - START SKIP.
				; IF SIGMA TYPE SKIP THEN  --
	INCL	R6			; SKIP N+1 FILES AND THEN WE WILL READ
					; 1 RECORD TO GET TO THE BEGINNING OF
					; THE DESIRED FILE.
;
;
SKIP_LOOP_1:
	CLRL	R5			; SET UP A COUNTER.
;
SKIP_LOOP:
	$QIOW_G	SKIP_TAPE		; SKIP A FILE.
;
	BLBS	R0,30$			; CHECK FOR DIRECTIVE ERROR.
	MOVL	R0,(R8)			; BAD - SET STATUS AND 
	RET				; RETURN TO USER.
;
30$:	TSTW	TAPE_IOSTB+2		; TEST TO SEE IF A FILE WAS SKIPPED.
	BNEQ	35$			; IF NOT ZERO, GO INCREMENT COUNT
	JSB	ZERO_CK			; IF ZERO, GO CHECK THE CONDITIONS.
	JMP	40$
;
35$:	INCL	(R7)			; INCREMENT THE TOTAL OF FILES SKIPPED.
;
			; IF END-OF-VOLUME FOUND, THEN WE SHOULD EXIT WITH THE
			; STATUS SET FOR EOV
40$:	CMPW	TAPE_IOSTB,#SS$_ENDOFVOLUME	; CHECK FOR END-OF-VOLUME
	BNEQ	SKIP_CK_STAT
	JMP	EOV_HANDLE		; GO HANDLE THE EOV CONDITION.
;
SKIP_CK_STAT:
	CMPW	TAPE_IOSTB,#SS$_ENDOFTAPE	; CHECK FOR END-OF-TAPE.
	BNEQ	10$
;
	MOVL	#3,(R8)			; SET THE END-OF-TAPE FLAG AND
	RET				; RETURN.
;
10$:	CMPW	TAPE_IOSTB,#SS$_NORMAL	; CHECK FOR NORMAL STATUS AND
	BEQL	15$			; BRANCH IF OK.
;
	MOVZWL	TAPE_IOSTB,(R8)		; MOVE THE ERROR STATUS AND
	RET				; RETURN TO USER.
;
15$:	BBS	#27,SKIP_TYPE,20$	; IF FLAG SET FOR ZERO FILES SKIPPED,
					; NEGATIVE SKIP, AND NORMAL SKIP TYPE.
					; THEN EXIT LOOP.
	AOBLSS	R6,R5,SKIP_LOOP		; INCREMENT THE COUNT AND GO BACK
					; FOR MORE IF NOT ALL SKIPPED.
;
			; DONE WITH THE SKIP - WE NEED TO CHECK TO SEE IF
			; WE ARE DOING A SIGMA OR VAX SKIP AND THEN READ
			; A RECORD IF SIGMA SKIP IN THE NEGATIVE DIRECTION.
20$:	BBS	#31,@8(AP),30$	; CHECK FOR NEGATIVE SKIP AND
					; BRANCH IF NECESSARY.
			; POSITIVE SKIP - ALL DONE.
25$:	MOVL	#SS$_NORMAL,(R8)	; SET NORMAL STATUS.
	RET
			; NEGATIVE SKIP - CHECK FOR VAX.
30$:	BBS	#4,SKIP_TYPE,25$	; IF BIT SET THEN VAX SKIP - FINISHED.
;
	MOVL	SKIP_TAPE+QIOW$_CHAN,R9		; SET UP FOR CHECKING BOT.
	$GETCHN_S	CHAN=R9,PRILEN=CHAR_LEN,PRIBUF=GET_DEV_BUF
					;
	BLBS	R0,35$			; CHECK FOR GOOD GET INFORMATION.
	MOVL	R0,(R8)			; BAD GET - PUT ERROR IN STATUS AND
	RET				; RETURN
					; CHECK FOR "BOT" BIT AND
35$:	BBC	#MT$V_BOT,GET_DEV_CHAR+DIB$L_DEVDEPEND,40$	; IF SET -
	MOVL	#9,(R8)			; PUT IN "BOT" CODE IN STATUS AND
	RET				; RETURN.
;
			; NOT "BOT" --
			; CHECK THE DEVICE TYPE TO SEE IF IT IS A TU78 AND
			; IF SO EXIT.
40$:	CMPB	GET_DEV_CHAR+DIB$B_DEVTYPE,#DT$_TU78	; IS IT A TU78?
	BNEQ	45$			; NO! GO TO READ A RECORD.
	BBC	#27,SKIP_TYPE,45$	; YES! CHECK THE ZERO SKIP FLAG AND
	MOVL	#10,(R8)		; PUT POSITION LOST MESSAGE IN
	RET				; ISTAT AND RETURN.
			;
			; READ RECORD TO POSITION FOR SIGMA SKIP.
45$:	MOVL	#64,SKIP_BYTE		; SET READ COUNT.
	PUSHAL	SKIP_STAT
	PUSHAL	SKIP_BYTE
	PUSHAL	SKIP_BYTE
	PUSHAL	SKIP_BUFF
	PUSHL	4(AP)
	CALLS	#5,RITAPE		; READ ONE RECORD (THE EOF MARK).
;
	CMPL	SKIP_STAT,#2		; CHECK FOR NORMAL EOF (FROM READ).
	BEQL	50$
;
	MOVL	SKIP_STAT,(R8)		; BAD READ - SET THE STATUS
	RET				; RETURN TO USER.
50$:	MOVL	#SS$_NORMAL,(R8)	; GOOD READ OF EOF, SET STATUS
	;			** CHANGE **   V02.B
	DECL	(R7)			; SUBTRACT THE EXTRA FILE SKIPPED.
	RET
;
;
			; HANDLE THE END-OF-VOLUME (DOUBLE EOF MARK)
EOV_HANDLE:
	BBS	#12,SKIP_TYPE,30$	; CHECK FOR "FIND DOUBLE EOF" AND
					; BRANCH IF TRUE.
;			**  CHANGE  **    V02.C
	BBC	#4,SKIP_TYPE,5$		; CHECK FOR "SKIPFILE_VAX" AND
;			**  CHANGE  **    V02.D
	MOVL	#4,(R8)			; BRANCH IF TRUE.  IF TRUE, SET EOV
	RET				; STATUS AND RETURN.
;
			; WE JUST WANT TO SKIP FILES - READ A RECORD TO GET
			; AROUND THE EXTRA EOF, INCREMENT THE SKIP FILE COUNT,
			; AND CONTINUE SKIPPING FILES.
5$:	MOVL	#64,SKIP_BYTE		; SET THE NUMBER OF BYTES TO READ.
	PUSHAL	SKIP_STAT
	PUSHAL	SKIP_BYTE
	PUSHAL	SKIP_BYTE
	PUSHAL	SKIP_BUFF
	PUSHL	4(AP)
	CALLS	#5,RITAPE		; READ ONE RECORD (THE EOF MARK).
;
	CMPL 	SKIP_STAT,#2 		; CHECK FOR NORMAL EOF.
					; (ENCODED BY THE READ ROUTINE).
	BEQL	10$
;
	MOVL	SKIP_STAT,(R8)		; BAD READ - SET STATUS.
	RET
;
			; GOOD READ - ONE FILE SKIPPED.
10$:	INCL	(R7)			; INCREMENT THE SKIP COUNTER.
	MOVW	#SS$_NORMAL,TAPE_IOSTB	; SET NORMAL STATUS.
	JMP	SKIP_CK_STAT		; RETURN TO THE SKIP LOOP.
;
			; DOUBLE EOF WANTED - NORMAL END
30$:	MOVL	#SS$_NORMAL,(R8)	; SET NORMAL STATUS
	RET				; RETURN TO USER.
;
;			SKIP ZERO FILES - POSITION TO THE END OF THE
;			CURRENT FILE.
ZERO_SKIP:	
	MOVL	#32767,SKIP_BYTE	; SKIP MANY RECORDS.
	PUSHAL	SKIP_STAT
	PUSHAL	SKIP_BYTE
	PUSHAL	SKIP_BYTE
	PUSHL	4(AP)	
	CALLS	#4,SKIPREC		; SKIP TO END OF FILE.
;
	;			** CHANGE **  V02.B
	CMPL	SKIP_STAT,#2		; CHECK FOR THE NORMAL EOF RETURN.
	BEQL	10$			; OK - BRANCH.
;
	MOVL	SKIP_STAT,(R8)		; NOT EOF - SET UP THE STATUS.
	RET
10$:	MOVL	#SS$_NORMAL,(R8)	; SET NORMAL STATUS.
	RET
;
;
			; CHECK FOR ZERO SKIP AND NEGATIVE SKIP DIRECTION
			; AND A NORMAL SKIP TYPE.  IF THIS IS ALL TRUE,
			; SET A FLAG AND RETURN.
ZERO_CK:
	BBS	#31,@8(AP),10$		; CHECK FOR NEGATIVE.
	RSB				; NOT NEGATIVE SKIP.
;
10$:	BBS	#8,SKIP_TYPE,20$	; CHECK FOR SIGMA EMULATION SKIP.
	RSB				; VAX SKIP.
;
20$:	BISL2	#^X08000000,SKIP_TYPE	; SET FLAG INDICATING THE TYPE OF SKIP.
	RSB
;
;
		; DATA FOR SKIP FILES
;
SKIP_STAT:	.LONG	0
SKIP_BYTE:	.LONG	0
SKIP_BUFF:	.BLKB	64
SKIP_TYPE:	.LONG	0
;
;
;******************************************************************************
;
	.PAGE
	.SBTTL	WRITE EOF (TAPE MARK) AND EXTENDED IRG ON TAPE
;
;		ROUTINE WRITES TWO EOF'S ON THE TAPE AND THEN BACKSPACES
;		ONE EOF.  EOF'S ARE WRITTEN WITH EXTENDED INTER-RECORD-GAP.
;
;		CALLING SEQUENCE IS:
;
;		CALL TAPE_EOF (LUN,ISTAT)
;			OR
;		PUSHAL	ISTAT
;		PUSHAL	LUN
;		CALLS	#2,TAPE_EOF
;
;		ARGUMENT IS:
;
;		ISTAT	THE ADDRESS OF A LONG WORD TO RECEIVE THE STATUS OF
;			THE QIO OPERATION.
;		LUN	THE ADDRESS OF A LONG WORD CONTAINING THE LUN NUMBER
;			ON WHICH THE I/O IS TO BE PERFORMED.
;
	.ENTRY	TAPE_EOF,^M<R2,R3,R4,R5,R6,R7,R8>
;
	PUSHAL	REW_CHANL		; PREPARE TO
	PUSHL	4(AP)			; CALL THE ROUTINE TO GET THE
	CALLS	#1,GET_TAPE_CHAN	; CHANNEL NUMBER.
;
	BLBS	R0,10$			; CHECK FOR GOOD LUN/CHANNEL MATCH.
	MOVL	R0,@8(AP)		; LUN INVALID - PUT IN ERROR CODE.
	RET
;
10$:	MOVL 	#2,R4			; SET UP COUNTER
;
15$:	$QIOW_S	CHAN=REW_CHANL,FUNC=#IO$_WRITEOF,IOSB=TAPE_IOSTB
;
	BLBS	R0,20$			; CHECK FOR DIRECTIVE ERROR.
	MOVL	R0,@8(AP)		; IF NOT OK, PUT CODE INTO STATUS AND
	RET				; RETURN.
;
20$:	BLBS	TAPE_IOSTB,30$		; CHECK FOR OK REWIND.
	PUSHAL	TAPE_IOSTB
	CALLS	#1,TAPE_ERROR
	MOVZWL	TAPE_IOSTB,@8(AP)	; IF NOT OK, PUT CODE INTO STATUS AND
	RET				; RETURN
;
30$:	SOBGTR	R4,15$			; SUBTRACT AND GO BACK FOR THE
					; SECOND EOF.
;
	MOVL	#-1,NSKIP_FILE		; INITIALIZE THE NUMBER TO SKIP.
	PUSHL	8(AP)			; PUT THE USER'S IOSTATUS ON THE STACK
	PUSHAL	NSKIPS_EOF		; PUT THE ADDR OF A # SKIPPED ON STACK
	PUSHAL	NSKIP_FILE		; PUT THE ADDR OF # TO SKIP
	PUSHL	4(AP)			; PUT THE USER'S LUN ON STACK.
	CALLS	#4,SKIPFILE_VAX
;
	RET				; RETURN AFTER THE SKIP.
;
REW_CHANL:	.WORD	0
NSKIP_FILE:	.LONG	0
NSKIPS_EOF:	.LONG	0
;******************************************************************************
;
	.PAGE
	.SBTTL	GET AN I/O CHANNEL FOR THE USER'S LOGICAL UNIT NUMBER.
;
;		ROUTINE TO GET THE I/O CHANEL CORRESPONDING TO A USER'S
;		TAPE LOGICAL UNIT NUMBER.
;
;		CALLING SEQUENCE IS:
;
;		CALL GET_TAPE_CHAN (LUN,ICHANL)
;			OR
;		PUSHAL	ICHANL
;		PUSHAL	LUN
;		CALLS	#2,GET_TAPE_CHAN
;
;		ARGUMENTS ARE:
;		LUN	ADDRESS OF LONG WORD WHICH CONTAINS THE LOGICAL
;			UNIT NUMBER TO BE USED WITH THE TAPE OPERATION.
;		ICHANL	THE ADDRESS OF A WORD WHICH WILL CONTAIN THE
;			CHANNEL NUMBER ASSOCIATED WITH THE DEVICE.
;			THIS PARAMETER IS USUALLY PLACED DIRECTLY IN THE
;			QIO CALL LIST.
;
	.ENTRY	GET_TAPE_CHAN,^M<R2,R3,R4,R5,R6,R7,R8>
;
	CLRL	R2			; SET UP SEARCH INDEX.
	MOVAL	LUN_NUMBS,R3
	MOVAL	CHAN_NUMBS,R4
;
LOOP_GET_CH:				; START LOOP TO GET THE CHANNEL
	CMPW	@4(AP),(R3)[R2]	; BY COMPARING THE LUN WITH THE
	BEQL	20$			; LIST OF LUN'S IN THE CODE.
;
			; INCREMENT THE INDEX AND CHECK FOR THE END-OF-LOOP.
	AOBLSS	LENG_LUNS,R2,LOOP_GET_CH
;
	MOVL	#SS$_IVLOGNAM,R0	; LUN NOT FOUND - SET STATUS AND
	RET				; RETURN.
;
20$:	MOVW	(R4)[R2],@8(AP)	; MOVE THE CHANNEL # TO THE QIO.
	MOVL	#SS$_NORMAL,R0		; SET STATUS
	RET				; RETURN
;******************************************************************************
;
	.END
