	.TITLE	TMDRIVER - TM03-TE16/TU77 MAGTAPE DRIVER
	.IDENT	/01/
 
;
; COPYRIGHT (C) 1977
; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
; THIS SOFTWARE IS FURNISHED UNDER  A LICENSE FOR USE ONLY  ON  A
; SINGLE COMPUTER SYSTEM AND MAY BE  COPIED ONLY WITH  THE INCLU-
; SION OF  THE  ABOVE  COPYRIGHT NOTICE.  THIS SOFTWARE,  OR  ANY
; OTHER COPIES THEREOF, MAY NOT BE  PROVIDED  OR  OTHERWISE  MADE
; AVAILABLE TO ANY OTHER PERSON EXCEPT  FOR  USE  ON  SUCH SYSTEM
; AND TO  ONE WHO AGREES  TO  THESE LICENSE  TERMS.  TITLE TO AND
; OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES REMAIN IN DEC.
;
; THE INFORMATION IN THIS SOFTWARE  IS  SUBJECT TO CHANGE WITHOUT
; NOTICE AND SHOULD NOT BE CONSTRUED  AS  A COMMITMENT BY DIGITAL
; EQUIPMENT CORPORATION.
;
; DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
; SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC.
;
; D. N. CUTLER 20-JUN-77
;
; TM03-TE16/TU77 MAGTAPE DRIVER
;
; MACRO LIBRARY CALLS
;
 
	$CRBDEF				;DEFINE CRB OFFSETS
	$DDBDEF				;DEFINE DDB OFFSETS
	$DDTDEF				;DEFINE DDT OFFSETS
	$EMBDEF				;DEFINE EMB OFFSETS
	$IDBDEF				;DEFINE IDB OFFSETS
	$IODEF				;DEFINE I/O FUNCTION CODES
	$IRPDEF				;DEFINE IRP OFFSETS
	$MBADEF				;DEFINE MBA REGISTER OFFSETS
	$MTDEF				;DEFINE MAGTAPE STATUS BITS
	$PRDEF				;DEFINE PROCESSOR REGISTERS
	$UCBDEF				;DEFINE UCB OFFSETS
;	$VCBDEF				;DEFINE VCB OFFSETS
	$VECDEF				;DEFINE INTERRUPT DISPATCH VECTOR OFFSETS
	$WCBDEF				;DEFINE WCB OFFSETS
 
;
; LOCAL MACROS
;
; CHECK FOR FATAL OR RETRIABLE ERROR
;
 
	.MACRO	CHECK_ERROR
		BSBW	CHECK_ERROR
	.ENDM	CHECK_ERROR
 
;
; EXECUTE FUNCTION AND BRANCH ON RETRIABLE ERROR CONDITION
;
 
	.MACRO	EXFUNC BDST,FCODE
		.IF NB	FCODE
		MOVZBL	#CD'FCODE,R0
		.ENDC
		BSBW	FEX
		.WORD	BDST-.-2
	.ENDM	EXFUNC
 
;
; GENERATE FUNCTION TABLE ENTRY AND CASE TABLE INDEX SYMBOL
;
 
	.MACRO	GENF FCODE
		CD'FCODE=.-FTAB
		.BYTE	FCODE!MT_CS1_M_GO
	.ENDM	GENF
 
;
; GENERATE ERROR MASK TABLE ENTRY
;
 
	.MACRO	MASK LIST
$.$=0
	.IRP	X,<LIST>
$.$=$.$!MT_ER_M_'X
	.ENDM
	.WORD	$.$
	.ENDM	MASK
 
;
; TEST IF ANY RETRIES REMAINING
;
 
	.MACRO	TESTR BDST
		BSBW	TESTR
		.WORD	BDST-.-2
	.ENDM	TESTR
 
;
; LOCAL SYMBOLS
;
; TE16/TU77 MASSBUS REGISTER OFFSETS
;
 
	$DEFINI	MT
 
$DEF	MT_CS1		.BLKL	1	;DRIVE CONTROL REGISTER
	_VIELD	MT_CS1,0,<-		; DRIVE CONTROL REGISTER BIT DEFINITIONS
		<GO,,M>,-		; GO BIT
		<FCODE,5>-		; FUNCTION CODE
	>				;
$DEF	MT_DS		.BLKL	1	;DRIVE STATUS REGISTER
	_VIELD	MT_DS,0,<-		; DRIVE STATUS REGISTER BIT DEFINITIONS
		<SLA,,M>,-		; SLAVE ATTENTION
		<BOT,,M>,-		; BEGINNING OF TAPE
		<TM,,M>,-		; TAPE MARK
		<IDB,,M>,-		; IDENTIFICATION BURST
		<SDWN,,M>,-		; SLOWING DOWN
		<PES,,M>,-		; PHASE ENCODED
		<SSC,,M>,-		; SLAVE STATUS CHANGE
		<DRY,,M>,-		; DRIVE READY
		<DPR,,M>,-		; DRIVE PRESENT
		<,1>,-			; RESERVED BIT
		<EOT,,M>,-		; END OF TAPE
		<WRL,,M>,-		; DRIVE WRITE LOCKED
		<MOL,,M>,-		; MEDIUM ONLINE
		<PIP,,M>,-		; POSITIONING IN PROGRESS
		<ERR,,M>,-		; COMPOSITE ERROR
		<ATA,,M>-		; ATTENTION ACTIVE
	>				;
$DEF	MT_ER		.BLKL	1	;ERROR REGISTER
	_VIELD	MT_ER,0,<-		; ERROR REGISTER BIT DEFINITIONS
		<ILF,,M>,-		; ILLEGAL FUNCTION
		<ILR,,M>,-		; ILLEGAL REGISTER
		<RMR,,M>,-		; REGISTER MODIFY REFUSED
		<CPAR,,M>,-		; CONTROL BUS PARITY ERROR
		<FMT,,M>,-		; FORMAT ERROR
		<DPAR,,M>,-		; DATA BUS PARITY ERROR
		<INC,0,M>,-		; INCORRECTABLE ERROR (PE)
		<VPE,,M>,-		; VERTICLE PARITY ERROR (NRZI)
		<PEF,0,M>,-		; FORMAT ERROR (PE)
		<LRC,,M>,-		; LONGITUDINAL PARITY ERROR (NRZI)
		<NSG,,M>,-		; NONSTANDARD GAP
		<FCE,,M>,-		; FRAME COUNT ERROR
		<CS,0,M>,-		; CORRECTABLE SKEW (PE)
		<ITM,,M>,-		; ILLEGAL TAPE MARK
		<NEF,,M>,-		; NONEXECUTABLE FUNCTION
		<DTE,,M>,-		; DRIVE TIMING ERROR
		<OPI,,M>,-		; OPERATION INCOMPLETE
		<UNS,,M>,-		; DRIVE UNSAFE
		<COR,0,M>,-		; CORRECTABLE DATA ERROR (PE)
		<CRC,,M>,-		; CRC ERROR (NRZI)
	>				;
$DEF	MT_MR		.BLKL	1	;MAINTENANCE REGISTER
$DEF	MT_AS		.BLKL	1	;ATTENTION SUMMARY REGISTER
$DEF	MT_FC		.BLKL	1	;FRAME COUNT REGISTER
$DEF	MT_DT		.BLKL	1	;DRIVE TYPE REGISTER
	_VIELD	MT_DT,0,<-		; DRIVE TYPE REGISTER FIELD DEFINITIONS
		<DTN,9>,-		; DRIVE TYPE NUMBER
		<,1>,-			; RESERVED BIT
		<SPR,,M>,-		; SLAVE PRESENT
		<DRQ,,M>,-		; DRIVE REQUEST REQUIRED (ALWAYS 0)
		<7CH,,M>,-		; 7-CHANNEL TAPE (ALWAYS 0)
		<MOH,,M>,-		; MOVING HEAD (ALWAYS 0)
		<TAP,,M>,-		; TAPE DRIVE (ALWAYS 1)
	>				;
$DEF	MT_CC		.BLKL	1	;CHECK CHARACTER REGISTER
$DEF	MT_SN		.BLKL	1	;SERIAL NUMBER REGISTER
$DEF	MT_TC		.BLKL	1	;MAGTAPE CONTROL REGISTER
	_VIELD	MT_TC,0,<-		; TAPE CONTROL REGISTER FIELD DEFFINITIONS
		<SSEL,3>,-		; SLAVE SELECT
		<EPAR,1,M>,-		; EVEN PARITY
		<FSEL,4,M>,-		; FORMAT SELECT
		<DEN,3,M>,-		; DENSITY
		<,1>,-			; RESERVED BIT
		<EABO,,M>,-		; ENABLE ABORT ON TRANSFER ERROR
		<TCW,,M>,-		; TAPE CONTROL WRITE
		<FCS,,M>,-		; FRAME COUNT STATUS
		<ACCL,,M>,-		; ACCELERATOR
	>				;
 
	$DEFEND	MT
 
;
; DEFINE DEVICE DEPENDENT UNIT CONTROL BLOCK OFFSETS
;
 
	$DEFINI	UCB,GLOBAL
 
.=UCB$L_DPC+4				;
 
$DEF	UCB$L_MT_SR	.BLKL	1	;SAVED MBA STATUS REGISTER
$DEF	UCB$W_MT_DS	.BLKW	1	;SAVED DRIVE STATUS REGISTER
$DEF	UCB$W_MT_ER	.BLKW	1	;SAVED DRIVE ERROR REGISTER
$DEF	UCB$W_MT_FC	.BLKW	1	;SAVED DRIVE FRAME COUNT REGISTER
$DEF	UCB$W_MT_SPACNT	.BLKW	1	;CURRENT SPACING COUNT
$DEF	UCB$W_MT_CS1	.BLKW	1	;SAVED DRIVE CONTROL REGISTER
$DEF	UCB$W_MT_FUNC	.BLKW	1	;CURRENT FUNCTION CODE
$DEF	UCB$L_MT_RECORD	.BLKL	1	;CURRENT TAPE POSITION
$DEF	UCB$W_MT_FORCNT	.BLKW	1	;FORWARD SPACE COUNT DURING RETRY
$DEF	UCB$W_MT_TC	.BLKW	1	;TAPE CONTROL REGISTER CONTENTS
 
	$DEFEND	UCB
 
;
; MAXIMUM SPACING ON READ AND WRITECHECK ERRORS
;
 
ERR_SPACING=5				;FIVE RECORDS
 
;
; HARDWARE FUNCTION CODES
;
 
F_NOP=0*2				;NO OPERATION
F_SENSECHAR=0*2				;SENSE TAPE CHARACTERISTICS
F_SETCHAR=0*2				;SET TAPE CHARACTERISTICS
F_UNLOAD=1*2				;UNLOAD DRIVE
F_REWIND=3*2				;REWIND
F_DRVCLR=4*2				;DRIVE CLEAR
F_READPRESET=8*2			;READ IN PRESET
F_ERASE=10*2				;ERASE TAPE
F_WRITEMARK=11*2			;WRITE TAPE MARK
F_SPCFILFOR=12*2			;SPACE FILE FORWARD
F_SPCFILREV=13*2			;SPACE FILE REVERSE
F_SPCRECFOR=12*2			;SPACE RECORD FORWARD
F_SPCRECREV=13*2			;SPACE RECORD REVERSE
F_WRITECHECK=20*2			;WRITE CHECK DATA FORWARD
F_WRITECHECKR=23*2			;WRITE CHECK DATA REVERSE
F_WRITE=24*2				;WRITE DATA FORWARD
F_WRITEDATA=24*2			;WRITE DATA FORWARD
F_READDATA=28*2				;READ DATA FORWARD
F_READDATAR=31*2			;READ DATA REVERSE
 
;
; MINIMUM RECORD SIZE
;
 
MIN_RECORD=14				;FOURTEEN BYTES
 
;
; HARWARE DENSITY DEFINITIONS
;
 
NRZI=3					;800 BPI
PE=4					;PHASE ENCODED
 
;
; ERROR COUNT THRESHOLD BEFORE ALTERNATE RECOVERY ATTEMPTED
;
 
THRESHOLD=8				;EIGHT RETRIES BEFORE ALTERNATE METHOD
 
;
; LOCAL DATA
;
; DRIVER DISPATCH TABLE
;
 
	.PSECT	WIONONPAGED
TM$DDT::				;ADDRESS OF DRIVER DISPATCH TABLE
	.LONG	STARTIO			;START I/O OPERATION
	.LONG	UNSOLNT			;UNSOLICITED INTERRUPT
	.LONG	FUNCTABLE		;FUNCTION DECISION TABLE
	.LONG	0			;CANCEL I/O ENTRY POINT
	.LONG	REGDUMP			;REGISTER DUMP ROUTINE
	.WORD	<MT_TC+4+MBA$L_BCR+4+8>+<<3+5+1>*4> ;SIZE OF DIAGNOSTIC BUFFER
	.WORD	<MT_TC+4+MBA$L_BCR+4+8>+<1*4>+<EMB$L_DV_REGSAV> ;SIZE OF ERROR BUFFER
 
;
; DENSITY CODE TRANSLATION TABLE
;
;	DENSITY CODES ARE TRANSLATED BY TAKING THE FIVE BIT ENCODED DENSITY
;	VALUE, MULTIPLYING BY FOUR TO FORM THE STARTING BIT NUMBER, AND THEN
;	EXTRACTING THE APPROPRIATE DENSITY CODE FROM THE TRANSLATION TABLE.
;
 
DENSITY:				;
	.LONG	^X33343333		;DENSITY CODES 0-7
	.LONG	^X33333333		;DENSITY CODES 8-15
	.LONG	^X33333333		;DENSITY CODES 16-23
	.LONG	^X33333333		;DENSITY CODES 24-31
 
;
; HARDWARE I/O FUNCTION CODE TABLE
;
 
FTAB:					;
	GENF	F_NOP			;NO OPERATION
	GENF	F_UNLOAD		;UNLOAD VOLUME
	GENF	F_SPCFILFOR		;SPACE FILE FORWARD
	GENF	F_REWIND		;REWIND
	GENF	F_DRVCLR		;DRIVE CLEAR
	GENF	F_SPCFILREV		;SPACE FILE REVERSE
	GENF	F_ERASE			;ERASE TAPE
	GENF	F_SPCRECREV		;SPACE RECORD REVERSE
	GENF	F_SETCHAR		;SET TAPE CHARACTERISTICS
	GENF	F_SPCRECFOR		;SPACE RECORD FORWARD
	GENF	F_WRITECHECK		;WRITE CHECK FORWARD
	GENF	F_WRITEDATA		;WRITE DATA FORWARD
	GENF	F_READDATA		;READ DATA FORWARD
	GENF	F_WRITECHECKR		;WRITE CHECK REVERSE
	GENF	F_WRITE			;WRITE DATA FORWARD
	GENF	F_READDATAR		;READ DATA REVERSE
	GENF	F_READPRESET		;READ IN PRESET
	GENF	F_SENSECHAR		;SENSE TAPE CHARACTERISTICS
	GENF	F_WRITEMARK		;WRITE TAPE MARK
 
;
; FORMAT CODE TRANSLATION TABLE
;
;	FORMAT CODES ARE TRANSLATED BY TAKING THE FOUR BIT ENCODED FORMAT VALUE,
;	MULTIPLYING BY FOUR TO FORM THE STARTING BIT NUMBER, AND THEN EXTRACTING
;	THE APPROPRIATE FORMAT CODE FROM THE TRANSLATION TABLE.
;
 
FORMAT:					;
	.LONG	^XCCCCCCCC		;FORMAT CODES 0-7
	.LONG	^XCEDCCCCC		;FORMAT CODES 8-15
 
;
; FUNCTION TIME OUT TABLE
;
 
TIME_OUT:				;
	.LONG	0			;NO OPERATION
	.LONG	6			;UNLOAD VOLUME
	.LONG	60*5			;SPACE FILE FORWARD
	.LONG	60*5			;REWIND
	.LONG	0			;DRIVE CLEAR
	.LONG	60*5			;SPACE FILE REVERSE
	.LONG	6			;ERASE TAPE
	.LONG	6			;SPACE RECORD REVERSE
	.LONG	0			;SET TAPE CHARACTERISTICS
	.LONG	6			;SPACE RECORD FORWARD
	.LONG	6			;WRITE CHECK DATA FORWARD
	.LONG	6			;WRITE DATA FORWARD
	.LONG	6			;READ DATA FORWARD
	.LONG	6			;WRITE CHECK DATA REVERSE
	.LONG	6			;WRITE DATA FORWARD
	.LONG	6			;READ DATA REVERSE
	.LONG	60*5			;READ IN PRESET
	.LONG	0			;SENSE TAPE CHARACTERISITCS
	.LONG	6			;WRITE TAPE MARK
 
;
; DON'T CARE ERROR MASK TABLE
;
; THIS TABLE CONTAINS A MASK OF THE ERROR BITS THAT ARE TO BE IGNORED FOR EACH
; FUNCTION WHEN EXAMINING THE DRIVE ERROR REGISTER.
;
 
XTAB:					;
	MASK	<FMT,DPAR,INC,PEF,NSG,FCE,CS,DTE,OPI,COR> ;NO-OP
	MASK	<FMT,DPAR,INC,PEF,NSG,FCE,CS,DTE,OPI,COR> ;UNLOAD
	MASK	<FMT,DPAR,INC,PEF,NSG,CS,DTE,COR> ;SPACE FILE FORWARD
	MASK	<FMT,DPAR,INC,PEF,NSG,FCE,CS,DTE,OPI,COR> ;REWIND
	MASK	<FMT,DPAR,INC,PEF,NSG,FCE,CS,NEF,DTE,OPI,COR> ;DRIVE CLEAR
	MASK	<FMT,DPAR,INC,PEF,NSG,CS,DTE,COR> ;SPACE FILE REVERSE
	MASK	<FMT,DPAR,INC,PEF,NSG,FCE,DTE,OPI,COR> ;ERASE
	MASK	<FMT,DPAR,INC,PEF,NSG,CS,DTE,COR> ;SPACE RECORD REVERSE
	MASK	<FMT,DPAR,INC,PEF,NSG,FCE,CS,DTE,OPI,COR> ;SET CHARACTERISTICS
	MASK	<FMT,DPAR,INC,PEF,NSG,CS,DTE,COR> ;SPACE RECORD FORWARD
	MASK	<DPAR>			;WRITE CHECK FORWARD
	MASK	<>			;WRITE DATA FORWARD
	MASK	<DPAR>			;READ DATA FORWARD
	MASK	<DPAR>			;WRITE CHECK REVERSE
	MASK	<>			;WRITE DATA FORWARD
	MASK	<DPAR>			;READ DATA REVERSE
	MASK	<FMT,DPAR,INC,PEF,NSG,FCE,CS,DTE,OPI,COR> ;READIN PRESET
	MASK	<FMT,DPAR,INC,PEF,NSG,FCE,CS,DTE,OPI,COR> ;SENSE CHARACTERISTICS
	MASK	<FMT,DPAR,FCE,DTE,COR>	;WRITE TAPE MARK
	.PAGE
	.SBTTL	TE16/TU77 FUNCTION DECISION TABLE
;+
; TE16/TU77 FUNCTION DECISION TABLE
;-
 
FUNCTABLE:				;FUNCTION DECISION TABLE
	FUNCTAB	,-			;LEGAL FUNCTIONS
		<NOP,-			;NO OPERATION
		 UNLOAD,-		;UNLOAD VOLUME
		 SPACERECORD,-		;SPACE RECORDS
		 RECAL,-		;RECALIBRATE (REWIND)
		 DRVCLR,-		;DRIVE CLEAR
		 READPRESET,-		;READ IN PRESET
		 ERASETAPE,-		;ERASE TAPE
		 SENSECHAR,-		;SENSE TAPE CHARACTERISTICS
		 SETCHAR,-		;SET CHARACTERISTICS
		 SPACEFILE,-		;SPACE FILE
		 WRITECHECK,-		;WRITE CHECK FORWARD
		 WRITEPBLK,-		;WRITE PHYSICAL BLOCK
		 READPBLK,-		;READ PHYSICAL BLOCK
		 WRITEMARK,-		;WRITE TAPE MARK
		 READLBLK,-		;READ LOGICAL BLOCK
		 WRITELBLK,-		;WRITE LOGICAL BLOCK
		 SENSEMODE,-		;SENSE TAPE MODE
		 SETMODE,-		;SET MODE
		 REWIND,-		;REWIND
		 REWINDOFF,-		;REWIND AND SET OFFLINE
		 SKIPRECORD,-		;SKIP RECORDS
		 SKIPFILE,-		;SKIP FILES
		 WRITEOF,-		;WRITE END OF FILE
		 READVBLK,-		;READ VIRTUAL BLOCK
		 WRITEVBLK,-		;WRITE VIRTUAL BLOCK
		 ACCESS,-		;ACCESS FILE AND/OR FIND DIRECTORY ENTRY
		 ACPCONTROL,-		;ACP CONTROL FUNCTION
		 CREATE,-		;CREATE FILE AND/OR CREATE DIRECTORY ENTRY
		 DEACCESS,-		;DEACCESS FILE
		 DELETE,-		;DELETE FILE AND/OR DIRECTORY ENTRY
		 MODIFY>		;MODIFY FILE ATTRIBUTES
	FUNCTAB	,-			;BUFFERED I/O FUNCTIONS
		<ACCESS,-		;ACCESS FILE AND/OR FIND DIRECTORY ENTRY
		 ACPCONTROL,-		;ACP CONTROL FUNCTION
		 CREATE,-		;CREATE FILE AND/OR CREATE DIRECTORY ENTRY
		 DEACCESS,-		;DEACCESS FILE
		 DELETE,-		;DELETE FILE AND/OR DIRECTORY ENTRY
		 MODIFY>		;MODIFY FILE ATTRIBUTES
	FUNCTAB	ACP$READBLK,-		;READ FUNCTIONS
		<READLBLK,-		;READ LOGICAL BLOCK FORWARD
		 READPBLK,-		;READ PHYSICAL BLOCK FORWARD
		 READVBLK>		;READ VIRTUAL BLOCK
	FUNCTAB	ACP$WRITEBLK,-		;WRITE FUNCTIONS
		<WRITECHECK,-		;WRITE CHECK FORWARD
		 WRITELBLK,-		;WRITE LOGICAL BLOCK
		 WRITEPBLK,-		;WRITE PHYSICAL BLOCK
		 WRITEVBLK>		;WRITE VIRTUAL BLOCK
	FUNCTAB	ACP$ACCESS,<ACCESS,CREATE> ;ACCESS AND CREATE FILE OR DIRECTORY
	FUNCTAB	ACP$DEACCESS,<DEACCESS>	;DEACCESS FILE
	FUNCTAB	ACP$MODIFY,-		;
		<ACPCONTROL,-		;ACP CONTROL FUNCTION
		 DELETE,-		;DELETE FILE OR DIRECTORY ENTRY
		 MODIFY>		;MODIFY FILE ATTRIBUTES
	FUNCTAB	MT$CHECK_ACCESS,-	;MAGTAPE CHECK ACCESS FUNCTIONS
		<ERASETAPE,-		;ERASE TAPE
		 WRITEMARK,-		;WRITE TAPE MARK
		 WRITEOF>		;WRITE END OF FILE
	FUNCTAB	EXE$ZEROPARM,-		;ZERO PARAMETER FUNCTIONS
		<NOP,-			;NO OPERATION
		 UNLOAD,-		;UNLOAD VOLUME
		 RECAL,-		;RECALIBRATE (REWIND)
		 REWIND,-		;REWIND
		 REWINDOFF,-		;REWIND AND SET OFFLINE
		 DRVCLR,-		;DRIVE CLEAR
		 READPRESET,-		;READ IN PRESET
		 ERASETAPE,-		;ERASE TAPE
		 SENSECHAR,-		;SENSE TAPE CHARACTERISTICS
		 SENSEMODE,-		;SENSE TAPE MODE
		 WRITEMARK,-		;WRITE TAPE MARK
		 WRITEOF>		;WRITE END OF FILE
	FUNCTAB	EXE$ONEPARM,-		;ONE PARAMETER FUNCTIONS
		<SPACERECORD,-		;SPACE RECORDS
		 SPACEFILE,-		;SPACE FILES
		 SKIPRECORD,-		;SKIP RECORDS
		 SKIPFILE>		;SKIP FILES
	FUNCTAB	EXE$SETMODE,-		;SET TAPE CHARACTERISTICS
		<SETCHAR,-		;
		 SETMODE>		;
	.PAGE
	.SBTTL	START I/O OPERATION
;+
; STARTIO - START I/O OPERATION ON DEVICE UNIT
;
; THIS ENTRY POINT IS ENTERED TO START AN I/O OPERATION ON A DEVICE UNIT.
;
; INPUTS:
;
;	R3 = ADDRESS OF I/O PACKET.
;	R5 = UCB ADDRESS OF DEVICE UNIT.
;
; OUTPUTS:
;
;	******OUTPUTS*******
;-
 
STARTIO:				;START I/O OPERATION
	MOVB	UCB$B_ERTMAX(R5),UCB$B_ERTCNT(R5) ;INITIALIZE ERROR RETRY COUNT
	MOVW	IRP$W_FUNC(R3),UCB$W_MT_FUNC(R5) ;SAVE FUNCTION CODE AND MODIFIERS
	MNEGW	#1,UCB$W_MT_SPACNT(R5)	;SET DEFAULT SPACING COUNT
	MOVL	IRP$L_MEDIA(R3),R0	;GET PARAMETER LONGWORD
 
;
; MOVE FUNCTION DEPENDENT PARAMETERS TO UCB
;
 
	EXTZV	#IRP$V_FCODE,#IRP$S_FCODE,- ;EXTRACT I/O FUNCTION CODE
		IRP$W_FUNC(R3),R1	;
	CMPL	#IO$_SPACEFILE,R1	;SPACE FILE FUNCTION?
	BEQL	10$			;IF EQL YES
	CMPL	#IO$_SPACERECORD,R1	;SPACE RECORD FUNCTION?
	BEQL	20$			;IF EQL YES
	CMPL	#IO$_SETCHAR,R1		;SET CHARACTERISTICS FUNCTION?
	BEQL	50$			;IF EQL YES
	CMPL	#IO$_READPBLK+1,R1	;DISJOINT FUNCTION CODE?
	BGTRU	100$			;IF GTRU NO
	CASE	R1,<-			;DISPATCH LOGICAL FUNCTIONS
		70$,-			;REWIND AND SET OFFLINE
		60$,-			;SET MODE
		80$,-			;REWIND
		10$,-			;SKIP FILE
		20$,-			;SKIP RECORD
		90$,-			;SENSE TAPE MODE
		90$,-			;WRITE EOF
		>,LIMIT=#IO$_REWINDOFF ;
	SUBW	#IO$_READPRESET-IO$_READPBLK-4,R1 ;CONVERT TO DENSE FUNCTION CODE
	BRB	110$			;
 
;
; SPACE FILE FUNCTION - SET SPACE COUNT AND PROPER FUNCTION
;
 
10$:	MOVZBL	#CDF_SPCFILFOR,R1	;SET FOR SPACE FILE FORWARD
	INCW	UCB$W_MT_SPACNT(R5)	;SET DEFAULT SPACING COUNT TO LARGEST VALUE
	TSTW	R0			;SPACE FILE FORWARD?
	BGTR	40$			;IF GTR YES
	MOVZBL	#CDF_SPCFILREV,R1	;SET FOR SPACE FILE REVERSE
	BRB	30$			;
 
;
; SPACE RECORD FUNCTION - SET SPACE COUNT AND PROPER FUNCTION
;
 
20$:	MOVZBL	#CDF_SPCRECFOR,R1	;SET FOR SPACE RECORD FORWARD
	MNEGW	R0,UCB$W_MT_SPACNT(R5)	;SET SPACING COUNT
	BLSS	40$			;IF LSS SPACE FORWARD FUNCTION
	MOVZBL	#CDF_SPCRECREV,R1	;SET FOR SPACE RECORD REVERSE
	MOVW	R0,UCB$W_MT_SPACNT(R5)	;SET SPACING COUNT
30$:	MNEGW	R0,R0			;CONVERT TO POSITIVE COUNT
40$:	MOVW	R0,UCB$W_BOFF(R5)	;SET SPACE COUNT
	MOVW	R0,UCB$W_BCNT(R5)	;SET SPACE COUNT
	BNEQ	110$			;IF NEQ SPACING REQUIRED
	MOVZBL	#CDF_NOP,R1		;SET FOR NO OPERATION
	BRB	110$			;
 
;
; SET CHARACTERISTICS FUNCTION - STORE NEW TAPE CHARACTERISTICS
;
 
50$:	MOVW	IRP$L_MEDIA(R3),UCB$B_DEVCLASS(R5) ;SET NEW DEVICE CLASS AND TYPE
 
;
; SET MODE FUNCTION - STORE NEW TAPE MODE
;
 
60$:	MOVW	IRP$L_MEDIA+2(R3),UCB$W_DEVBUFSIZ(R5) ;SET NEW DEFAULT BUFFER SIZE
	MOVW	IRP$L_MEDIA+4(R3),UCB$W_BOFF(R5) ;SAVE NEW TAPE CONTROL PARAMETERS
	MOVZBL	#CDF_SETCHAR,R1		;SET FUNCTION DISPATCH INDEX
	BRB	110$			;
 
;
; LOGICAL REWIND AND SET TAPE OFFLINE - CONVERT TO UNLOAD FUNCTION
;
 
70$:	MOVZBL	#CDF_UNLOAD,R1		;SET FOR UNLOAD FUNCTION
	BRB	110$			;
 
;
; LOGICAL REWIND FUNCTION - CONVERT TO PHYSICAL FUNCTION
;
 
80$:	MOVZBL	#CDF_REWIND,R1		;SET FOR REWIND FUNCTION
	BRB	110$			;
 
;
; LOGICAL WRITE EOF OR SENSE MODE FUNCTION - CONVERT TO PHYSICAL FUNCTION
;
 
90$:	SUBW	#IO$_SENSEMODE-IO$_READPBLK-5,R1 ;CONVERT TO PHYSICAL FUNCTION
	BRB	110$			;
 
;
; DENSE FUNCTION CODE - CHECK FOR READ, WRITE, OR WRITECHECK FUNCTION
;
 
100$:	CMPL	#IO$_WRITECHECK,R1	;DATA TRANSFER FUNCTION?
	BGTRU	110$			;IF GTRU NO
	BBC	#IO$V_REVERSE,UCB$W_MT_FUNC(R5),110$ ;IF CLR, NOT REVERSE FUNCTION
	ADDW	#CDF_WRITECHECKR-CDF_WRITECHECK,R1 ;CONVERT TO REVERSE FUNCTION
 
;
; FINISH PREPROCESSING
;
 
110$:	MOVB	R1,UCB$B_FEX(R5)	;SAVE FUNCTION DISPATCH INDEX
 
;
; CENTRAL FUNCTION DISPATCH
;
 
FDISPATCH:				;FUNCTION DISPATCH
	REQPCHAN			;REQUEST PRIMARY I/O CHANNEL
	MOVL	R4,R3			;SAVE ADDRESS OF TM03/DRIVE REGISTERS
	MOVL	UCB$L_CRB(R5),R4	;GET ADDRESS OF CRB
	MOVL	CRB$L_LINK(R4),R4	;GET ADDRESS OF SECONDARY CRB
	MOVL	@CRB$L_INTD+VEC$L_IDB(R4),R4 ;GET ADDRESS OF MBA CSR
	MOVZBL	UCB$B_FEX(R5),R0	;GET DISPATCH FUNCTION CODE
	BICW	#UCB$M_CANCEL!-		;CLEAR CANCEL I/O,
		UCB$M_POWER!-		;POWERFAIL, AND
		UCB$M_TIMOUT,UCB$W_STS(R5) ;TIMEOUT STATUS BITS
	CASE	R0,<-			;DISPATCH TO FUNCTION HANDLING ROUTINE
		NOP,-			;NO OPERATION
		UNLOAD,-		;UNLOAD VOLUME
		SPCFILFOR,-		;SPACE FILE FORWARD
		REWIND,-		;REWIND
		DRVCLR,-		;DRIVE CLEAR
		SPCFILREV,-		;SPACE FILE REVERSE
		ERASE,-			;ERASE TAPE
		SPCRECREV,-		;SPACE RECORD REVERSE
		SETCHAR,-		;SET TAPE CHARACTERISTICS
		SPCRECFOR,-		;SPACE RECORD FORWARD
		WRITECHECK,-		;WRITE CHECK FORWARD
		WRITEDATA,-		;WRITE DATA FORWARD
		READDATA,-		;READ DATA FORWARD
		WRITECHECKR,-		;WRITE CHECK REVERSE
		WRITEDATA,-		;WRITE DATA FORWARD
		READDATAR,-		;READ DATA REVERSE
		READPRESET,-		;READ IN PRESET
		SENSECHAR,-		;SENSE TAPE CHARACTERISTICS
		>			;
	.PAGE
	.SBTTL	WRITE TAPE MARK FUNCTION
;
; WRITE TAPE MARK FUNCTION
;
 
WRITEMARK:				;WRITE TAPE MARK
	EXFUNC	10$,F_WRITEMARK		;EXECUTE FUNCTION
	INCL	UCB$L_MT_RECORD(R5)	;UPDATE TAPE POSITION
	MOVZWL	S^#SS$_NORMAL,R0	;SET NORMAL COMPLETION STATUS
	BRW	FUNCXT			;
 
;
; FUNCTION ENDED IN AN ERROR
;
; THE ERROR COULD BE A NONFATAL CONTROLLER OR DRIVE ERROR. FATAL ERRORS TERMINATE
; THE FUNCTION IN THE FUNCTION EXECUTOR.
;
; FATAL CONTROLLER ERRORS ARE:
;
;	ERCONF	= ERROR CONFIRMATION.
;	ISTO	= INTERFACE SEQUENCE TIMEOUT.
;	PGE	= PROGRAMMING ERROR.
;	NED	= NONEXISTENT DRIVE.
;	RDTO	= READ DATA TIMEOUT.
;
; FATAL DRIVE ERRORS ARE:
;
;	ILF	= ILLEGAL FUNCTION.
;	ILR	= ILLEGAL REGISTER.
;	NEF	= NONEXECUTABLE FUNCTION.
;	RMR	= REGISTER MODIFY REFUSE.
;	UNS	= UNSAFE.
;
; IGNORED DRIVE ERRORS ARE:
;
;	FMT	= FORMAT.
;	DPAR	= DATA BUS PARITY.
;	FCE	= FRAME COUNT.
;	DTE	= DRIVE TIMING.
;	COR/CRC	= CORRECTABLE OR CHECK CHARACTER ERROR.
;
; NOTE THAT IT IS ASSUMED THAT MASSBUS EXCEPTION (MBEXC) WILL OCCUR ONLY IN
; COMBINATION WITH ANOTHER DRIVE OR CONTROLLER ERROR.
;
 
10$:	TESTR	20$			;TEST REMAINING RETRIES AND RELEASE CHANNEL
	EXFUNC	DOUBLE,F_SPCRECREV	;SPACE RECORD REVERSE
20$:	BBS	#IO$V_INHEXTGAP,UCB$W_MT_FUNC(R5),30$ ;IF SET, NO EXTENDED GAPS
	EXFUNC	DOUBLE,F_ERASE		;WRITE EXTENDED INTER-RECORD GAP
30$:	BRB	WRITEMARK		;
	.PAGE
	.SBTTL	ERASE TAPE FUNCTION
;
; ERASE TAPE FUNCTION
;
 
ERASE:					;ERASE TAPE
	EXFUNC	10$			;EXECUTE FUNCTION
	MOVZWL	S^#SS$_NORMAL,R0	;SET NORMAL COMPLETION
	CLRW	UCB$W_MT_FC(R5)		;CLEAR FRAME COUNT
	BRW	FUNCXT			;
 
;
; FUNCTION ENDED IN AN ERROR
;
; THE ERROR COULD BE A NONFATAL CONTROLLER OR DRIVE ERROR. FATAL ERRORS TERMINATE
; THE FUNCTION IN THE FUNCTION EXECUTOR.
;
; FATAL CONTROLLER ERRORS ARE:
;
;	ERCONF	= ERROR CONFIRMATION.
;	ISTO	= INTERFACE SEQUENCE TIMEOUT.
;	PGE	= PROGRAMMING ERROR.
;	NED	= NONEXISTENT DRIVE.
;	RDTO	= READ DATA TIMEOUT.
;
; FATAL DRIVE ERRORS ARE:
;
;	ILF	= ILLEGAL FUNCTION.
;	ILR	= ILLEGAL REGISTER.
;	NEF	= NONEXECUTABLE FUNCTION.
;	RMR	= REGISTER MODIFY REFUSE.
;	UNS	= UNSAFE.
;
; IGNORED DRIVE ERRORS ARE:
;
;	FMT	= FORMAT.
;	DPAR	= DATA BUS PARITY.
;	INC/VPE	= INCORRECTABLE OR VERTICLE PARITY ERROR.
;	PEF/LRC	= FORMAT (PE) OR LONGITUDINAL PARITY ERROR.
;	NSG	= NONSTANDARD GAP.
;	FCE	= FRAME COUNT.
;	DTE	= DRIVE TIMING.
;	OPI	= OPERATION INCOMPLETE.
;	COR/CRC	= CORRECTABLE OR CHECK CHARACTER ERROR.
;
 
10$:	EXFUNC	DOUBLE,F_SPCRECREV	;BACK SPACE RECORD
	EXFUNC	DOUBLE,F_SPCRECFOR	;SPACE RECORD FORWARD
	BRW	RETRY			;
	.PAGE
	.SBTTL	HOUSEKEEPING FUNCTIONS
;
; HOUSEKEEPING FUNCTIONS INCLUDE:
;
;	NO OPERATION,
;	DRIVE CLEAR,
;	SENSE TAPE CHARACTERISTICS, AND
;	SET TAPE CHARACTERISTICS.
;
; IF THE FUNCTION ENDS IN A NONFATAL DRIVE ERROR IT IS RETRIED. FATAL ERRORS
; TERMINATE THE FUNCTION IN THE FUNCTION EXECUTOR.
;
; FATAL DRIVE ERRORS ARE:
;
;	ILF	= ILLEGAL FUNCTION.
;	ILR	= ILLEGAL REGISTER.
;	NEF	= NONEXECUTABLE FUNCTION (EXCEPT FOR DRIVE CLEAR).
;	RMR	= REGISTER MODIFY REFUSE.
;	UNS	= UNSAFE.
;
; IGNORED DRIVE ERRORS ARE:
;
;	FMT	= FORMAT.
;	DPAR	= DATA BUS PARITY.
;	INC/VPE	= INCORRECTABLE OR VERTICLE PARITY ERROR.
;	PEF/LRC	= FORMAT (PE) OR LONGITUDINAL PARITY ERROR.
;	NSG	= NONSTANDARD GAP.
;	FCE	= FRAME COUNT.
;	CS/ITM	= CORRECTABLE SKEW OR INVALID TAPE MARK.
;	DTE	= DRIVE TIMING.
;	OPI	= OPERATION INCOMPLETE.
;	COR/CRC	= CORRECTABLE OR CHECK CHARACTER ERROR.
;
; ADDITIONAL IGNORED DRIVE ERRORS FOR DRIVE CLEAR ARE:
;
;	NEF	= NONEXECUTABLE FUNCTION.
;
; NO OPERATION, SENSE CHARACTERISTICS, AND DRIVE CLEAR.
;
;
 
	.ENABL	LSB
NOP:					;NO OPERATION
SENSECHAR:				;SENSE CHARACTERISTICS
DRVCLR:					;DRIVE CLEAR
	EXFUNC	RETRY			;EXECUTE HOUSEKEEPING FUNCTION
	BRB	30$			;
 
;
; SET TAPE CHARACTERISTICS
;
 
SETCHAR:				;SET TAPE CHARACTERISTICS
	EXFUNC	RETRY			;EXECUTE FUNCTION
	EXTZV	#MT$V_DENSITY,#MT$S_DENSITY,- ;EXTRACT DENSITY CODE
		UCB$W_BOFF(R5),R0	;
	MULL	#4,R0			;CALCULATE BIT NUMBER
	EXTZV	R0,#4,DENSITY,R0	;EXTRACT DENSITY CODE
	EXTZV	#MT$V_FORMAT,#MT$S_FORMAT,- ;EXTRACT FORMAT CODE
		UCB$W_BOFF(R5),R1	;
	MULL	#4,R1			;CALCULATE BIT NUMBER
	EXTZV	R1,#4,FORMAT,R1		;EXTRACT FORMAT CODE
	MOVZWL	#MT$M_FORMAT,R3		;SET INITIAL MASK WORD
	BBC	#MT_DS_V_BOT,R2,10$	;IF CLR, TAPE NOT AT BEGINNING
 
;
; TAPE DENSITY CAN ONLY BE SET WHEN THE SELECTED DRIVE IS AT BEGINNING OF TAPE
;
 
	INSV	R0,#MT_TC_V_DEN,-	;SET NEW DENSITY
		#MT_TC_S_DEN,UCB$W_MT_TC(R5) ;
	BISW	#MT$M_DENSITY,R3	;SET DENSITY MASK BITS
10$:	BICW	#MT_TC_M_EPAR,UCB$W_MT_TC(R5) ;CLEAR EVEN PARITY
	BBS	#MT_TC_V_DEN+2,UCB$W_MT_TC(R5),20$ ;IF SET, PHASE ENCODED TAPE
 
;
; TAPE PARITY CAN ONLY BE SET IF NRZI FORMATTED TAPE IS BEING READ OR WRITTEN
;
 
	BBC	#MT$V_PARITY,UCB$W_BOFF(R5),20$ ;IF CLR, ODD PARITY
	BISW	#MT_TC_M_EPAR,UCB$W_MT_TC(R5) ;SET EVEN PARITY
	BISW	#MT$M_PARITY,R3		;SET PARITY MASK BIT
20$:	INSV	R1,#MT_TC_V_FSEL,-	;SET NEW FORMAT
		#MT_TC_S_FSEL,UCB$W_MT_TC(R5) ;
	BICW	R3,UCB$L_DEVDEPEND(R5)	;CLEAR OLD FIELD VALUES
	MCOML	R3,R3			;COMPLEMENT MASK
	BICW	R3,UCB$W_BOFF(R5)	;CLEAR FIELDS NOT BE BE INSERTED
	BISW	UCB$W_BOFF(R5),UCB$L_DEVDEPEND(R5) ;INSERT NEW FIELD VALUES
30$:	CLRW	UCB$W_MT_FC(R5)		;CLEAR SAVED FRAME COUNT REGISTER
	MOVZWL	S^#SS$_NORMAL,R0	;SET NORMAL COMPLETION
	BRW	FUNCXT			;
	.DSABL	LSB
	.PAGE
	.SBTTL	REWIND AND UNLOAD FUNCTIONS
;
; REWIND AND UNLOAD FUNCTIONS INCLUDE:
;
;	READIN PRESET,
;	REWIND, AND
;	UNLOAD.
;
; IF THE FUNCTION ENDS WITH A NONFATAL DRIVE ERRORS IT IS RETRIED. FATAL ERRORS
; TERMINATE THE FUNCTION IN THE FUNCTION EXECUTOR.
;
; FATAL DRIVE ERRORS ARE:
;
;	ILF	= ILLEGAL FUNCTION.
;	ILR	= ILLEGAL REGISTER.
;	NEF	= NONEXECUTABLE FUNCTION.
;	RMR	= REGISTER MODIFY REFUSE.
;	UNS	= UNSAFE.
;
; IGNORED DRIVE ERRORS ARE:
;
;	FMT	= FORMAT.
;	DPAR	= DATA BUS PARITY.
;	INC/VPE	= INCORRECTABLE OR VERTICLE PARITY ERROR.
;	PEF/LRC	= FORMAT (PE) OR LONGITUDINAL PARITY ERROR.
;	NSG	= NONSTANDARD GAP.
;	FCE	= FRAME COUNT.
;	CS/ITM	= CORRECTABLE SKEW OR INVALID TAPE MARK.
;	DTE	= DRIVE TIMING.
;	OPI	= OPERATION INCOMPLETE.
;	COR/CRC	= CORRECTABLE OR CHECK CHARACTER ERROR.
;
 
READPRESET:				;READ IN PRESET
	TSTW	UCB$W_UNIT(R5)		;UNIT ZERO?
	BEQL	REWIND			;IF EQL YES
	MOVZBL	#CDF_REWIND,R0		;CONVERT FUNCTION TO REWIND
 
;
; UNLOAD AND REWIND FUNCTIONS
;
 
REWIND:					;REWIND TO BEGINNING OF TAPE
UNLOAD:					;UNLOAD VOLUME
	EXFUNC	LOSTPOS			;EXECUTE FUNCTION
	CLRW	UCB$W_MT_FC(R5)		;CLEAR SAVED FRAME COUNT REGISTER
	MOVZWL	S^#SS$_NORMAL,R0	;SET NORMAL COMPLETION STATUS
	BRW	FUNCXT			;
	.PAGE
	.SBTTL	SPACING FUNCTIONS
;
; SPACING FUNCTIONS INCLUDE:
;
;	SPACE FILE FORWARD,
;	SPACE FILE REVERSE,
;	SPACE RECORD FORWARD, AND
;	SPACE RECORD REVERSE.
;
; ALL ARE IMPLEMENTED VIA THE SPACE RECORD FUNCTIONS.
;
; A SPACING FUNCTION CAN END WITH A NONFATAL DRIVE ERROR. FATAL ERRORS TERMINATE
; THE FUNCTION IN THE FUNCTION EXECUTOR.
;
; FATAL DRIVE ERRORS ARE:
;
;	ILF	= ILLEGAL FUNCTION.
;	ILR	= ILLEGAL REGISTER.
;	NEF	= NONEXECUTABLE FUNCTION (FORWARD FUNCTIONS).
;	RMR	= REGISTER MODIFY REFUSE.
;	UNS	= UNSAFE.
;
; NONFATAL DRIVE ERRORS ARE:
;
;	CPAR	= CONTROL BUS PARITY.
;	FCE	= FRAME COUNT.
;	NEF	= NONEXECUTABLE FUNCTION (REVERSE FUNCTIONS INTO BEGINNING OF TAPE).
;	OPI	= OPERATION INCOMPLETE (REVERSE FUNCTIONS INTO BEGINNING OF TAPE).
;
; IGNORED DRIVE ERRORS ARE:
;
;	FMT	= FORMAT.
;	DPAR	= DATA BUS PARITY.
;	INC/VPE	= INCORRECTABLE OR VERTICLE PARITY ERROR.
;	PEF/LRC	= FORMAT (PE) OR LONGITUDINAL PARITY ERROR.
;	NSG	= NONSTANDARD GAP.
;	CS/ITM	= CORRECTABLE SKEW OR INVALID TAPE MARK.
;	DTE	= DRIVE TIMING.
;	COR/CRC	= CORRECTABLE OR CHECK CHARACTER ERROR.
;
; SPACE FILE FORWARD
;
;	SPACING FILES IS ACCOMPLISHED BY SPACING A VERY LARGE NUMBER OF RECORDS.
;	IF THE RECORD SPACING OPERATION COMPLETES WITHOUT ERROR, THEN THE RECORD
;	COUNT IS INCREASED BY 65,536 AND THE SPACING OPERATION IS CONTINUED.
;
;	SEVERAL SPECIAL CONDITIONS CAN ARISE DURING A SPACE FILE FORWARD:
;
;		1. A CONTROL BUS PARITY ERROR OCCURS.
;
;			THE OPERATION IS MERELY RETRIED SINCE TAPE MOTION COULD
;			NOT HAVE OCCURED.
;
;		2. AN END OF TAPE IS ENCOUNTERED WITHOUT AN END OF FILE.
;
;			THE OPERATION IS CONTINUED SINCE END OF TAPE WHILE FILE
;			SKIPPING DOES NOT TERMINATE THE OPERATION.
;
;		3. AN END OF FILE IS ENCOUNTERED.
;
;			THE FILE SKIP COUNT IS DECREMENTED AND IF NONZERO, THE
;			OPERATION IS CONTINUED.
;
;	UNLESS A HARD ERROR IS ENCOUNTERED, NORMAL COMPLETION IS ALWAYS RETURNED
;	FOR A SKIP FILE FORWARD FUNCTION.
;
;	AS RECORDS ARE SKIPPED FORWARD ON THE TAPE, THE CURRENT TAPE POSITION IS
;	MAINTAINED BY ADDING THE NUMBER OF RECORDS AND TAPE MARKS SKIPPED OVER.
;
 
SPCFILFOR:				;SPACE FILE FORWARD
	EXFUNC	10$,F_SPCFILFOR		;EXECUTE FUNCTION
	INCW	UCB$L_MT_RECORD+2(R5)	;UPDATE TAPE POSITION
	BRB	SPCFILFOR		;
10$:	CHECK_ERROR			;CHECK FOR FATAL OF RETRIABLE ERROR
	MOVZWL	UCB$W_MT_FC(R5),R0	;GET NUMBER OF RECORDS SKIPPED OVER
	ADDL	R0,UCB$L_MT_RECORD(R5)	;UPDATE TAPE POSITION
	BBC	#MT_DS_V_TM,R2,SPCFILFOR ;IF CLR, TAPE MARK NOT ENCOUNTERED
	DECW	UCB$W_BOFF(R5)		;DECREMENT NUMBER OF FILES TO SKIP
	BNEQ	SPCFILFOR		;IF NEQ MORE TO GO
	BRW	NORXIT			;
 
;
; SPACE FILE REVERSE
;
;	SPACING FILES IS ACCOMPLISHED BY SPACING A VERY LARGE NUMBER OF RECORDS.
;	IF THE RECORD SPACING OPERATION COMPLETES WITHOUT ERROR, THE THE RECORD
;	COUNT IS REDUCED BY 65,536 AND THE SPACING OPERATION IS CONTINUED.
;
;	SEVERAL SPECIAL CONDITIONS CAN ARISE DURING A SPACE FILE REVERSE:
;
;		1. A CONTROL BUS PARITY ERROR OCCURS.
;
;			THE OPERATION IS MERELY RETRIED SINCE TAPE MOTION COULD
;			NOT HAVE OCCURED.
;
;		2. AN END OF TAPE IS ENCOUNTERED WITHOUT AN END OF FILE.
;
;			THE OPERATION IS CONTINUED SINCE END OF TAPE WHILE FILE
;			SKIPPING DOES NOT TERMINATE THE OPERATION.
;
;		3. A BEGINNING OF TAPE IS ENCOUNTERED.
;
;			THE OPERATION IS IMMEDIATELY TERMINATED.
;
;		4. AN END OF FILE IS ENCOUNTERED.
;
;			THE FILE SKIP COUNT IS DECREMENTED AND IF NONZERO, THE
;			OPERATION IS CONTINUED.
;
;	UNLESS A HARD ERROR IS ENCOUNTERED, NORMAL COMPLETION IS ALWAYS RETURNED
;	FOR A SKIP FILE REVERSE OPERATION.
;
;	AS RECORDS ARE SKIPPED BACKWARDS ON THE TAPE, THE CURRENT TAPE POSITION
;	IS MAINTAINED BY SUBTRACTING THE NUMBER RECORDS AND TAPE MARKS SKIPPED
;	OVER.
;
 
SPCFILREV:				;SPACE FILE REVERSE
	EXFUNC	10$,F_SPCFILREV		;EXECUTE FUNCTION
	DECW	UCB$L_MT_RECORD+2(R5)	;UPDATE RECORD POSITION
	BRB	SPCFILREV		;
10$:	CHECK_ERROR			;CHECK FOR FATAL OR RETRIABLE ERROR
	MOVZWL	UCB$W_MT_FC(R5),R0	;GET NUMBER OF RECORDS SKIPPED OVER
	SUBL	R0,UCB$L_MT_RECORD(R5)	;UPDATE TAPE POSITION
	BITW	#MT_DS_M_BOT!MT_DS_M_TM,R2 ;NOT AT BOT AND NO TAPE MARK ENCOUNTERED?
	BEQL	SPCFILREV		;IF EQL YES
	BBS	#MT_DS_V_BOT,R2,20$	;IF SET, BEGINNING OF TAPE
	DECW	UCB$W_BOFF(R5)		;ANY MORE FILES TO SKIP?
	BNEQ	SPCFILREV		;IF NEQ YES
20$:	BRB	NORXIT			;
 
;
; SPACE RECORD FORWARD
;
;	SEVERAL SPECIAL CONDITIONS CAN ARISE DURING A SPACE FORWARD:
;
;		1. A CONTROL BUS PARITY ERROR OCCURS.
;
;			THE OPERATION IS MERELY RETRIED SINCE TAPE MOTION COULD
;			NOT HAVE OCCURED.
;
;		2. AN END OF TAPE IS ENCOUNTERED WITHOUT AN END OF FILE.
;
;			THE OPERATION IS TERMINATED WITH A FINAL STATUS OF END OF
;			TAPE.
;
;		3. AN END OF FILE IS ENCOUNTERED.
;
;			THE OPERATION IS TERMINATED WITH A FINAL STATUS OF END OF
;			FILE.
;
;	UNLESS A HARD ERROR IS ENCOUNTERED, THE CURRENT TAPE POSITION IS MAINTAINED
;	BY ADDING THE TOTAL NUMBER OF RECORDS SKIPPED OVER.
;
 
SPCRECFOR:				;SPACE RECORD FORWARD
	EXFUNC	10$			;EXECUTE FUNCTION
	BRB	20$			;
10$:	CHECK_ERROR			;CHECK FOR FATAL OR RETRIABLE ERROR
20$:	CLRL	R0			;CLEAR UPPER HALF OF REGISTER
	ADDW3	UCB$W_MT_FC(R5),UCB$W_BOFF(R5),R0 ;CALCULATE RECORDS SKIPPED
	ADDL	R0,UCB$L_MT_RECORD(R5)	;UPDATE TAPE POSITION
	MNEGW	UCB$W_MT_FC(R5),UCB$W_BOFF(R5) ;SET REMAINING RECORD SKIP COUNT
	BBS	#MT_DS_V_TM,R2,SETEOF	;IF SET, END OF FILE ENCOUNTERED
	BRB	NORXIT			;
 
;
; SPACE RECORD REVERSE
;
;	SEVERAL SPECIAL CONDITIONS CAN ARISE DURING A SPACE RECORD REVERSE:
;
;		1. A CONTROL BUS PARITY ERROR.
;
;			THE OPERATION IS MERELY RETRIED SINCE TAPE MOTION COULD
;			NOT HAVE OCCURED.
;
;		2. A BEGINNING OF TAPE IS ENCOUNTERED.
;
;			THE OPERATION IS TERMINATED WITH A FINAL STATUS OF END OF
;			FILE.
;
;		3. AN END OF TAPE IS ENCOUNTERED WITHOUT AN END OF FILE.
;
;			THE OPERATION IS CONTINUED SINCE AN END OF TAPE WHILE
;			SKIPPING RECORDS BACKWARDS DOES NOT TERMINATE THE OPER-
;			ATION.
;
;		4. AN END OF FILE IS ENCOUNTERED.
;
;			THE OPERATION IS TERMINATED WITH A FINAL STATUS OF END OF
;			FILE.
;
;	UNLESS A HARD ERROR IS ENCOUNTERED, THE CURRENT TAPE POSITION IS MAINTAINED
;	BY SUBTRACTING THE TOTAL NUMBER OF RECORDS SKIPPED OVER.
;
 
SPCRECREV:				;SPACE RECORD REVERSE
	EXFUNC	10$,F_SPCRECREV		;EXECUTE FUNCTION
	BRB	20$			;
10$:	CHECK_ERROR			;CHECK FOR FATAL OR RETRIABLE ERROR
20$:	CLRL	R0			;CLEAR UPPER HALF OF REGISTER
	ADDW3	UCB$W_MT_FC(R5),UCB$W_BOFF(R5),R0 ;CALCULATE RECORD SKIP COUNT
	SUBL	R0,UCB$L_MT_RECORD(R5)	;UPDATE TAPE POSITION
	MNEGW	UCB$W_MT_FC(R5),UCB$W_BOFF(R5) ;SET REMAINING RECORD SKIP COUNT
	MOVW	UCB$W_MT_FC(R5),UCB$W_MT_SPACNT(R5) ;RESET SPACING COUNT
	BBS	#MT_DS_V_TM,R2,SETEOF	;IF SET, END OF FILE ENCOUNTERED
	BBS	#MT_DS_V_BOT,R2,SETEOF	;IF SET, BEGINNING OF TAPE ENCOUNTERED
	BBS	#MT_DS_V_EOT,R2,SPCRECREV ;IF SET, AT END OF TAPE
 
;
; NORMAL SPACING FUNCTION EXIT
;
 
	.ENABL	LSB
NORXIT:	MOVZWL	S^#SS$_NORMAL,R0	;SET NORMAL COMPLETION STATUS
	BRB	10$			;
 
;
; SET EOF OF FILE STATUS
;
 
SETEOF:	MOVZWL	#SS$_ENDOFFILE,R0	;SET END OF FILE STATUS
10$:	SUBW3	UCB$W_BOFF(R5),UCB$W_BCNT(R5),- ;CALCULATE TOTAL NUMBER OF FILES
		UCB$W_MT_FC(R5)		;OR RECORDS SKIPPED OVER
	BRW	FUNCXT			;
	.DSABL	LSB
	.PAGE
	.SBTTL	READ DATA FORWARD AND WRITECHECK DATA FORWARD FUNCTIONS
;
; READ DATA FORWARD AND WRITECHECK DATA FORWARD FUNCTIONS
;
 
WRITECHECK:				;WRITE CHECK FORWARD
	BICW	#IO$M_DATACHECK,UCB$W_MT_FUNC(R5) ;CLEAR DATA CHECK REQUEST
READDATA:				;READ DATA FORWARD
	REQSCHAN			;REQUEST SECONDARY I/O CHANNEL
	MOVZBL	UCB$B_FEX(R5),R0	;RETRIEVE FUNCTION INDEX
	EXFUNC	20$			;EXECUTE FUNCTION
10$:	BBC	#IO$V_DATACHECK,UCB$W_MT_FUNC(R5),50$ ;IF CLR, NO DATA CHECK
	RELSCHAN			;RELEASE SECONDARY I/O CHANNEL
	EXFUNC	DOUBLE,F_SPCRECREV	;SPACE RECORD REVERSE
	REQSCHAN			;REQUEST SECONDARY I/O CHANNEL
	EXFUNC	20$,F_WRITECHECK	;WRITE CHECK DATA
	BRB	50$			;
 
;
; FUNCTION ENDED IN AN ERROR
;
; THE ERROR COULD BE A NONFATAL CONTROLLER OR DRIVE ERROR. FATAL ERRORS TERMINATE
; THE FUNCTION IN THE FUNCTION EXECUTOR.
;
; FATAL CONTROLLER ERRORS ARE:
;
;	ERCONF	= ERROR CONFIRMATION.
;	ISTO	= INTERFACE SEQUENCE TIMEOUT.
;	PGE	= PROGRAMMING ERROR.
;	NED	= NONEXISTENT DRIVE.
;	RDTO	= READ DATA TIMEOUT.
;
; FATAL DRIVE ERRORS ARE:
;
;	ILF	= ILLEGAL FUNCTION.
;	ILR	= ILLEGAL REGISTER.
;	NEF	= NONEXECUTABLE FUNCTION.
;	RMR	= REGISTER MODIFY REFUSE.
;	UNS	= UNSAFE.
;
; IGNORED DRIVE ERRORS ARE:
;
;	DPAR	= DATA BUS PARITY.
;
; NOTE THAT IT IS ASSUMED THAT MASSBUS EXCEPTION (MBEXC) WILL OCCUR ONLY IN
; COMBINATION WITH ANOTHER DRIVE OR CONTROLLER ERROR.
;
 
20$:	BITL	#MBA$M_SR_DLT!-		;DATA LATE OR,
		MBA$M_SR_INVMAP!-	;INVALID MAP REGISTER OR,
		MBA$M_SR_MAPPE!-	;MAP PARITY ERROR OR,
		MBA$M_SR_MCPE!-		;MASSBUS CONTROL PARITY ERROR OR,
		MBA$M_SR_MDPE!-		;MASSBUS DATA PARITY ERROR OR,
		MBA$M_SR_MXF!-		;MISSED TRANSFER OR,
		MBA$M_SR_RDS,R1		;READ DATA SUBSTITUTE?
	BNEQ	70$			;IF NEQ YES
	BBS	#MT_DS_V_TM,R2,30$	;IF SET, TAPE MARK DETECTED
	BITW	#MBA$M_SR_WCKLWR!-	;WRITE CHECK LOWER BYTE OR,
		MBA$M_SR_WCKUPR,R1	;WRITE CHECK UPPER BYTE?
	BNEQ	70$			;IF NEQ YES
30$:	BITW	#MT_ER_M_CPAR!-		;CONTROL BUS PARITY ERROR OR,
		MT_ER_M_DTE!-		;DRIVE TIMING ERROR OR,
		MT_ER_M_FMT!-		;FORMAT ERROR OR,
		MT_ER_M_INC!-		;INCORRECTABLE ERROR (PE) OR,
		MT_ER_M_LRC!-		;LONGITUDINAL PARITY ERROR (NRZI) OR,
		MT_ER_M_NSG!-		;NONSTANDARD GAP OR,
		MT_ER_M_OPI!-		;OPERATION INCOMPLETE OR,
		MT_ER_M_PEF!-		;FORMAT ERROR (PE) OR,
		MT_ER_M_VPE,R0		;VERTICLE PARITY ERROR (NRZI)?
	BNEQ	70$			;IF NEQ YES
	BBS	#MT_DS_V_PES,R2,40$	;IF SET, PHASE ENCODED TAPE
	BITW	#MT_ER_M_CRC!MT_ER_M_ITM,R0 ;CRC OR INVALID TAPE MARK?
	BNEQ	70$			;IF NEQ YES
 
;
; FRAME COUNT ERROR
;
; IF THE RECORD CONTAINED MORE BYTES THAN THE SPECIFIED BUFFER, THEN A DATA OVERRUN
; ERROR IS RETURNED. ELSE A CHECK IS MADE FOR END OF FILE AND IMPLICIT WRITECHECK.
;
 
40$:	MOVZWL	#SS$_DATAOVERUN,R0	;SET DATA OVER RUN STATUS
	CMPW	UCB$W_MT_FC(R5),UCB$W_BCNT(R5) ;DATA OVER RUN?
	BGTRU	60$			;IF GTR YES
	MOVZWL	#SS$_ENDOFFILE,R0	;ASSUME END OF FILE
	BBS	#MT_DS_V_TM,R2,60$	;IF SET, TAPE MARK ENCOUNTERED
	CMPB	#CDF_READDATA,UCB$B_CEX(R5) ;LAST FUNCTION READ DATA?
	BEQL	10$			;IF EQL YES
50$:	MOVZWL	S^#SS$_NORMAL,R0	;SET NORMAL COMPLETION STATUS
60$:	INCL	UCB$L_MT_RECORD(R5)	;INCREMENT RECORD POSITION
	BRW	FUNCXT			;
 
;
; RECOVERABLE CONTROLLER OR DRIVE ERROR
;
; A CHECK IS MADE TO DETERMINE IF ANY RETRIES REMAIN. IF THE NUMBER OF RETRIES IS
; EXHAUSTED, THEN AN ERROR IS RETURNED. ELSE RECOVERY IS ATTEMPTED. THE METHOD USED
; DEPENDS ON THE PREVIOUS NUMBER OF RETRIES.
;
; IF THE PREVIOUSLY ATTEMPTED RETRIES HAVE EXCEEDED A THRESHOLD, THEN THE TAPE IS
; BACKSPACED THE ERROR BACKSPACE COUNT, FORWARD SPACED THAT NUMBER MINUS ONE, AND
; THE OPERATION IS REPEATED.
;
; IF THE PREVIOULY ATTEMPTED RETRIES HAVE NOT EXCEEDED THE THRESHOLD, THEN THE TAPE
; IS BACKSPACED ONE RECORD AND THE OPERATION IS RETRIED.
;
 
70$:	TESTR	120$			;TEST REMAINING RETRIES AND RELEASE CHANNEL
	CMPB	#THRESHOLD,UCB$B_ERTCNT(R5) ;TIME TO USE ALTERNATE RECOVERY?
	BLEQU	110$			;IF LEQU NO
	MNEGW	#ERR_SPACING,UCB$W_MT_SPACNT(R5) ;SET ERROR RECORD SPACING
	CMPL	#ERR_SPACING,UCB$L_MT_RECORD(R5) ;ENOUGH RECORDS WRITTEN ON TAPE?
	BLEQU	80$			;IF LEQU YES
	EXFUNC	DOUBLE,F_REWIND		;REWIND TAPE
	MNEGW	UCB$L_MT_RECORD(R5),UCB$W_MT_FORCNT(R5) ;SET PROPER RECORD COUNT
	BRB	90$			;
80$:	EXFUNC	DOUBLE,F_SPCRECREV	;SPACE RECORDS REVERSE
	MNEGW	#ERR_SPACING-1,UCB$W_MT_FORCNT(R5) ;SET FORWARD SPACING COUNT
90$:	MNEGW	#1,UCB$W_MT_SPACNT(R5)	;RESET SPACE COUNT FOR ONE RECORD
100$:	EXFUNC	DOUBLE,F_SPCRECFOR	;SPACE RECORD FORWARD
	INCW	UCB$W_MT_FORCNT(R5)	;ANY MORE RECORDS TO SPACE OVER?
	BLSS	100$			;IF LSS YES
	BRB	120$			;
110$:	EXFUNC	DOUBLE,F_SPCRECREV	;SPACE RECORD REVERSE
	EXFUNC	DOUBLE,F_SPCRECFOR	;SPACE RECORD FORWARD
120$:	BRW	READDATA		;
	.PAGE
	.SBTTL	READ DATA REVERSE AND WRITECHECK DATA REVERSE FUNCTIONS
;
; READ DATA REVERSE AND WRITECHECK DATA REVERSE FUNCTIONS
;
 
WRITECHECKR:				;WRITE CHECK REVERSE
	BICW	#IO$M_DATACHECK,UCB$W_MT_FUNC(R5) ;CLEAR DATA CHECK REQUEST
READDATAR:				;READ DATA REVERSE
	REQSCHAN			;REQUEST SECONDARY I/O CHANNEL
	MOVZBL	UCB$B_FEX(R5),R0	;RETRIEVE FUNCTION INDEX
	EXFUNC	20$			;EXECUTE FUNCTION
10$:	BBC	#IO$V_DATACHECK,UCB$W_MT_FUNC(R5),50$ ;IF CLR, NO DATA CHECK
	RELSCHAN			;RELEASE SECONDARY I/O CHANNEL
	EXFUNC	DOUBLE,F_SPCRECFOR	;SPACE RECORD FORWARD
	REQSCHAN			;REQUEST SECONDARY I/O CHANNEL
	EXFUNC	20$,F_WRITECHECKR	;WRITE CHECK DATA REVERSE
	BRB	50$			;
 
;
; FUNCTION ENDED IN AN ERROR
;
; THE ERROR COULD BE A NONFATAL CONTROLLER OR DRIVE ERROR. FATAL ERRORS TERMINATE
; THE FUNCTION IN THE FUNCTION EXECUTOR.
;
; FATAL CONTROLLER ERRORS ARE:
;
;	ERCONF	= ERROR CONFIRMATION.
;	ISTO	= INTERFACE SEQUENCE TIMEOUT.
;	PGE	= PROGRAMMING ERROR.
;	NED	= NONEXISTENT DRIVE.
;	RDTO	= READ DATA TIMEOUT.
;
; FATAL DRIVE ERRORS ARE:
;
;	ILF	= ILLEGAL FUNCTION.
;	ILR	= ILLEGAL REGISTER.
;	RMR	= REGISTER MODIFY REFUSE.
;	UNS	= UNSAFE.
;
; IGNORED DRIVE ERRORS ARE:
;
;	DPAR	= DATA BUS PARITY.
;
; NOTE THAT IT IS ASSUMED THAT MASSBUS EXCEPTION (MBEXC) WILL OCCUR ONLY IN
; COMBINATION WITH ANOTHER DRIVE OR CONTROLLER ERROR.
;
 
20$:	BITL	#MBA$M_SR_DLT!-		;DATA LATE OR,
		MBA$M_SR_INVMAP!-	;INVALID MAP REGISTER OR,
		MBA$M_SR_MAPPE!-	;MAP PARITY ERROR OR,
		MBA$M_SR_MCPE!-		;MASSBUS CONTROL PARITY ERROR OR,
		MBA$M_SR_MDPE!-		;MASSBUS DATA PARITY ERROR OR,
		MBA$M_SR_MXF!-		;MISSED TRANSFER OR,
		MBA$M_SR_RDS,R1		;READ DATA SUBSTITUTE OR,
	BNEQ	70$			;IF NEQ YES
	BBS	#MT_DS_V_TM,R2,30$	;IF SET, TAPE MARK DETECTED
	BITW	#MBA$M_SR_WCKLWR!-	;WRITE CHECK LOWER BYTE OR,
		MBA$M_SR_WCKUPR,R1	;WRITE CHECK UPPER BYTE?
	BNEQ	70$			;IF NEQ YES
30$:	BITW	#MT_ER_M_CPAR!-		;CONTROL BUS PARITY ERROR OR,
		MT_ER_M_DTE!-		;DRIVE TIMING ERROR OR,
		MT_ER_M_FMT!-		;FORMAT ERROR OR,
		MT_ER_M_INC!-		;INCORRECTABLE ERROR (PE) OR,
		MT_ER_M_LRC!-		;LONGITUDINAL PARITY ERROR (NRZI) OR,
		MT_ER_M_NSG!-		;NONSTANDARD GAP OR,
		MT_ER_M_OPI!-		;OPERATION INCOMPLETE OR,
		MT_ER_M_PEF!-		;FORMAT ERROR (PE) OR,
		MT_ER_M_VPE,R0		;VERTICLE PARITY ERROR (NRZI)?
	BNEQ	70$			;IF NEQ YES
	BBS	#MT_DS_V_PES,R2,40$	;IF SET, PHASE ENCODED TAPE
	BITW	#MT_ER_M_CRC!MT_ER_M_ITM,R0 ;CRC OR INVALID TAPE MARK?
	BNEQ	70$			;IF NEQ YES
 
;
; FRAME COUNT OR NONEXECUTABLE FUNCTION
;
; IF THE RECORD CONTAINED MORE BYTES THAN THE SPECIFIED BUFFER, THEN A DATA OVERRUN
; IS RETURNED. ELSE A CHECK IS MADE FOR END OF FILE, BEGINNING OF TAPE, AND
; IMPLICIT WRITECHECK.
;
 
40$:	MOVZWL	#SS$_DATAOVERUN,R0	;SET DATA OVER RUN STATUS
	CMPW	UCB$W_MT_FC(R5),UCB$W_BCNT(R5) ;DATA OVER RUN?
	BGTRU	60$			;IF GTR YES
	MOVZWL	#SS$_ENDOFFILE,R0	;SET END OF FILE STATUS
	BBS	#MT_DS_V_TM,R2,60$	;IF SET, TAPE MARK ENCOUNTERED
	BBS	#MT_DS_V_BOT,R2,60$	;IF SET, BEGINNING OF TAPE
	CMPB	#CDF_READDATAR,UCB$B_CEX(R5) ;LAST FUNCTION READ DATA?
	BEQL	10$			;IF EQL YES
50$:	MOVZWL	S^#SS$_NORMAL,R0	;SET NORMAL COMPLETION STATUS
60$:	DECL	UCB$L_MT_RECORD(R5)	;DECREMENT TAPE POSITION
	BRW	FUNCXT			;
 
;
; FUNCTION ENDED IN A RETRIABLE ERROR
;
 
70$:	TESTR	130$			;TEST FOR RETRIES AND RELEASE CHANNEL
	ADDW	UCB$W_BCNT(R5),UCB$W_BOFF(R5) ;CALCULATE CORRECT BUFFER ADDRESS
	SUBW	UCB$W_MT_FC(R5),UCB$W_BOFF(R5) ;
	MOVW	UCB$W_MT_FC(R5),UCB$W_BCNT(R5) ;SET BYTE COUNT TO ACTUAL RECORD SIZE
	CMPB	#THRESHOLD,UCB$B_ERTCNT(R5) ;TIME TO USE ALTERNATE RECOVERY?
	BLEQU	90$			;IF LEQU NO
	MNEGW	#ERR_SPACING,UCB$W_MT_FORCNT(R5) ;SET FORWARD SPACING COUNT
80$:	EXFUNC	DOUBLE,F_SPCRECFOR	;SPACE RECORD FORWARD
	INCW	UCB$W_MT_FORCNT(R5)	;ANY MORE RECORDS TO SPACE?
	BLSS	80$			;IF LSS YES
	MNEGW	#ERR_SPACING,UCB$W_MT_SPACNT(R5) ;SET REVERSE SPACE COUNT
	EXFUNC	DOUBLE,F_SPCRECREV	;SPACE RECORDS REVERSE
	MNEGW	#1,UCB$W_MT_SPACNT(R5)	;RESET SPACE COUNT FOR ONE RECORD
90$:	CMPB	#CDF_WRITECHECKR,UCB$B_CEX(R5) ;WRITE CHECK REVERSE?
	BEQL	120$			;IF EQL YES
	REQSCHAN			;REQUEST SECONDARY CHANNEL
	EXFUNC	100$,F_READDATA		;READ DATA FORWARD
100$:	BITL	#MBA$M_SR_DLT!-		;DATA LATE OR,
		MBA$M_SR_INVMAP!-	;INVALID MAP REGISTER OR,
		MBA$M_SR_MAPPE!-	;MAP PARITY ERROR OR,
		MBA$M_SR_MCPE!-		;MASSBUS CONTROL PARITY ERROR OR,
		MBA$M_SR_MDPE!-		;MASSBUS DATA PARITY ERROR OR,
		MBA$M_SR_MXF!-		;MISSED TRANSFER OR,
		MBA$M_SR_NED!-		;NONEXISTENT DISK OR,
		MBA$M_SR_RDS,R1		;READ DATA SUBSTITUTE.
	BNEQ	110$			;IF NEQ YES
	BITW	#MT_ER_M_CPAR!-		;CONTROL BUS PARITY ERRROR, OR
		MT_ER_M_DTE!-		;DRIVE TIMING ERROR ,OR
		MT_ER_M_FCE!-		;FRAME COUNT ERROR OR,
		MT_ER_M_FMT!-		;FORMAT ERROR OR,
		MT_ER_M_ITM!-		;INVALID TAPE MARK OR,
		MT_ER_M_NSG!-		;NONSTANDARD GAP OR,
		MT_ER_M_OPI,R0		;OPERATION INCOMPLETE.
	BNEQ	110$			;IF NEQ YES
	RELSCHAN			;RELEASE SECONDARY I/O CHANNEL
	EXFUNC	DOUBLE,F_SPCRECREV	;SPACE RECORD REVERSE
	REQSCHAN			;REQUEST SECONDARY I/O CHANNEL
	EXFUNC	110$,F_READDATA		;READ DATA FORWARD
	RELSCHAN			;RELEASE SECONDARY I/O CHANNEL
	EXFUNC	DOUBLE,F_SPCRECREV	;SPACE RECORD REVERSE
	BRW	10$			;
110$:	INCB	UCB$B_ERTCNT(R5)	;BIAS ERROR RETRY COUNT
	TESTR	120$			;TEST FOR TAPE MOVEMENT
	BRB	130$			;
120$:	EXFUNC	DOUBLE,F_SPCRECFOR	;SPACE RECORD FORWARD
130$:	BRW	READDATAR		;
	.PAGE
	.SBTTL	WRITE DATA FORWARD FUNCTION
;
; WRITE DATA FORWARD FUNCTION
;
 
WRITEDATA:				;WRITE DATA FORWARD
	REQSCHAN			;REQUEST SECONDARY CHANNEL
	EXFUNC	20$,F_WRITEDATA		;EXECUTE FUNCTION
	BBC	#IO$V_DATACHECK,UCB$W_MT_FUNC(R5),10$ ;IF CLR, NO DATA CHECK
	RELSCHAN			;RELEASE SECONDARY CHANNEL
	EXFUNC	DOUBLE,F_SPCRECREV	;SPACE RECORD REVERSE
	REQSCHAN			;REQUEST SECONDARY CHANNEL
	EXFUNC	50$,F_WRITECHECK	;WRITE CHECK DATA
10$:	MOVW	UCB$W_BCNT(R5),UCB$W_MT_FC(R5) ;SET TRANSFER BYTE COUNT
	INCL	UCB$L_MT_RECORD(R5)	;INCREMENT TAPE POSITION
	MOVZWL	S^#SS$_NORMAL,R0	;SET NORMAL COMPLETION STATUS
	BRW	FUNCXT			;
 
;
; WRITE FUNCTION ENDED IN AN ERROR
;
; THE ERROR COULD BE A NONFATAL CONTROLLER OR DRIVE ERROR. FATAL ERRORS TERMINATE
; THE FUNCTION IN THE FUNCTION EXECUTOR.
;
; FATAL CONTROLLER ERRORS ARE:
;
;	ERCONF	= ERROR CONFIRMATION.
;	ISTO	= INTERFACE SEQUENCE TIMEOUT.
;	PGE	= PROGRAMMING ERROR.
;	NED	= NONEXISTENT DRIVE.
;	RDTO	= READ DATA TIMEOUT.
;
; FATAL DRIVE ERRORS ARE:
;
;	ILF	= ILLEGAL FUNCTION.
;	ILR	= ILLEGAL REGISTER.
;	NEF	= NONEXECUTABLE FUNCTION.
;	RMR	= REGISTER MODIFY REFUSE.
;	UNS	= UNSAFE.
;
; IGNORED DRIVE ERRORS ARE:
;
;	NONE.
;
 
20$:	BISW	#IO$M_DATACHECK,UCB$W_MT_FUNC(R5) ;FORCE DATA CHECK
	ADDW	UCB$W_BCNT(R5),UCB$W_MT_FC(R5) ;CALCULATE ACTUAL BYTES TRANSFERED
	TESTR	30$			;TEST REMAINING RETRIES AND RELEASE CHANNEL
	EXFUNC	DOUBLE,F_SPCRECREV	;SPACE RECORD REVERSE
30$:	BBS	#IO$V_INHEXTGAP,UCB$W_MT_FUNC(R5),40$ ;IF SET, NO EXTENDED GAP
	EXFUNC	DOUBLE,F_ERASE		;ERASE TAPE
40$:	BRB	WRITEDATA		;
 
;
; WRITECHECK FUNCTION ENDED IN ERROR
;
; THE WRITECHECK ERROR IS NOT COUNTED AGAINST THE RETRY COUNT, BUT RATHER THE
; TAPE IS REPOSITIONED AND THE WRITE IS RETRIED.
;
 
50$:	ADDW	UCB$W_BCNT(R5),UCB$W_MT_FC(R5) ;CALCULATE TRANSFERED BYTE COUNT
	INCB	UCB$B_ERTCNT(R5)	;BIAS ERROR RETRY COUNT
	TESTR	WRITEDATA		;TEST REMAINING RETRIES AND RELEASE CHANNEL
	EXFUNC	DOUBLE,F_SPCRECREV	;SPACE RECORD REVERSE
	BRB	WRITEDATA		;
	.PAGE
	.SBTTL	CHECK FOR FATAL OR RETRIABLE SPACING ERROR
;
; CHECK_ERROR - CHECK FOR FATAL OR RETRIABLE SPACING ERROR
;
; THIS ROUTINE IS CALLED FROM THE SPACE FILE FORWARD, SPACE RECORD FORWARD, SPACE
; FILE REVERSE, AND SPACE RECORD REVERSE FUNCTION ROUTINES TO TEST WHETHER A
; SPACING ERROR IS FATAL AND WHETHER ANY RETRIES REMAIN.
;
; INPUTS:
;
;	R0 = DRIVE ERROR REGISTER.
;	R1 = MBA STATUS REGISTER.
;	R2 = DRIVE STATUS REGISTER.
;
;	UCB$B_CEX(R5) = FUNCTION INDEX OF LAST FUNCTION EXECUTED.
;	UCB$B_ERTCNT(R5) = NUMBER OF ERROR RETRIES REMAINING.
;	UCB$W_BCNT(R5) = ORIGINAL SPACING COUNT.
;	UCB$W_BOFF(R5) = REMAINING SPACING COUNT.
;
; OUTPUTS:
;
;	IF ONLY A FRAME COUNT ERROR OCCURED, OR THE FUNCTION WAS A REVERSE DIRECTION
;	FUNCTION AND A CONTROL BUS PARITY ERROR DID NOT OCCUR, THEN AN IMMEDIATE
;	RETURN TO THE CALLER IS EXECUTED. ELSE THE REMAINING RETRY COUNT IS DE-
;	CREMENTED, AND IF THE RESULT IS ZERO, THEN THE FUNCTION IS TERMINATED VIA
;	THE DOUBLE ERROR EXIT. ELSE THE FUNCTION IS REDISPATCHED.
;
 
CHECK_ERROR:				;
	POPL	R1			;REMOVE RETURN ADDRESS FROM STACK
	BITW	#^C<MT_ER_M_FCE>,R0	;RETRIABLE OR FATAL ERROR?
	BEQL	20$			;IF EQL NO
 
;
; RETRIABLE OR FATAL DRIVE ERROR
;
;	CPAR	= CONTROL BUS PARITY ERROR.
;	NEF	= NONEXECUTABLE FUNCTION.
;	OPI	= OPERATION INCOMPLETE.
;
 
	BBS	#MT_ER_V_CPAR,R0,40$	;IF SET, CONTROL BUS PARITY ERROR
 
;
; ERROR WAS EITHER A NONEXECUTABLE FUNCTION OR OPERATION INCOMPLETE
;
 
	CMPB	#CDF_SPCFILREV,UCB$B_CEX(R5) ;SPACE FILE REVERSE?
	BEQL	10$			;IF EQL YES
	CMPB	#CDF_SPCRECREV,UCB$B_CEX(R5) ;SPACE RECORD REVERSE?
	BNEQ	30$			;IF NEQ NO
10$:	BBC	#MT_DS_V_BOT,R2,30$	;IF CLR, NOT AT BEGINNING OF TAPE
20$:	JMP	(R1)			;
 
;
; FORCE FATAL ERROR ON NONEXECUTABLE FUNCTION OR OPERATION INCOMPLETE FOR A FORWARD
; DIRECTION FUNCTION, OR A REVERSE DIRECTION FUNCTION THAT DID NOT END UP AT BEGINNING
; OF TAPE.
;
 
30$:	MOVB	#1,UCB$B_ERTCNT(R5)	;SET RETRY COUNT TO ONE
 
;
; ERROR WAS A CONTROL BUS PARITY ERROR OR A NONEXECUTABLE FUNCTION OR OPERATION
; INCOMPLETE IN COMBINATION WITH A REVERSE DIRECTION FUNCTION
;
 
40$:	SUBW3	UCB$W_BOFF(R5),UCB$W_BCNT(R5),- ;CALCULATE TOTAL SPACE COUNT
		UCB$W_MT_FC(R5)		;
	BSBW	ERL$DEVICERR		;LOG DEVICE ERROR
	DECB	UCB$B_ERTCNT(R5)	;ANY RETRIES REMAINING?
	BEQL	DOUBLE			;IF EQL NO
	BRW	FDISPATCH		;
	.PAGE
	.SBTTL	TEST FOR REMAINING RETRIES
;
; TESTR - TEST FOR REMAINING RETRIES
;
; THIS ROUTINE IS CALLED FROM THE READ DATA, READ DATA REVERSE, WRITECHECK,
; WRITECHECK REVERSE, WRITE DATA, AND WRITE TAPE MARK FUNCTION ROUTINES TO
; TEST FOR REMAINING RETRIES.
;
; INPUTS:
;
;	R0 = DRIVE ERROR REGISTER.
;	R1 = MBA STATUS REGISTER.
;	R2 = DRIVE STATUS REGISTER.
;
;	UCB$B_CEX(R5) = FUNCTION INDEX OF LAST FUNCTION EXECUTED.
;	UCB$B_ERTCNT(R5) = NUMBER OF ERROR RETRIES REMAINING.
;	UCB$L_MT_RECORD(R5) = CURRENT TAPE POSITION BEFORE FUNCTION EXECUTION.
;	UCB$W_MT_DS(R5) = SAVED DRIVE STATUS REGISTER.
;	UCB$W_MT_FUNC(R5) = ORIGINAL FUNCTION WORD.
;	UCB$W_MT_FC(R5) = NUMBER OF BYTES THAT WERE READ OR WRITTEN TO/FROM TAPE.
;
;	@(SP) = SIGNED BRANCH DISPLACEMENT TO CONDITIONAL EXIT POINT.
;
; OUTPUTS:
;
;	THE REMAINING RETRY COUNT IS DECREMENTED AND IF THE RESULT IS ZERO, THEN
;	THE FUNCTION IS TERMINATED WITH AN ERROR VIA THE FATAL ERROR EXIT AFTER
;	HAVING ADJUSTED THE CURRENT TAPE POSITION. ELSE THE SECONDARY CHANNEL IS
;	RELEASED AND THE CONDITIONAL BRANCH EXIT IS TAKEN IF NO TAPE MOVEMENT
;	OCCURED.
;
 
TESTR:					;
	BSBW	ERL$DEVICERR		;LOG DEVICE ERROR
	DECB	UCB$B_ERTCNT(R5)	;ANY RETRIES REMAINING?
	BEQL	20$			;IF EQL NO
	RELSCHAN			;RELEASE SECONDARY I/O CHANNEL
	CMPW	#MIN_RECORD,UCB$W_MT_FC(R5) ;ANY TAPE MOVEMENT?
	BLEQU	10$			;IF LEQU YES
	BBS	#MT_DS_V_TM,UCB$W_MT_DS(R5),10$ ;IF SET, TAPE MARK DETECTED
	CVTWL	@(SP),-(SP)		;GET DISPLACEMENT VALUE
	ADDL	(SP)+,(SP)		;CALCULATE BRANCH ADDRESS
10$:	ADDL	#2,(SP)			;
	RSB				;
 
;
; ERROR RETRIES EXHAUSTED
;
; CHECK FOR TAPE MOVEMENT, ADJUST TAPE POSITION AS APPROPRIATE, AND TAKE FATAL
; ERROR EXIT.
;
 
20$:	TSTL	(SP)+			;REMOVE RETURN FROM STACK
	BBS	#MT_DS_V_TM,UCB$W_MT_DS(R5),30$ ;IF SET, TAPE MARK DETECTED
	CMPW	#MIN_RECORD,UCB$W_MT_FC(R5) ;ANY TAPE MOVEMENT?
	BGTRU	40$			;IF GTRU NO
30$:	DECL	UCB$L_MT_RECORD(R5)	;ASSUME REVERSE TAPE OPERATION
	CMPB	#CDF_READDATAR,UCB$B_CEX(R5) ;READ DATA REVERSE?
	BEQL	40$			;IF EQL YES
	CMPB	#CDF_WRITECHECKR,UCB$B_CEX(R5) ;WRITE CHECK REVERSE?
	BEQL	40$			;IF EQL YES
	ADDL	#2,UCB$L_MT_RECORD(R5)	;ADJUST FOR FORWARD TAPE OPERATION
40$:	BRW	FATALERR		;
	.PAGE
	.SBTTL	TAPE POSITION LOST
;
; TAPE POSITION LOST
;
 
LOSTPOS:				;
	BISW	#<MT$M_LOST@-16>,UCB$L_DEVDEPEND+2(R5) ;SET TAPE POSITION LOST
 
;
; TEST FOR RETRY
;
 
RETRY:					;TEST FOR RETRY
	BSBW	ERL$DEVICERR		;LOG DEVICE ERROR
	DECB	UCB$B_ERTCNT(R5)	;ANY RETRIES REMAINING?
	BEQL	FATALERR		;IF EQL NO
	BRW	FDISPATCH		;
 
;
; DOUBLE ERROR WHILE TRYING TO REPOSITION TAPE - TAPE POSITION LOST
;
 
DOUBLE:					;
	BISW	#<MT$M_LOST@-16>,UCB$L_DEVDEPEND+2(R5) ;SET LOST POSITION STATUS
 
;
; FATAL CONTROLLER/DRIVE ERROR, ERROR RETRY COUNT EXHAUSTED, ERROR RETRY
; INHIBITED, OR FINAL OFFSET TRIED
;
 
FATALERR:				;FATAL ERROR - SET STATUS
	MOVL	R0,R3			;COPY ERROR STATUS REGISTER
	MOVZWL	#SS$_MEDOFL,R0		;SET MEDIUM OFFLINE STATUS
	BBC	#MT_DS_V_MOL,R2,FUNCXT	;IF CLR, MEDIUM OFFLINE
	BBC	#MT_ER_V_NEF,R3,10$	;IF CLR, EXECUTABLE FUNCTION
	MOVZWL	#SS$_WRITLCK,R0		;SET WRITE LOCK ERROR STATUS
	BBS	#MT_DS_V_WRL,R2,FUNCXT	;IF SET, DRIVE HARDWARE WRITE LOCKED
10$:	MOVZWL	#SS$_UNSAFE,R0		;SET DRIVE UNSAFE STATUS
	BBS	#MT_ER_V_UNS,R3,FUNCXT	;IF SET, DRIVE UNSAFE
	MOVZWL	#SS$_OPINCOMPL,R0	;SET OPERATION INCOMPLETE STATUS
	BBS	#MT_ER_V_OPI,R3,FUNCXT	;IF SET, OPERATION INCOMPLETE
	MOVZWL	#SS$_FORMAT,R0		;SET FORMAT ERROR STATUS
	BBS	#MT_ER_V_FMT,R3,FUNCXT	;IF SET, FORMAT ERROR
	MOVZWL	#SS$_DRVERR,R0		;SET DRIVE ERROR STATUS
	BITW	#MT_ER_M_DTE!-		;DRIVE TIMING ERROR OR,
		MT_ER_M_ILF!-		;ILLEGAL FUNCTION OR,
		MT_ER_M_ILR!-		;ILLEGAL REGISTER OR,
		MT_ER_M_NEF!-		;NON-EXECUTABLE FUNCTION OR,
		MT_ER_M_RMR,R3		;REGISTER MODIFY REFUSE
	BNEQ	FUNCXT			;IF NEQ YES
	MOVZWL	#SS$_PARITY,R0		;SET PARITY ERROR STATUS
	BITW	#MT_ER_M_CRC!-		;CRC ERROR OR,
		MT_ER_M_CPAR!-		;CONTROL BUS PARITY ERROR OR,
		MT_ER_M_COR!-		;CORRECTABLE DATA ERROR (PE) OR,
		MT_ER_M_CS!-		;CORRECTABLE SKEW (PE) OR,
		MT_ER_M_DPAR!-		;DATA PARITY ERROR OR,
		MT_ER_M_INC!-		;INCORRECTABLE ERROR (PE) OR,
		MT_ER_M_ITM!-		;INVALID TAPE MARK OR,
		MT_ER_M_LRC!-		;LONGITUDINAL PARITY ERROR (NRZI) OR,
		MT_ER_M_NSG!-		;NONSTANDARD GAP OR,
		MT_ER_M_PEF!-		;FORMAT ERROR (PE) OR,
		MT_ER_M_VPE,R3		;VERTICLE PARITY ERROR (NRZI)?
	BNEQ	FUNCXT			;IF NEQ YES
	BITL	#MBA$M_SR_MAPPE!-	;MAP PARITY ERROR OR,
		MBA$M_SR_MCPE!-		;MASSBUS CONTROL PARITY ERROR OR,
		MBA$M_SR_MDPE!-		;MASSBUS DATA PARITY ERROR OR,
		MBA$M_SR_RDS,R1		;READ DATA SUBSTITUTE?
	BNEQ	FUNCXT			;IF NEQ YES
	MOVZWL	#SS$_DATACHECK,R0	;SET DATA CHECK ERROR STATUS
	BITW	#MBA$M_SR_WCKLWR!-	;WRITE CHECK ERROR LOWER BYTE OR,
		MBA$M_SR_WCKUPR,R1	;WRITE CHECK ERROR UPPER BYTE?
	BNEQ	FUNCXT			;IF NEQ YES
	MOVZWL	#SS$_NONEXDRV,R0	;SET NONEXISTENT DRIVE STATUS
	BBS	#MBA$V_SR_NED,R1,FUNCXT	;IF SET, NONEXISTENT DRIVE
	MOVZWL	#SS$_CTRLERR,R0		;SET CONTROLLER ERROR STATUS
	.PAGE
	.SBTTL	FUNCTION COMPLETION COMMON EXIT
;
; FUNCTION COMPLETION COMMON EXIT
;
; THIS ROUTINE IS JUMPED TO AT THE END OF ALL MAGTAPE OPERATIONS.
;
; INPUTS:
;
;	R0 = FINAL I/O COMPLETION STATUS.
;	R2 = DRIVE STATUS REGISTER.
;
;	UCB$B_FEX(R5) = FUNCTION EXECUTION INDEX.
;
; OUTPUTS:
;
;	THE FINAL DRIVE STATUS IS TESTED AND THE FOLLOWING STATUS BITS ARE SET
;	IN THE SECOND WORD OF THE DEVICE DEPENDENT CHARACTERISTICS LONGWORD.
;
;		MT$M_BOT = SET IF TAPE IS AT BEGINNING OF TAPE AT END OF FUNCTION.
;		MT$M_EOF = SET IF A VALID TAPE MARK WAS DETECTED DURING THE TAPE
;			OPERATION.
;		MT$M_EOT = SET IF AN END OF TAPE CONDITION WAS PRESENT AT THE END
;			OF THE TAPE OPERATION AND THE FUNCTION WAS A READ DATA
;			FORWARD, WRITECHECK DATA FORWARD, WRITE DATA FORWARD, OR
;			SPACE RECORD FORWARD FUNCTION.
;		MT$M_HWL = SET IF THE SLAVE DRIVE HAS A TAPE MOUNTED THAT DOES NOT
;			CONTAIN A WRITE RING.
;
 
FUNCXT:					;FUNCTION EXIT
	MOVZBL	UCB$B_FEX(R5),R1	;GET FUNCTION DISPATCH INDEX
	BICW	#<MT$M_BOT!-		;CLEAR BEGINNING OF TAPE AND,
		MT$M_EOF!-		;END OF FILE AND,
		MT$M_EOT!-		;END OF TAPE AND,
		MT$M_HWL>@-16,UCB$L_DEVDEPEND+2(R5) ;HARDWARE WRITE LOCK
	BBC	#MT_DS_V_BOT,R2,10$	;IF CLR, NOT AT BEGINNING OF TAPE
	BISW	#<MT$M_BOT@-16>,UCB$L_DEVDEPEND+2(R5) ;SET BEGINNING OF TAPE
	BICW	#<MT$M_LOST@-16>,UCB$L_DEVDEPEND+2(R5) ;CLEAR TAPE POSITION LOST
	CLRL	UCB$L_MT_RECORD(R5)	;CLEAR TAPE POSITION
10$:	BBC	#MT_DS_V_TM,R2,30$	;IF CLR, NO TAPE MARK DETECTED
	BISW	#<MT$M_EOF@-16>,UCB$L_DEVDEPEND+2(R5) ;SET END OF FILE
	CMPB	#CDF_WRITECHECK,R1	;DATA TRANSFER FUNCTION?
	BGTRU	30$			;IF GTRU NO
	CMPB	#CDF_WRITEMARK,R1	;WRITE TAPE MARK FUNCTION?
	BEQL	20$			;IF EQL YES
	CMPB	#CDF_READPRESET,R1	;DATA TRANSFER FUNCTION?
	BLEQU	30$			;IF LEQU NO
20$:	CLRW	UCB$W_MT_FC(R5)		;CLEAR FRAME COUNT
	CMPW	#SS$_DATACHECK,R0	;WRITE CHECK ERROR?
	BNEQ	30$			;IF NEQ NO
	MOVZWL	#SS$_ENDOFFILE,R0	;SET END OF FILE STATUS
30$:	BBC	#MT_DS_V_EOT,R2,50$	;IF CLR, NOT AT END OF TAPE
	CMPB	#CDF_READDATA,R1	;READ DATA FORWARD?
	BEQL	40$			;IF EQL YES
	CMPB	#CDF_SPCRECFOR,R1	;SPACE RECORD FORWARD?
	BEQL	40$			;IF EQL YES
	CMPB	#CDF_WRITECHECK,R1	;WRITE CHECK DATA FORWARD?
	BEQL	40$			;IF EQL YES
	CMPB	#CDF_WRITEDATA,R1	;WRITE DATA?
	BEQL	40$			;IF EQL YES
	CMPB	#CDF_ERASE,R1		;ERASE  TAPE?
	BEQL	40$			;IF EQL YES
	CMPB	#CDF_WRITEMARK,R1	;WRITE TAPE MARK?
	BNEQ	50$			;IF NEQ NO
40$:	BISW	#<MT$M_EOT@-16>,UCB$L_DEVDEPEND+2(R5) ;SET END OF TAPE
	BLBC	R0,50$			;IF LBC ALREADY RETURNING ERROR
	MOVZWL	#SS$_ENDOFTAPE,R0	;SET END OF TAPE STATUS
50$:	BBC	#MT_DS_V_WRL,R2,60$	;IF CLR, NOT HARDWARE WRITE LOCKED
	BISW	#<MT$M_HWL@-16>,UCB$L_DEVDEPEND+2(R5) ;SET HARDWARE WRITE LOCKED
60$:	PUSHL	R0			;SAVE FINAL STATUS
	BSBW	IOC$DIAGBUFILL		;FILL DIAGNOSTIC BUFFER IF PRESENT
	MOVW	UCB$W_MT_FC(R5),2(SP)	;SET BYTES TRANSFERED OR RECORDS/FILES SKIPPED
	BLBS	(SP),80$		;IF LBS SUCCESSFUL COMPLETION
	MOVL	UCB$L_IRP(R5),R4	;GET ADDRESS OF CURRENT I/O PACKET
	BBC	#IRP$V_VIRTUAL,IRP$W_STS(R4),80$ ;IF CLR, NOT VIRTUAL FUNCTION
	MOVL	IRP$L_WIND(R4),R4	;GET ADDRESS OF WINDOW BLOCK
	CLRW	WCB$W_NMAP(R4)		;CLEAR NUMBER OF MAPPING POINTERS
	MOVL	UCB$L_VCB(R5),R4	;GET ADDRESS OF VCB
;	MOVAB	VCB$L_FCBFL(R4),R4	;GET ADDRESS OF BLOCKED I/O LISTHEAD
	MOVL	R4,R3			;SET ADDRESS OF PREVIOUS ENTRY
70$:	MOVL	(R3),R3			;GET ADDRESS OF NEXT ENTRY
	CMPL	R3,R4			;END OF LIST?
	BEQL	80$			;IF EQL YES
	BBC	#IRP$V_VIRTUAL,IRP$W_STS(R3),70$ ;IF CLR, NOT VIRTUAL FUNCTION
	MOVL	4(R3),R3		;RETRIEVE ADDRESS OF PREVIOUS ENTRY
	REMQUE	@(R3),R2		;REMOVE ENTRY FROM DRIVER QUEUE
	INSQUE	(R2),@4(R4)		;INSERT ENTRY IN BLOCKED I/O LIST
	BRB	70$			;
80$:	POPL	R0			;RETRIEVE FINAL STATUS
	MOVL	UCB$L_DEVDEPEND(R5),R1	;SET MAGTAPE STATUS AND CHARACTERISTICS
	REQCOM				;COMPLETE REQUEST
	.PAGE
	.SBTTL	TM03-TE16/TU77 HARDWARE FUNCTION EXECUTION
;
; FEX - TM03-TE16/TU77 HARDWARE FUNCTION EXECUTION
;
; THIS ROUTINE IS CALLED VIA A BSB WITH A BYTE IMMEDIATELY FOLLOWING THAT
; SPECIFIES THE ADDRESS OF AN ERROR ROUTINE. ALL DATA IS ASSUMED TO HAVE BEEN
; SET UP IN THE UCB BEFORE THE CALL. THE APPROPRIATE PARAMETERS ARE LOADED
; INTO DEVICE REGISTERS AND THE FUNCTION IS INITIATED. IF THE FUNCTION IS AN
; IMMEDIATE FUNCTION CONTROL RETURNS IMMEDIATELY. ELSE THE RETURN ADDRESS
; IS STORED IN THE UCB AND A WAITFOR INTERRUPT IS EXECUTED. WHEN THE INTER-
; RUPT OCCURS, CONTROL IS RETURNED TO THE CALLER.
;
; INPUTS:
;
;	R0 = FUNCTION TABLE DISPATCH INDEX.
;	R3 = ADDRESS OF DRIVE CONTROL STATUS REGISTER 1.
;	R4 = ADDRESS OF MBA CONFIGURATION STATUS REGISTER.
;	R5 = DEVICE UNIT UCB ADDRESS.
;
;	00(SP) = RETURN ADDRESS OF CALLER.
;	04(SP) = RETURN ADDRESS OF CALLER'S CALLER.
;
;	IMMEDIATELY FOLLOWING INLINE AT THE CALL SITE IS A BYTE WHICH CONTAINS
;	A BRANCH DESTINATION TO AN ERROR RETRY ROUTINE.
;
; OUTPUTS:
;
;	THERE ARE FOUR EXITS FROM THIS ROUTINE:
;
;	1. SPECIAL CONDITION - THIS EXIT IS TAKEN IF A POWER FAILURE OCCURS
;		OR THE OPERATION TIMES OUT. IT IS A JUMP TO THE APPROPRIATE
;		ERROR ROUTINE.
;
;	2. FATAL ERROR - THIS EXIT IS TAKEN IF A FATAL CONTROLLER OR DRIVE
;		ERROR OCCURS OR IF ANY ERROR OCCURS AND ERROR RETRY IS
;		INHIBITED. IT IS A JUMP TO THE FATAL ERROR EXIT ROUTINE.
;
;	3. RETRIABLE ERROR - THIS EXIT IS TAKEN IF A RETRIABLE CONTROLLER
;		OR DRIVE ERROR OCCURS AND ERROR RETRY IS NOT INHIBITED.
;		IT CONSISTS OF TAKING THE ERROR BRANCH EXIT.
;
;	4. SUCCESSFUL OPERATION - THIS EXIT IS TAKEN IF NO ERROR OCCURS
;		DURING THE OPERATION. IT CONSISTS OF A RETURN INLINE.
;
;	IN ALL CASES IF AN ERROR OCCURS, AN ATTEMPT IS MADE TO LOG THE ERROR.
;
;	IN ALL CASES FINAL DRIVE AND CONTROLLER REGISTERS ARE RETURNED VIA
;	THE GENERAL REGISTERS R0, R1, AND R2, AND THE UCB.
;
;	R0 = DRIVE ERROR REGISTER.
;	R1 = MBA STATUS REGISTER.
;	R2 = DRIVE STATUS REGISTER.
;
;	UCB$W_MT_FC(R5) = FRAME COUNT REGISTER.
;
 
FEX:					;FUNCTION EXECUTOR
	POPL	UCB$L_DPC(R5)		;SAVE DRIVER PC VALUE
	MOVZWL	UCB$W_MT_TC(R5),MT_TC(R3) ;SELECT DRIVE AND SET CHARACTERISTICS
	MOVZBL	#F_DRVCLR!1,MT_CS1(R3)	;CLEAR DRIVE
	MOVB	R0,UCB$B_CEX(R5)	;SAVE CASE INDEX
	CASE	R0,<-			;DISPATCH TO PROPER FUNCTION ROUTINE
		IMMED,-			;NO OPERATION
		POSIT,-			;UNLOAD VOLUME
		POSIT,-			;SPACE FILE FORWARD
		RECAL,-			;REWIND
		IMMED,-			;DRIVE CLEAR
		POSIT,-			;SPACE FILE REVERSE
		POSIT,-			;ERASE TAPE
		POSIT,-			;SPACE RECORD REVERSE
		IMMED,-			;SET TAPE CHARACTERISTICS
		POSIT,-			;SPACE RECORD FORWARD
		XFER,-			;WRITE CHECK FORWARD
		XFER,-			;WRITE DATA FORWARD
		XFER,-			;READ DATA FORWARD
		XFER,-			;WRITECHECK REVERSE
		XFER,-			;WRITE DATA FORWARD
		XFER,-			;READ DATA REVERSE
		RECAL,-			;READ IN PRESET
		IMMED,-			;SENSE CHARACTERISTICS
		>			;
 
;
; POSITIONING FUNCTION EXECUTION
;
;	FUNCTIONS INCLUDE:
;
;		SPACE FILE FORWARD,
;		SPACE FILE REVERSE,
;		ERASE TAPE,
;		SPACE RECORD REVERSE,
;		SPACE RECORD FORWARD,
;		UNLOAD, AND
;		WRITE TAPE MARK.
;
; THE FUNCTION IS INITIATED AND A WAITFOR INTERRUPT IS EXECUTED. WHEN THE INTERRUPT
; OCCURS FINAL DEVICE REGISTERS ARE RETURNED TO THE CALLER.
;
 
POSIT:					;POSITIONING FUNCTION EXECUTION
	DSBINT				;DISABLE ALL INTERRUPTS
	BBS	#UCB$V_POWER,UCB$W_STS(R5),ENBEXT ;IF SET, POWER HAS FAILED
	CVTWL	UCB$W_MT_SPACNT(R5),MT_FC(R3) ;LOAD FRAME COUNT REGISTER
	MOVZBL	FTAB[R0],MT_CS1(R3)	;EXECUTE FUNCTION
	WFIKPCH	RETREG,TIME_OUT[R0]	;WAITFOR INTERRUPT AND KEEP CHANNEL
	BRW	DRVREG			;
 
;
; IMMEDIATE FUNCTION EXECUTION
;
;	FUNCTIONS INCLUDE:
;
;		NO OPERATION, AND
;		DRIVE CLEAR.
;
; THESE FUNCTIONS ARE EXECUTED IMMEDIATELY AND THE FINAL DEVICE REGISTERS
; ARE RETURNED TO THE CALLER.
;
 
IMMED:					;IMMEDIATE FUNCTION EXECUTION
	DSBINT				;DISABLE INTERRUPTS
	BBS	#UCB$V_POWER,UCB$W_STS(R5),ENBEXT ;IF SET, POWER HAS FAILED
	MOVZBL	FTAB[R0],MT_CS1(R3)	;EXECUTE FUNCTION
ENBEXT:					;
	BRW	ENBXIT			;
 
;
; RECALIBRATE FUNCTION EXECUTION
;
;	FUNCTIONS INCLUDE:
;
;		READ IN PRESET, AND
;		REWIND.
;
; THE FUNCTION IS INITIATED AND A WAITFOR INTERRUPT IS EXECUTED. WHEN THE INTERRUPT
; OCCURS A TEST IS MADE TO SEE IF POSITIONING IS STILL IN PROGRESS. IF POSITIONING
; IS STILL IN PROGRESS, THEN ANOTHER WAITFOR INTERRUPT IS EXECUTED. ELSE FINAL DRIVE
; REGISTERS ARE RETURNED TO THE CALLED.
;
 
RECAL:					;RECALIBRATE FUNCTION EXECUTION
	DSBINT				;DISABLE INTERRUPTS
	BBS	#UCB$V_POWER,UCB$W_STS(R5),ENBEXT ;IF SET, POWER HAS FAILED
	MOVZBL	FTAB[R0],MT_CS1(R3)	;EXECUTE FUNCTION
	WFIKPCH	RETREG,#4		;WAITFOR INTERRUPT
	IOFORK				;CREATE FORK PROCESS
	DSBINT				;DISABLE INTERRUPTS FOR SECOND WAIT
	BBS	#UCB$V_POWER,UCB$W_STS(R5),ENBEXT ;IF SET, POWER HAS FAILED
	ASHL	#31-MT_DS_V_PIP,MT_DS(R3),R1 ;POSITIONING IN PROGRESS?
	BGEQ	ENBEXT			;IF GEQ NO
	WFIRLCH	RETREG,#60*5		;WAITFOR FINAL INTERRUPT
	BRB	DRVREG			;
 
;
; TRANSFER FUNCTION EXECUTION
;
;	FUNCTIONS INCLUDE:
;
;		WRITE CHECK,
;		WRITE DATA,
;		READ DATA,
;		READ DATA REVERSE, AND
;		WRITECHECK DATA REVERSE.
;
; THE MAP REGISTERS, BYTE COUNT REGISTER, AND VIRTUAL ADDRESS REGISTERS ARE LOADED.
; THE FUNCTION IS INITIATED AND A WAITFOR INTERRUPT IS EXECUTED. WHEN THE INTERRUPT
; OCCURS FINAL DEVICE REGISTERS ARE RETURNED TO THE CALLER.
;
 
XFER:					;TRANSFER FUNCTION EXECUTION
	MCOML	#0,MBA$L_SR(R4)		;CLEAR MASSBUS ADAPTER ERRORS
	LOADMBA				;LOAD MAP, BYTE COUNT, AND VIRTUAL ADDRESS
	MOVL	MBA$L_BCR(R4),MT_FC(R3)	;LOAD FRAME COUNT REGISTER
	MOVZBL	UCB$B_CEX(R5),R0	;RETRIEVE FUNCTION TABLE INDEX
	CMPB	#CDF_READDATAR,R0	;READ DATA REVERSE?
	BEQL	10$			;IF EQL YES
	CMPB	#CDF_WRITECHECKR,R0	;WRITE CHECK DATA REVERSE?
	BNEQ	20$			;IF NEQ NO
10$:	MOVZWL	UCB$W_BCNT(R5),R1	;GET TRANSFER BYTE COUNT
	DECL	R1			;REDUCE BYTE COUNT BY ONE
	ADDL	R1,MBA$L_VAR(R4)	;CALCULATE ENDING ADDRESS OF BUFFER
20$:	DSBINT				;DISABLE INTERRUPTS
	BBS	#UCB$V_POWER,UCB$W_STS(R5),ENBXIT ;IF SET, POWER FAILED
	MOVZBL	FTAB[R0],MT_CS1(R3)	;INITIATE FUNCTION
	WFIKPCH	RETREG,TIME_OUT[R0]	;WAITFOR INTERRUPT AND KEEP CHANNEL
	MOVL	MBA$L_SR(R4),UCB$L_MT_SR(R5) ;SAVE FINAL CONTROLLER STATUS
	INSV	#MT$K_PE_1600,#MT$V_DENSITY,- ;SET CORRECT DENSITY CODE
		#MT$S_DENSITY,UCB$L_DEVDEPEND(R5) ;
	INSV	#4,#MT_TC_V_DEN,-	;
		#MT_TC_S_DEN,UCB$W_MT_TC(R5) ;
	BITL	#MT_DS_M_PES,MT_DS(R3)	;PHASE ENCODED TAPE?
	BNEQ	DRVREG			;IF NEQ YES
	INSV	#MT$K_NRZI_800,#MT$V_DENSITY,- ;SWITCH TO NRZI 800 BPI
		#MT$S_DENSITY,UCB$L_DEVDEPEND(R5) ;
	INSV	#3,#MT_TC_V_DEN,-	;
		#MT_TC_S_DEN,UCB$W_MT_TC(R5) ;
DRVREG:					;SAVE DRIVE REGISTERS
	CVTLW	MT_FC(R3),UCB$W_MT_FC(R5) ;SAVE FRAME COUNT REGISTER
	CVTLW	MT_ER(R3),UCB$W_MT_ER(R5) ;SAVE ERROR STATUS REGISTER
	CVTLW	MT_DS(R3),UCB$W_MT_DS(R5) ;SAVE DRIVE STATUS REGISTER
	CVTLW	MT_CS1(R3),UCB$W_MT_CS1(R5) ;SAVE DRIVE CONTROL REGISTER
	MOVZBL	#F_DRVCLR!1,MT_CS1(R3)	;CLEAR DRIVE
	IOFORK				;CREATE FORK PROCESS
	BRB	RETREG			;
 
;
; ENABLE INTERRUPTS
;
 
ENBXIT:					;
	CVTLW	MT_ER(R3),UCB$W_MT_ER(R5) ;SAVE ERROR STATUS REGISTER
	CVTLW	MT_DS(R3),UCB$W_MT_DS(R5) ;SAVE DRIVE STATUS REGISTER
	CVTLW	MT_CS1(R3),UCB$W_MT_CS1(R5) ;SAVE DRIVE CONTROL REGISTER
	ENBINT				;ENABLE INTERRUPTS
 
;
; RETURN REGISTERS
;
 
RETREG:					;RETURN FINAL DEVICE REGISTERS
	MOVZWL	UCB$W_MT_ER(R5),R0	;RETRIEVE CONTENTS OF DRIVE ERROR REGISTER
	MOVZBL	UCB$B_CEX(R5),R1	;GET CURRENT FUNCTION INDEX
	BICW	XTAB[R1],R0		;CLEAR DON'T CARE BITS
	MOVL	UCB$L_MT_SR(R5),R1	;RETRIEVE FINAL CONTROLLER STATUS
	MOVZWL	UCB$W_MT_DS(R5),R2	;RETRIEVE CONTENTS OF DRIVE STATUS REGISTER
	BITW	#UCB$M_POWER!-		;POWER FAIL OR DEVICE TIMEOUT?
		UCB$M_TIMOUT,UCB$W_STS(R5) ;
	BNEQ	60$			;IF NEQ YES - SPECIAL CONDITION
	CMPB	#CDF_WRITECHECK,UCB$B_CEX(R5) ;DRIVE RELATED FUNCTION?
	BGTRU	10$			;IF GTRU YES
	CMPB	#CDF_READPRESET,UCB$B_CEX(R5) ;DRIVE RELATED FUNCTION?
	BLEQU	10$			;IF LEQU YES
 
;
; CONTROLLER RELATED FUNCTION
;
 
	BITL	#MBA$M_ERROR,R1		;ANY CONTROLLER ERRORS?
	BEQL	50$			;IF EQL NO
	BBS	#IO$V_INHRETRY,UCB$W_MT_FUNC(R5),80$ ;IF SET, RETRY INHIBITED
	BITL	#MBA$M_SR_ERCONF!-	;ERROR CONFIRMATION OR,
		MBA$M_SR_ISTO!-		;INTERFACE SEQUENCE TIMEOUT OR,
		MBA$M_SR_PGE!-		;PROGRAMMING ERROR OR,
		MBA$M_SR_NED!-		;NONEXISTENT DRIVE, OR
		MBA$M_SR_RDTO,R1	;READ TIMEOUT?
	BNEQ	80$			;IF NEQ YES - FATAL CONTROLLER ERROR
	BITL	#MBA$M_SR_DLT!-		;DATA LATE OR,
		MBA$M_SR_INVMAP!-	;INVALID MAP REGISTER OR,
		MBA$M_SR_MAPPE!-	;MAP REGISTER PARITY ERROR OR,
		MBA$M_SR_MCPE!-		;MASSBUS CONTROL PARITY ERROR OR,
		MBA$M_SR_MDPE!-		;MASSBUS DATA PARITY ERROR OR,
		MBA$M_SR_MXF!-		;MISSED TRANSFER OR,
		MBA$M_SR_RDS!-		;READ DATA SUBSTITUTE OR,
		MBA$M_SR_WCKLWR!-	;WRITE CHECK LOWER BYTE OR,
		MBA$M_SR_WCKUPR,R1	;WRITE CHECK UPPER BYTE?
	BNEQ	20$			;IF NEQ YES - RETRIABLE CONTROLLER ERROR
 
;
; DRIVE RELATED FUNCTION
;
 
10$:	CLRL	R1			;CLEAR CONTENTS OF STATUS REGISTER
	TSTW	R0			;ANY DRIVE ERRORS?
	BEQL	50$			;IF EQL NO
	BBS	#IO$V_INHRETRY,UCB$W_MT_FUNC(R5),80$ ;IF SET, RETRY INHIBITED
20$:	BITW	#MT_ER_M_ILF!-		;ILLEGAL FUNCTION OR,
		MT_ER_M_ILR!-		;ILLEGAL REGISTER OR,
		MT_ER_M_RMR!-		;REGISTER MODIFY REFUSE OR,
		MT_ER_M_UNS,R0		;DRIVE UNSAFE
	BNEQ	80$			;IF NEQ YES - FATAL DRIVE ERROR
	BBC	#MT_ER_V_NEF,R0,40$	;IF CLR, NOT NONEXECUTABLE FUNCTION
	CMPB	#CDF_DRVCLR,UCB$B_CEX(R5) ;DRIVE CLEAR?
	BEQL	30$			;IF EQL YES
	CMPB	#CDF_READDATAR,UCB$B_CEX(R5) ;READ DATA REVERSE?
	BEQL	30$			;IF EQL YES
	CMPB	#CDF_SPCFILREV,UCB$B_CEX(R5) ;SPACE FILE REVERSE?
	BEQL	30$			;IF EQL YES
	CMPB	#CDF_SPCRECREV,UCB$B_CEX(R5) ;SPACE RECORD REVERSE?
	BEQL	30$			;IF EQL YES
	CMPB	#CDF_WRITECHECKR,UCB$B_CEX(R5) ;WRITECHECK REVERSE?
	BNEQ	80$			;IF NEQ NO
30$:	CLRW	UCB$W_MT_FC(R5)		;CLEAR SAVED FRAME COUNT REGISTER
 
;
; RETRIABLE ERROR EXIT
;
 
40$:	CVTWL	@UCB$L_DPC(R5),-(SP)	;GET BRANCH DISPLACEMENT
	ADDL	(SP)+,UCB$L_DPC(R5)	;CALCULATE RETURN ADDRESS - 2
50$:	ADDL	#2,UCB$L_DPC(R5)	;ADJUST TO CORRECT RETURN ADDRESS
	JMP	@UCB$L_DPC(R5)		;RETURN TO DRIVER
 
;
; SPECIAL CONDITION EXIT
;
 
60$:	CMPB	#CDF_WRITECHECK,UCB$B_CEX(R5) ;DRIVE RELATED FUNCTION?
	BGTRU	70$			;IF GTRU YES
	CMPB	#CDF_READPRESET,UCB$B_CEX(R5) ;DRIVE RELATED FUNCTION?
	BLEQU	70$			;IF LEQU YES
	MOVL	#MBA$M_CR_ABORT,MBA$L_CR(R4) ;ABORT CURRENT TRANSFER
70$:	SETIPL	UCB$B_FIPL(R5)		;LOWER IPL TO DEVICE FORK LEVEL
	MOVL	#MBA$M_CR_IE,MBA$L_CR(R4) ;ENABLE MBA INTERRUPTS
 
;
; FATAL CONTROLLER OR DRIVE ERROR EXIT
;
 
80$:	BSBW	ERL$DEVICERR		;LOG DEVICE ERROR
	BRW	FATALERR		;
	.PAGE
	.SBTTL	TM03-TE16/TU77 REGISTER DUMP ROUTINE
;
; REGDUMP - TM03-TE16/TU77 REGISTER DUMP ROUTINE
;
; THIS ROUTINE IS CALLED TO SAVE THE CONTROLLER AND DRIVE REGISTERS IN A
; SPECIFIED BUFFER. IT IS CALLED FROM THE DEVICE ERROR LOGGING ROUTINE AND
; FROM THE DIAGNOSTIC BUFFER FILL ROUTINE.
;
; INPUTS:
;
;	R0 = ADDRESS OF REGISTER SAVE BUFFER.
;	R4 = ADDRESS OF ADAPTER CONFIGURATION REGISTER.
;	R5 = DEVICE UNIT UCB ADDRESS.
;
; OUTPUTS:
;
;	THE CONTROLLER AND DRIVE REGISTERS ARE SAVED IN THE SPECIFIED BUFFER.
;
 
REGDUMP:				;TM03-TE16/TU77 REGISTER DUMP ROUTINE
	MOVL	#<MT_TC+4+MBA$L_BCR+4+8>/4,(R0)+ ;INSERT NUMBER OF DEVICE REGISTERS
	MOVL	MBA$L_CSR(R4),(R0)+	;SAVE CONFIGURATION REGISTER
	MOVL	MBA$L_CR(R4),(R0)+	;SAVE CONTROL REGISTER
	MOVL	UCB$L_MT_SR(R5),(R0)+	;SAVE STATUS REGISTER
	MOVL	MBA$L_VAR(R4),(R0)+	;SAVE VIRTUAL ADDRESS REGISTER
	MOVL	MBA$L_BCR(R4),(R0)+	;SAVE BYTE COUNT REGISTER
	EXTZV	#9,#8,-8(R0),R1		;GET FINAL MAP REGISTER NUMBER
	MOVL	MBA$L_MAP(R4)[R1],(R0)+	;SAVE FINAL MAP REGISTER CONTENTS
	CLRL	(R0)+			;ASSUME NO PREVIOUS MAP REGISTER
	DECL	R1			;CALCULATE PREVIOUS MAP REGISTER NUMBER
	BLSS	10$			;IF LSS NONE
	MOVL	MBA$L_MAP(R4)[R1],-4(R0) ;SAVE PREVIOUS MAP REGISTER CONTENTS
10$:	MOVZBL	#<MT_TC>/4,R1		;SET NUMBER OF DRIVE REGISTERS TO SAVE
	MOVL	UCB$L_CRB(R5),R2	;GET ADDRESS OF PRIMARY CRB
	ADDL3	#4,@CRB$L_INTD+VEC$L_IDB(R2),R2 ;GET ADDRESS OF TM03-TE16/TU77 REGISTERS
	MOVZWL	UCB$W_MT_CS1(R5),(R0)+	;SAVE DRIVE CONTROL REGISTER
20$:	MOVL	(R2)+,(R0)+		;SAVE DRIVE REGISTER
	SOBGTR	R1,20$			;ANY MORE TO SAVE?
	RSB				;
UNSOLNT:	RSB			;******TEMP*******
	.PAGE
	.SBTTL	TM03-TE16/TU77 SLAVE CONTROLLER INTERRUPT DISPATCHER
;+
; TM$INT - TM03-TE16/TU77 SLAVE CONTROLLER INTERRUPT DISPATCHER
;
; THIS ROUTINE IS ENTERED VIA A JSB INSTRUCTION WHEN AN INTERRUPT OCCURS ON A
; TM03-TE16/TU77 SLAVE CONTROLLER. THE STATE OF THE STACK ON ENTRY IS:
;
;	00(SP) = ADDRESS OF IDB ADDRESS.
;	04(SP) = SAVED R2.
;	08(SP) = SAVED R3.
;	12(SP) = SAVED R4.
;	16(SP) = SAVED R5.
;	20(SP) = INTERRUPT PC.
;	24(SP) = INTERRUPT PSL.
;
; INTERRUPT DISPATCHING OCCURS AS FOLLOWS:
;
;	IF THE INTERRUPTING CONTROLLER IS CURRENTLY OWNED AND THE OWNER UNIT IS
;	EXPECTING AN INTERRUPT, THEN THAT UNIT IS DISPATCHED FIRST. ALL OTHER
;	UNITS ARE DISPATCHED BY SELECTING THE CORRESPONDING SLAVE DRIVE, READING
;	ITS STATUS, AND DISPATCHING IF AN ATTENTION CONDITION EXISTS. AS EACH UNIT
;	IS FOUND, A TEST IS MADE TO DETERMINE IF AN INTERRUPT IS EXPECTED ON THE
;	UNIT. IF YES, THEN THE DRIVER IS CALLED AT ITS INTERRUPT RETURN ADDRESS.
;	ELSE THE DRIVER IS CALLED AT ITS UNSOLICITED INTERRUPT ADDRESS. AS EACH
;	CALL TO THE DRIVER RETURNS, THE NEXT SLAVE UNIT IS SELECTED AND AN ATTEMPT
;	IS MADE TO DISPATCH THAT UNIT. WHEN ALL UNITS HAVE BEEN SELECTED AND NO
;	ATTENTION CONDITIONS REMAIN, THE INTERRUPT IS DISMISSED.
;-
 
TM$INT::				;TM03-TE16/TU77 SLAVE CONTROLLER INTERRUPT DISPATHCER
	MOVL	@(SP),R3		;GET ADDRESS OF IDB
	MOVL	IDB$L_CSR(R3),R4	;GET ADDRESS OF TM03-TE16/TU77 REGISTERS
	PUSHL	MT_TC(R4)		;SAVE CONTENTS OF TAPE CONTROL REGISTER
	MOVL	IDB$L_OWNER(R3),R5	;GET OWNER UCB ADDRESS
	BEQL	10$			;IF EQL NONE
	BBSC	#UCB$V_INT,UCB$W_STS(R5),70$ ;IF SET, INTERRUPT EXPECTED
10$:	ASHL	#31-MT_DS_V_SSC,MT_DS(R4),R2 ;ANY SLAVE CHANGE STATUS?
	BGEQ	100$			;IF GEQ NO
20$:	MOVL	@4(SP),R3		;RETRIEVE ADDRESS OF IDB
	MOVL	IDB$L_CSR(R3),R4	;RETRIEVE ADDRESS OF OF TM03-TE16/TU77 REGISTERS
	ASHL	#31-MT_DS_V_SSC,MT_DS(R4),R2 ;ANY SLAVE STATUS CHANGE?
	BGEQ	50$			;IF GEQ NO
	CLRL	R2			;CLEAR STARTING SLAVE UNIT NUMBER
30$:	MOVL	R2,MT_TC(R4)		;SELECT SLAVE UNIT
	MOVL	MT_DS(R4),R5		;READ SLAVE DRIVE STATUS
	BBS	#MT_DS_V_SLA,R5,60$	;IF SET, SLAVE TRANSITION TO ONLINE
	BBS	#MT_DS_V_PIP,R5,40$	;IF SET, POSITIONING IN PROGRESS
	BBS	#MT_DS_V_BOT,R5,60$	;IF SET, SLAVE AT BEGINNING OF TAPE
40$:	AOBLEQ	#7,R2,30$		;ANY MORE SLAVE UNITS TO SCAN?
50$:	POPL	MT_TC(R4)		;RESTORE CONTENTS OF TAPE CONTROL REGISTER
	ADDL	#4,SP			;CLEAN STACK
	POPR	#^M<R2,R3,R4,R5>	;RESTORE REGISTERS
	REI				;
60$:	CMPB	R2,IDB$B_UNITS(R3)	;LEGAL SLAVE DRIVE UNIT NUMBER?
	BGEQ	90$			;IF GEQ NO
	BBS	#MT_DS_V_SLA,R5,90$	;IF SET, SLAVE TRANSITION TO ONLINE
	MOVL	IDB$L_UCBLST(R3)[R2],R5	;GET ADDRESS OF UCB
	BBCC	#UCB$V_INT,UCB$W_STS(R5),40$ ;IF CLR, INTERRUPT NOT EXPECTED
70$:	MOVQ	UCB$L_FR3(R5),R3	;RESTORE DRIVER CONTEXT
	JSB	@UCB$L_FPC(R5)		;CALL DRIVER AT INTERRUPT RETURN ADDRESS
	BRB	20$			;
80$:	MOVL	UCB$L_DDB(R5),R3	;GET ADDRESS OF DDB
	MOVL	DDB$L_DDT(R3),R3	;GET ADDRESS OF DDT
	JSB	@DDT$L_UNSOLINT(R3)	;CALL DRIVER AT UNSOLICITED INTERRUPT ADDRESS
	BRB	20$			;
90$:	MOVZBL	#F_DRVCLR!1,MT_CS1(R4)	;CLEAR DRIVE
	BRB	40$			;
;**************
; LOG/UNEXPECTED INTERRUPT
;**************
100$:					;
	BRB	20$			;
 
	.END
