Google
 

Trailing-Edge - PDP-10 Archives - BB-Y393Q-SM - monitor-sources/phyx2.mac
There are 47 other files named phyx2.mac in the archive. Click here to see a list.
;<4-1-FIELD-IMAGE.MONITOR>PHYX2.MAC.2, 25-Feb-82 20:45:19, EDIT BY DONAHUE
;UPDATE COPYRIGHT DATE
; UPD ID= 476, FARK:<4-WORKING-SOURCES.MONITOR>PHYX2.MAC.2,  23-Apr-81 16:04:06 by SCHMITT
;Edit 1855 - Reset overdue timer before starting I/O on retry
;<4.MONITOR>PHYX2.MAC.24,  3-Jan-80 08:10:17, EDIT BY R.ACE
;UPDATE COPYRIGHT DATE
;<4.MONITOR>PHYX2.MAC.23, 30-Oct-79 14:50:10, EDIT BY DBELL
;FIX 4.2551 BY USING RDREG INSTEAD OF RDREG3 IN ROUTINE HLTCHK
;<4.MONITOR>PHYX2.MAC.22, 25-Oct-79 19:35:43, EDIT BY DBELL
;TCO 4.2551 - CHECK IF MICROCODE IS HALTED IN DX2CON, GIVE ERROR IF SO
;<4.MONITOR>PHYX2.MAC.21, 19-Sep-79 15:18:20, EDIT BY DBELL
;TCO 4.2476 - ADD DISPATCH AND ROUTINE TO MAKE SET ONLINE WORK IN GENERAL
;<4.MONITOR>PHYX2.MAC.20, 18-Sep-79 17:22:02, EDIT BY DBELL
;FIX 4.2457 SOME BY CLEARING ATTENTION IN ASYNST
;<4.MONITOR>PHYX2.MAC.19, 12-Sep-79 10:40:07, EDIT BY DBELL
;FIX DX2DNF BUGCHK
;<4.MONITOR>PHYX2.MAC.18, 11-Sep-79 17:42:13, EDIT BY DBELL
;TCO 4.2457 - MAKE MULTIPLE TXO2'S OFF ONE DX20 (AND TXO3 OPTION) WORK
;<OSMAN.MON>PHYX2.MAC.1, 10-Sep-79 16:01:58, EDIT BY OSMAN
;TCO 4.2412 - Move definition of BUGHLTs, BUGCHKs, and BUGINFs to BUGS.MAC
;<4.MONITOR>PHYX2.MAC.16, 24-Aug-79 16:46:44, EDIT BY DBELL
;TCO 4.2421 - REMOVE USES OF US.OFS, PHYONL, PHYOFL SINCE UNRELIABLE
;<4.MONITOR>PHYX2.MAC.15, 24-Jul-79 14:13:07, EDIT BY DBELL
;TCO 4.2339 - PREVENT RMR ERRORS WHEN TWO ASYCHRONOUS EVENTS HAPPEN
;<4.MONITOR>PHYX2.MAC.14,  6-Mar-79 09:37:09, Edit by KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<2BOSACK>PHYX2.MAC.7, 19-Feb-79 23:55:55, EDIT BY BOSACK
;<2BOSACK>PHYX2.MAC.6, 19-Feb-79 21:03:44, EDIT BY BOSACK
;<2BOSACK>PHYX2.MAC.5, 19-Feb-79 20:59:57, EDIT BY BOSACK
;ADD LOGIC TO DETERMINE HARDWARE SELECTED DENSITY ON FIRST OP FROM BOT
;<2BOSACK>PHYX2.MAC.4, 19-Feb-79 19:38:12, EDIT BY BOSACK
;<2BOSACK>PHYX2.MAC.3, 19-Feb-79 19:33:51, EDIT BY BOSACK
;<2BOSACK>PHYX2.MAC.2, 19-Feb-79 19:30:44, EDIT BY BOSACK
;<4.MONITOR>PHYX2.MAC.12,  3-Feb-79 00:20:54, Edit by MCLEAN
;<4.MONITOR>PHYX2.MAC.11,  3-Feb-79 00:19:51, Edit by MCLEAN
;<4.MONITOR>PHYX2.MAC.10, 31-Jan-79 01:09:26, Edit by MCLEAN
;MORE .DGPDL FIXES
;<4.MONITOR>PHYX2.MAC.9, 23-Jan-79 18:33:57, Edit by MCLEAN
;MORE DIAG JSYS
;<4.MONITOR>PHYX2.MAC.8, 21-Jan-79 17:54:18, Edit by MCLEAN
;INSERT .DGPDL CODE
;<4.MONITOR>PHYX2.MAC.7, 30-Aug-78 09:31:02, EDIT BY FORTMILLER
;TCO 4.1997 Set US.REW at interrupt level instead of at Start I/O
; time.
;<4.MONITOR>PHYX2.MAC.6,  8-Aug-78 13:44:10, Edit by MCLEAN
;<4.MONITOR>PHYX2.MAC.5,  5-Aug-78 16:08:24, Edit by MCLEAN
;<4.MONITOR>PHYX2.MAC.4,  4-Aug-78 16:08:05, Edit by FORTMILLER
;Add a BUGCHK - DX2HLT If the DX20 is discovered not running and
; print out the contents of DXGP6 which contains an error code
; Only check for legal data mode in Start I/O if a data type operation
;<3A.MONITOR>PHYX2.MAC.5,  1-Aug-78 14:33:10, Edit by FORTMILLER
;Remove BUGCHK at ENDLOD and fix bug in checking whether a mode
; set needs to be done for a TU71
;<4.MONITOR>PHYX2.MAC.3, 31-Jul-78 21:02:44, Edit by MCLEAN
;ADD ONLINE/OFFLINE INTERRUPT PSI
;<4.MONITOR>PHYX2.MAC.2, 22-Jul-78 22:12:37, Edit by MCLEAN
;<3A.MONITOR>PHYX2.MAC.4, 14-Jul-78 09:13:57, Edit by FORTMILLER
;Information printed from AC T1 during BUGCHK DX2NUE is garbage
;<3A.MONITOR>PHYX2.MAC.3, 13-Jul-78 16:04:35, Edit by FORTMILLER
;Add BUGCHK if SYSERR block at ENDLOD doesn't have any beginning data in it
; On some of the BUGs print out interesting AC information
;<3A-NEW>PHYX2.MAC.2,  1-Jun-78 20:19:03, Edit by FORTMILLER
;<3A-NEW>PHYX2.MAC.1, 30-May-78 10:45:29, Edit by FORTMILLER
;MAKE MANY CHANGES FOR 3A
;<DX20-101B-SOURCES>PHYDX2.MAC.4, 14-Jun-77 08:48:05, Edit by OUYANG

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980,1981,1982 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	SEARCH PROLOG,PHYPAR,SERCOD ;SYSTEM PARAMETERS
	TTITLE (PHYX2,,< - DEVICE DEPENDENT CODE FOR DX20/TU70S MAGTAPES VER 1>)
	SUBTTL E. OUYANG/Ed Fortmiller  24 FEB 78

	DX2VER==1		;EDIT VERSION

	ENTRY DX2DSP		;FOR LIBRARY SEARCH

;	For information on how to program the DX20/TU7x, see
;	document 105-220-001-00 DX20-v100 Microcode by Steve
;	Paavola.

PHYX2:				;BEGINNING ADDRESS OF PHYX2
	SUBTTL DEVICE DEPENDANT TABLE DEFS

;DX20 STARTING ADDRESS

	STADDR==6		;DX20 STARTING ADDRESS
	MAXDRV==^D256		;TOTAL NUMBER OF DRIVES PER DX20
	NUMDRV==^D16		;MAXIMUM NUMBER OF DRIVES WHICH CAN BE
				;USED DUE TO TABLE SPACE LIMITATIONS

;UDB EXTENSIONS

	U.HDEN==UDBDDP		;DENSITY (HARDWARE DETERMINED)
				;NOTE: DO NOT MOVE WITHOUT CHANGING MAGTAP
	U.EPOS==U.HDEN+1	;ERROR POSITION
	U.EBP==U.EPOS+1		;ERROR BYTE POINTER
	E.EBC==U.EBP+1		;ERROR BYTE COUNTER
	U.ETCF==E.EBC+1		;TAPE CLEANER FLAG
	U.ETIE==U.ETCF+1	;TIE BYTE

	LU.DX2==U.ETIE+1	;LENGTH OF UDB

	UDB.NM==1B17		;BIT SET IN UDBERR TO INDICATE
				; A RECOVERABLE NO MOTION ERROR
;KDB DEVICE DEPENDANT PORTION

	K.DUDB==KDBDDP		;UDB TABLE (NUMDRV DRIVES LONG)
	K.DNUM==K.DUDB+NUMDRV	;NUMBER OF DRIVES IN UDB TABLE
	K.DXAD==K.DNUM+1	;MASSBUS ADDRESS OF DX20
	K.SUDB==K.DXAD+1	;CURRENT UDB (0 IF NONE)
	K.DCNI==K.SUDB+1	;CONI OF RH GOES HERE
	K.DCS1==K.DCNI+1	;DATAI RH CONTROL REGISTER
	K.DDBF==K.DCS1+1	;DATAI RH DATA REGISTER
	K.DVER==K.DDBF+1	;MICROCODE VERSION #

	K.DREG==K.DVER+1	;DRIVE REGISTERS GO HERE

DEFINE SAVREG(REGS),<
	IRP REGS,<SAVBIT==SAVBIT!<1_<^D35-REGS>>
	SAVNUM==SAVNUM+1	;COUNT NUMBER OF REGISTERS
	>;END IRP REGS
>;END DEFINE SAVREG

	SAVBIT==0		;INIT TO 0, THIS WILL HAVE A BIT SET
				; FOR EACH DX20 MASSBUS REG TO SAVE
				; IN THE KDB.
	SAVNUM==0		;INIT TO 0, THIS WILL BE A COUNT OF
				; THE NUMBER OF DX20 MASSBUS REGS
				; THAT GET SAVED IN THE KDB

	SAVREG <0,1,2,3,4,5,6,20,21,22,23,24,26,27,30,31,32,33,34,35,36,37>

	LR.DX2==SAVNUM		;NUMBER OF DX20 REGISTERS SAVED IN THE KDB

;FOLLOWING ARE THE 24(OCTAL) WORDS FOR THE EXTENDED STATUS TABLE

	K.DEST==K.DREG+^D22	;EXTENDED STATUS TABLE GOES HERE
	LK.DX2==K.DEST+^D20	;LENGTH OF DX20 KDB
	SUBTTL	MASSBUS-DX20 REGISTER DEFINITIONS

;MASSBUSS DEVICE REGISTER BIT ASSIGNMENTS (REGISTERS 00-37)

	DXCTR==0B5		;CONTROL REGISTER
	DXSTR==1B5		;STATUS REGISTER
	DXERR==2B5		;ERROR REGISTER 
	DXMTR==3B5		;MAINTAINABILITY REGISTER
	DXASR==4B5		;ATTENTION SUMMARY "PSEUDO" REGISTER
	DO.FC==5B5		;FRAME COUNT REGISTER
	DXDTR==6B5		;DRIVE TYPE AND HARDWARE VERSION REGISTER
	MBRA07==7B5		;NOT USED
	MBRA10==10B5		;NOT USED
	MBRA11==11B5		;NOT USED
	MBRA12==12B5		;NOT USED
	MBRA13==13B5		;NOT USED
	MBRA14==14B5		;NOT USED
	MBRA15==15B5		;NOT USED
	MBRA16==16B5		;NOT USED
	MBRA17==17B5		;NOT USED
	DXGP0==20B5		;GENERAL PURPOSE REGISTER 0
	DXGP1==21B5		;GENERAL PURPOSE REGISTER 1
	DXGP2==22B5		;GENERAL PURPOSE REGISTER 2
	DXGP3==23B5		;GENERAL PURPOSE REGISTER 3
	DXGP4==24B5		;GENERAL PURPOSE REGISTER 4
	DXGP5==25B5		;GENERAL PURPOSE REGISTER 5
	DXGP6==26B5		;GENERAL PURPOSE REGISTER 6
	DXGP7==27B5		;GENERAL PURPOSE REGISTER 7
	DXDR0==30B5		;DIAGNOSTICS REGISTER 0
	DXDR1==31B5		;DIAGNOSTICS REGISTER 1
	DXDR2==32B5		;DIAGNOSTICS REGISTER 2
	DXDR3==33B5		;DIAGNOSTICS REGISTER 3
	DXDR4==34B5		;DIAGNOSTICS REGISTER 4
	DXDR5==35B5		;DIAGNOSTICS REGISTER 5
	DXDR6==36B5		;DIAGNOSTICS REGISTER 6
	DXDR7==37B5		;DIAGNOSTICS REGISTER 7
	;CONTROL REGISTER DEFINITIONS (DXCTR REG. 0)

GO==1B35			;GO BIT
DEFSTR(DXFTN,T1,^D35,6)		;DX20 FUNCTON FIELD(INCLUDES GO BIT) AS IN T1

;DX20 FUNCTION CODES(INCLUDING GO BIT)

	XF.NOP==1		;NO OPERATION
	XF.UNL==3		;REWIND AND UNLOAD
	XF.REW==7		;REWIND
	XF.CLR==11		;DRIVE CLEAR
	XF.SRL==13		;SENSE RELEASE
	XF.ERA==25		;ERASE GAP
	XF.WTM==27		;WRITE TAPE MARK
	XF.SPF==31		;FORWARD SPACE RECORD
	XF.SPR==33		;BACK SPACE RECORD
	XF.SBF==35		;FORWARD SPACE BLOCK
	XF.SBR==37		;BACKWARD SPACE BLOCK
	XF.TIO==41		;TEST I/O
	XF.DSE==43		;DATA SECURITY ERASE
	XF.SNS==45		;SENSE
	XF.SNR==47		;SENSE RESERVE
;
;THE FOLLOWING ARE NON IMMEDIATE TYPE OF OPERATIONS
; AND CAUSE A COMMAND DONE INTERRUPT
;
	XF.WTF==61		;WRITE DATA
	XF.DIA==63		;WRITE DIAGNOSTIC
	XF.LWR==65		;LOOP WRITE TO READ
	XF.RDF==71		;READ DATA
	XF.RXS==75		;READ EXTENDED STATUS
	XF.RDR==77		;READ REVERSE

;STATUS REGISTER DEFINITIONS (DXSTR REG. 1)

	SR.ATA==1B20		;ATTENTION ACTIVE (CAUSES ATTN SUMMARY)
	SR.CER==1B21		;COMPOSITE ERROR (MUST CHECK ERROR REG.)
	SR.LP==1B22		;LINK PRESENT
	SR.RUN==1B23		;MICROPROCESSOR RUNNING
;ERROR REGISTER DEFINITIONS (DXERR REG. 2)

DEFSTR(ECC,T1,^D27,^D4)		;STRUCTURE FOR ERROR CLASS CODE
DEFSTR(ESCC,T1,^D23,^D4)	;STRUCTURE FOR ERROR SUB-CLASS CODE
	ER.NEW==1B28		;MICROPROCESSOR DETECTED ERROR
	ER.SPT==1B29		;MICROPROCESSOR STOPED
	ER.MPE==1B30		;MICROBUS PAR. ERROR IN MASSBUSS INTERFACE
	ER.DPE==1B31		;DATA BUFFER PAR. ERROR
	ER.CPE==1B32		;MASSBUS CONTROL BUS PAR. ERROR
	ER.RMR==1B33		;REGISTER MODIFICATION REFUSED
	ER.ILR==1B34		;TRIED TO ACCESS NON-IMPLEMENTED REG.
	ER.ILF==1B35		;TRIED TO ISSUE NON-IMPLEMENTED COMMAND

;*CLASS SUB-CLASS ERROR CODES
; NOTE SUB-CLASS ERROR CODE DEFN.S ARE INDENTED

	ER.UDS==1		;UNUSUAL DEVICE STATUS
		SER.FS==0	;FINAL STATUS SEQUENCE
		SER.IS==1	;INITIAL STATUS SEQUENCE
	ER.SR==2		;SHORT RECORD
	ER.LR==3		;LONG RECORD
	ER.DSE==4		;DRIVE SELECTION ERROR
	ER.RER==5		;RECOVERABLE ERROR(TAPE MOTION STARTED)
		SER.DP==0	;DATA PARITY ERROR
	ER.RE1==6		;RECOVERABLE ERROR(NO TAPE MOTION)
		SER.AM==0	;ADDRESS MISMATCH
		SER.B1==1	;BUS PARITY ERROR FROM DRIVE
		SER.B2==2	;BUS PARITY ERROR FROM INITIAL STATUS
	ER.NRE==7		;NON-RECOVERABLE ERROR
		SER.DP==0	;DATA PATH, MICRO BUS PARITY ERROR
		SER.CB==1	;CHANNEL BUS INTER.,MICRO BUS PARITY ERROR
	ER.FTL==^D8		;FATAL ERROR
		SER.DT==0	;DRIVE TYPE NOT MATCHING BY MICROCODE
		SER.PE==1	;PARITY ERROR DURING CONTROL UNIT INITIAL SEQUENCE
		SER.PE==2	;****SIMILAR AS ABOVE

;MAINTENANCE REGISTER DEFINITIONS (DXMTR REG. 3)

	MR.SS==1B31		;SINGLE STEP MICRO CONTROLLER
	MR.WEP==1B32		;WRITE EVEN PARITY BALU
	MR.ST==1B33		;START/STOP MICRO CONTROLLER
	MR.RES==1B34		;RESET MICRO CONTROLLER
;ATTENTION SUMMARY REGISTER DEFINITIONS (DXASR REG. 4)

	AS.7==1B28		;DRIVE-7 NEEDS ATTENTION
	AS.6==1B29		;DRIVE-6 NEEDS ATTENTION
	AS.5==1B30		;DRIVE-5 NEEDS ATTENTION
	AS.4==1B31		;DRIVE-4 NEEDS ATTENTION
	AS.3==1B32		;DRIVE-3 NEEDS ATTENTION
	AT.2==1B33		;DRIVE-2 NEEDS ATTENTION
	AT.1==1B34		;DRIVE-1 NEEDS ATTENTION
	AT.0==1B35		;DRIVE-0 NEEDS ATTENTION

;BYTE REGISTER DEFINITIONS(DO.FC REG. 5)
; USED INTERCHANGEABLY WITH REG. 25

;STATUS INDEX/ENDING STATUS REGISTER DEFINITION(DXGP0 REG.20)

ES.RES==1B28			;BIT TO REQUEST FOR EXTENDED STATUS
ES.UEX==1B27			;UNIT EXCEPTION
ES.UCK==1B26			;UNIT CHECK
ES.DVE==1B25			;DEVICE END
ES.CHE==1B24			;CHANNEL END
ES.BSY==1B23			;CONTROL UNIT OR DEVICE BUSY
ES.CUE==1B22			;CONTROL UNIT END
ES.SM==1B21			;STATUS MODIFIER
ES.ATN==1B20			;ATTENTION

;DRIVE NUMBER/MODE REGISTER DEFINITION(DXGP1 REG. 21)

DEFSTR(DRVNUM,T1,^D35,^D8)	;STRUCTURE DEFN FOR DRIVE NUMBER
DEFSTR(DRVMOD,T1,^D27,^D4)	;DRIVE MODE
DEFSTR(DATMOD,T1,^D23,^D4)	;STRUCTURE FOR DATA MODE

;DRIVE MODE VALUES

	DRV.NM==0		;NO MODE SET TO BE ISSUED
	DRV.O2==1		;7 TRACK, 200 BPI, ODD PARITY
	DRV.O5==2		;7 TRACK, 556 BPI, ODD PARITY
	DRV.O8==3		;7 TRACK, 800 BPI, ODD PARITY
	DRV.E2==5		;7 TRACK, 200 BPI, EVEN PARITY
	DRV.E5==6		;7 TRACK, 556 BPI, EVEN PARITY
	DRV.E8==7		;7 TRACK, 800 BPI, EVEN PARITY
	DRV.NR==13		;9 TRACK, 800 BPI
	DRV.PE==14		;9 TRACK, 1600 BPI
	DRV.GC==15		;9 TRACK, 6250 BPI.
	DRV.IL==77		;ILLEGAL CODE

;DATA MODE VALUES

	DAT.IL==0		;ILLEGAL CODE
	DAT.CD==1		;CORE DUMP FORMAT(9-TRACK)
	DAT.IC==2		;INDUSTRY COMPATIBLE, 4 8-BIT BYTES/WRD
	DAT.SB==3		;6 6-BIT BYTES/WRD
	DAT.AS==4		;7-BIT ASCII MODE
	DAT.HD==5		;HI DENSITY

;EXTENDED STATUS TABLE SIZE REGISTER DEFINITION (DXGP2 REG. 22)

DEFSTR(ESTSZ,T1,^D35,^D8)	;STRUCTURE FOR EXTENDED STATUS TABLE SIZE

;TRACK IN ERROR, FLAGS REGISTER DEFINITIONS (DXGP3 REG. 23)

	TE.TIE==1B27		;=1, IF TIE ERROR RECOVERY ATTEMPTED
	TE.SOP==1B26		;=1, IF SENSE OPERATION REQUIRED
	TE.SAS==1B25		;=1, IF SUPPRESS AUTOMATIC SENSE ON UNIT CHECK.

;ASYNCHRONOUS STATUS REGISTER DEFINITIONS (DXGP4 REG. 24)

;BYTE COUNT REGISTER DEFINITIONS (DXGP5 REG. 25)

	DXGP==177777B35		;MASK FOR 16 DATA BITS IN REGISTER

;EXTENDED STATUS REGISTER 0 DEFINITIONS(DXGP6 REG. 26)

	DXGP==177777B35		;MASK FOR 16 DATA BITS IN REGISTER

;EXTENDED STATUS REGISTER 1 DEFINITIONS (DXGP7 REG. 27)

	DXGP==177777B35		;MASK FOR 16 DATA BITS IN REGISTER
;DIAGNOSTIC REGISTER 0 DEFINITION (DXDR0 REG. 30)

	IR==177777B35		;MASK FOR IR REG.

;DIAGNOSTIC REGISTER 1 DEFINITION (DXDR1 REG. 31)

	D1.IRE==1B20		;ENABLE IR LOAD FROM MICRO-STORE
	D1.MSE==1B21		;ENABLE MICRO-STORE LOAD FROM IR
	D1.PCE==1B22		;ALLOW LOAD/WRITE OF THE PC
	D1.PCI==1B23		;ALLOW AUTO-INCREMENT OF PC 
	D1.PC==7777B35		;MASK FOR 12 BITS IN PC


	DS.BOT==1B35		;BOT SEEN
	DS.EOT==1B34		;EOT SEEN
	DS.TM==1B33		;TAPE MARK SEEN
	DS.WLK==1B32		;WRITE LOCKED
	DS.OFL==1B31		;DRIVE IS OFFLINE
	DS.NMV==1B30		;TAPE DIDN'T MOVE
	DS.DC==1B29		;DATA CHECK IN SENSE BYTES
	DS.RTY==1B28		;RETRIABLE ERROR
	DS.ERR==1B27		;ERROR
;BIT DEFINITIONS FOR SENSE BYTES 0-3

	S0.CR==1B2		;COMMAND REJECT
	S0.IR==1B3		;INTERVENTION REQUIRED
	S0.BOC==1B4		;BUS OUT CHECK
	S0.EC==1B5		;EQUIPMENT CHECK
	S0.DC==1B6		;DATA CHECK
	S0.OR==1B7		;OVERRUN
	S0.WCZ==1B8		;WORD COUNT ZERO
	S0.DCC==1B9		;CONVERTER CHECK
	S1.NSE==1B10		;NOISE
	S1.TUA==1B11		;TU STATUS A
	S1.TUB==1B12		;TU STATUS B
	S1.7TK==1B13		;7 TRACK FEATURE
	S1.BOT==1B14		;BOT - LOAD POINT
	S1.WS==1B15		;WRITE STATUS
	S1.FP==1B16		;WRITE PROTECTED
	S1.NC==1B17		;NOT CAPABLE
	S2.TIE==377B27		;TRACK IN ERROR REGISTER
	S3.VRC==1B28		;R/W VRC
	S3.MTE==1B29		;MTE/LRC
	S3.SKW==1B30		;SKEW ERROR
	S3.CRC==1B31		;CRC ERROR
	S3.ENV==1B32		;VRC ERROR
	S3.D16==1B33		;1600 BPI
	S3.BKW==1B34		;BACKWARD STATUS
	S3.CPC==1B35		;C COMPARE

;BIT DEFINITIONS FOR SENSE BYTE 6

	S6.7TK==1B20		;7 TRACK DRIVE
	S6.DD==1B22		;DUAL DENSITY TAPE UNIT
				; TU IS CAPABLE OF BOTH 1600 AND 6250
	S6.TMI==17B27		;MODEL ID FIELD
	S6M.70==1		;TU70 (ONLY WHEN ONLINE)
	S6M.71==1		;TU71 (ONLY WHEN ONLINE)
	S6M.72==3		;TU72
	S6M.73==13		;TU7x (200 IPS GCR DRIVE)
	SUBTTL DX20 ERROR RECOVERY DEFS

;RETRY COUNTS:

	CLNREC==5		;SP REVERSE THIS NR RECORDS TO HIT CLEANER
	RTYOP==4		;RETRY OPERATION THIS MANY TIMES BEFORE TAPE CLEAN SEQUENCE
	RTYCLN==^D10		;RETRY CLEAN SEQUENCE THIS MANY TIMES ON READ
				; BEFORE GIVING UP
				; THE TOTAL NR OF RD RETRIES = RTYOP*(RTYCLN+1)

	RTYWRT==^D14		;# WRITE RETRIES MAXIMUM BEFORE ABORT

	RTY.DN==16		;CODE SIGNAL END OF RETRY
	RTY.CP==17		;CODE TO CHECK POSITION

;ERROR WORDS

;	E.EBC			;ERR BYTE COUNTER (USED IF WE HIT BOT
				;DURING TAPE CLEAN SEQUENCE)
;	U.EBP			;ERR BYTE POINTER
;	U.ETCF			;-1= IN TAPE CLN SEQUENCE, 0= NOT
;	UDBERR(RH)		;CURRENT FUNCTION (1 - 17)
				;ON RETRY OF ORIGINAL OPERATION, THIS LOC
				;MUST BE SET TO THE ORIGINAL OPERATION
;	UDBERC			;RETRY COUNT
				;CONVERTED TO # RETRIES DONE AT END
;	U.EPOS			;WE SHOULD BE HERE WHEN WE'RE
				;READY TO RETRY OPERATION
	SUBTTL	ROUTINE TO MANIPULATE DX20 REGISTERS

;MACROS TO READ AND WRITE A DX20 REGISTER
; ASSUME: P1/ CDB POINTER
;	  Q2/ UNIT NUMBER OF THE DX20
; T1,T4 ARE PRESERVED

DEFINE RDRG (REG),<
	MOVSI T2,(REG)
	 CALL RDREG3
>;END DEFINE RDRG

DEFINE WTRG (REG,DATA),<
	MOVEI T2,DATA		;DATA LESS OR EQUAL TO 16 BITS
	TLO T2,(REG)	
	CALL WTREG3
>;END DEFINE WTRG

;MACRO TO READ AND WRITE DX20 REGISTERS
; ASSUME: P1/ CDB POINTER
;	  P3/ UDB POINTER
; T1,T4 ARE PRESERVED

DEFINE REDRG (REG),<
	MOVSI T2,(REG)
	CALL RDREG
>;END DEFINE REDRG

DEFINE WRTRG (REG,DATA),<
	MOVEI T2,DATA		;;DATA LESS OR EQUAL TO 16 BITS
	TLO T2,(REG)
	CALL WTREG
>;END DEFINE WRTRG
;STDX - STARTS THE MICROCODE IN THE DX20
; T1/ STARTING ADDRESS OF THE CRAM
; P1/ CDB, Q2/ UNIT NUMBER OF THE DX20
;	CALL STDX
; RETURN+1: ALWAYS
; T1 IS NOT PRESERVED

STDX:	PUSH P,T1		;SAVE T1
	MOVX T2,DXMTR!MR.RES	;ISSUE A RESET TO
	CALL WTREG3		; THE DX20. (ALSO STOP IT)
	POP P,T2		;GET BACK THE STARTING ADDR
	ANDI T2,D1.PC		;STRIP
	TXO T2,DXDR1!D1.PCE!D1.PCI!D1.IRE ;LOAD STARTING
	CALL WTREG3		; ADDRESS IN THE DX20
	MOVX T2,DXMTR!MR.ST	;START THE
	CALLRET WTREG3		; DX20 MICROPROCESSOR

;GTVER - GETS THE VERSION NUMBER OF THE MICROCODE FROM
; LOCATION 0 OF THE CRAM IN THE DX20
; P1/CDB, Q2/ UNIT NUMBER OF THE DX20
;	CALL GTVER
; RETURN+1: ALWAYS, AND T1/ CONTENTS OF LOC. 0 OF CRAM

GTVER:	MOVX T2,DXMTR!MR.RES	;STOP THE
	CALL WTREG3		; DX20 MICROPROCESSOR
	MOVX T2,DXDR1!D1.PCE!D1.IRE ;SET THE
	CALL WTREG3		; PC TO 0
	MOVX T2,DXDR0		;READ THE IR
	CALLRET RDREG3		; REGISTER INTO T1
;GTSNS - READS IN SENSE BYTES 0-3 INTO T1
; T4/ DRIVE NUMBER
; P1/ CDB, Q2/ UNIT NUMBER OF DX20
;	CALL GTSNS
; RETURN+1: FAIL
; RETURN+2: GOOD RETURN
; T1/ SENSE BYTES 0 - 3  (0) 2-9 (1) 10-17 (2) 20-27 (3) 28-35

GTSNS:	CALL HLTCHK		;SEE IF MICROCODE IS STILL RUNNING
	 RET			;NO, FAIL
	MOVE T2,T4		;GET THE DRIVE NUMBER
	TXO T2,DXGP1		;SET THE DRIVE
	CALL WTREG3		; NUMBER INTO THE DX20
REPEAT 0,<			;IF ITS DESIRED TO DO A NOP TO
				; GET THE SENSE BYTE DELETE THE
				; REPEAT 0 AND THE MOVX FOLLOWING IT

	MOVX T2,DXGP3!TE.SOP	;SET FORCE SENSE BIT
	CALL WTREG3		; LOAD INTO THE FLAGS REG
	MOVX T2,DXCTR!XF.NOP	;DO A
>;END REPEAT 0
	MOVX T2,<DXCTR!XF.SNS>	;DO A SENSE OPERATION
	CALL WTREG3		; NOP OPERATION
	MOVEI T4,1		;GET MASK BIT
	LSH T4,(Q2)		;ATTENTION MASK FOR THIS DX20
	PUSH P,P4		;USE P4 AS COUNTER
	MOVEI P4,1000		;LOOP COUNT=1000
				; (THIS MUST BE THIS LARGE AS THE
				; FIRST TIME THRU TAKES A LONG TIME)
GTSN1:	RDRG DXASR		;READ ATTENTION SUMMARY REG. IN T1
	TDNE T1,T4		;SKIP IF ATTENTION BIT NOT SET
	JRST GTSN2		;JUMP, GET ATTENTION SET
	SOJG P4,GTSN1		;TRY AGAIN
	POP P,P4		;FAIL, THEN RESTORE P4
	BUG(DX2FGS) ;PUT OUT BUGCHK
	RET			;JUST RETURN
GTSN2:	POP P,P4		;SUCCEED, RESTORE P4
	WTRG DXASR,(T4)		;CLEAR ATTENTION BIT FOR THIS DX20
	CALLRET RDSNS		;GET 4 SENSE BYTES IN T1
;GETEXS - READ IN 4 BYTES OF EXTENDED STATUS
; T1/ INDEX FOR EXTENDED STATUS
; P1/ CDB, Q2/ UNIT NUMBER OF DX20
;	CALL GETEXS
; RETURN+1: FAIL RETURN
; RETURN+2: SUCEED
; T1/ T1 HAS THE 4 BYTES  (1) 2-9 (2) 10-17 (3) 20-27 (4) 28 - 35

GETEXS:	MOVE T2,T1		;GET INDEX FROM T1
	TXO T2,<DXGP0!ES.RES>	;SET BIT TO REQUEST
	CALL WTREG3		; TO REQUEST SENSE BYTES
RDSNS:	MOVX T4,100		;NUMBER OF TIMES TO WAIT
				; FOR ES.RES TO CLEAR BEFORE GIVING UP
RDSNS1:	RDRG DXGP0		;READ BACK REG. 20
	TXNN T1,ES.RES		;REQUEST SENSE BYTE BIT CLEARED?
	JRST RDSNS2		;GO READ REG 26 AND 27
	SOJG T4,RDSNS1		;NO, TRY AGAIN
	BUG(DX2FUS)
	RET			;FAIL, NONSKIP RETURN
RDSNS2:	RDRG DXGP6		;READ IN REG 26
	HRL T4,T1		;PUT REG. 26 IN LEFT HALF
	RDRG DXGP7		;READ IN REG 27
	HRR T4,T1		;PUT REG. 27 IN RIGHT HALF
	MOVE T1,T4		;PUT IN T1
	RETSKP			;SKIP RETURN
;HLTCHK - SEES IF THE MICROCODE IS STILL RUNNING IN THE DX20
; P1/	CDB
; P2/	KDB
; P3/	UDB
;RETURNS:
;  +1:	MICROCODE HALTED, BUGINF PRINTED IF FIRST TIME NOTICED
;  +2:	MICROCODE IS RUNNING FINE
;
;PRESERVES T4.



HLTCHK:	MOVX T2,DXSTR		;READ THE DX20 STATUS REGISTER
	CALL RDREG		; TO SEE IF THE DX20 IS RUNNING
	MOVX T2,KS.HLT		;GET HALTED FLAG READY
	TXNN T1,SR.RUN		;IS IT RUNNING?
	JRST DX2STP		;NO IT QUIT ON US
	ANDCAM T2,KDBSTS(P2)	;NOT HALTED, REMEMBER THAT
	RETSKP			;GOOD RETURN


DX2STP:	TDNE T2,KDBSTS(P2)	;ALREADY KNEW THAT IT WAS STOPPED?
	RET			;YES, JUST RETURN
	IORM T2,KDBSTS(P2)	;NOW WE KNOW
	PUSH P,T4		;SAVE T4
	PUSH P,T1		;SAVE STATUS
	MOVX T2,DXERR		;NOW WANT ERROR REGISTER
	CALL RDREG		;READ IT
	HRLZ T4,T1		;SAVE ERROR REGISTER
	MOVX T2,DXGP6		;FINALLY GET POSSIBLE ERROR REASON
	CALL RDREG		;READ IT
	HRR T4,T1		;SAVE IT
	CALL FNDCKU		;SET UP CHANNEL AND CONTROLLER NUMBERS
	POP P,T3		;RESTORE STATUS REGISTER
	BUG(DX2HLT,<<T1,CHAN>,<T2,DX20>,<T3,REG1>,<T4,2AND26>>)	;COMPLAIN
	POP P,T4		;RESTORE AC
	RET			;ERROR RETURN
;ASYNST - TAKES CARE OF ANY ASYNCHRONOUS STATUS PRESENTED TO DX20,
;  WHICH IS CAUSED BY THE COMPLETION OF A REWIND
; OR AN UNIT BECOMES ON-LINE.
; P1/CDB, P2/KDB
;	CALL ASYNST
; RETURN+1: ALWAYS

ASYNST:	PUSH P,Q2		;SAVE DRIVE STATUS
	MOVE Q2,K.DXAD(P2)	;GET UNIT NUMBER OF DX20
ASYNS1:	RDRG DXGP4		;GET ASYNST STATUS
	JUMPE T1,Q2RET		;NONE, SO RETURN
	PUSH P,P3		;PRESERVE P3
	PUSH P,P4		; AND P4
	MOVX T2,DXGP4		;ZERO THE ASYNC STATUS
	CALL WTREG3		; REGISTER
	LOAD T4,DRVNUM		;GET DRIVE NUMBER IN T4
	CALL DRVSRC		;FIND THE UDB WITH THIS DRIVE NUMBER
	 JRST [	BUG(DX2DNF,<<T4,DRIVE>>)	;CAN'T FIND IT
		MOVX T2,1	;GET BIT READY
		LSH T2,(Q2)	;MASK TO CLEAR OUR ATTENTION BIT
		TXO T2,DXASR	;CLEAR THE ATTENTION
		CALL WTREG3	; BIT FOR THIS DX20
		POP P,P4	;RESTORE AC'S
		POP P,P3	;THAT WERE PUSHED
		JRST ASYNS1]	;AND LOOK FOR MORE STATUS
	CALL GTSNS		;CLEAR ATTN BIT AND GET SENSE BYTES IN T1
	 MOVX T1,S1.FP		;FAIL, MAKEUP SOME SENSE BYTES
	MOVX T2,<US.BOT!US.WLK> ;GET MASK
	ANDCAM T2,UDBSTS(P3)	;CLEAR THESE BITS FIRST
	TXNN T1,S1.BOT		;UNIT AT BOT?
	TXZ T2,US.BOT		;NO, CLEAR BOT BIT
	TXNN T1,S1.FP		;FILE-PROTECTED AS IN SENSE BYTE
	TXZ T2,US.WLK		;NO, CLEAR US.WLK IN MASK
	IORM T2,UDBSTS(P3)	;MARK INTO UDB
	MOVSI T2,(US.REW)	;SAY NO LONGER REWINDING
	ANDCAM T2,UDBSTS(P3)	;SO CLEAR THE BIT
	MOVSI T2,(US.PSI)	;SET POSSIBLE PSI
	IORM T2,UDBSTS(P3)	; FOR REWIND DONE
	MOVX T2,DXGP4		;GET ASYCHRONOUS STATUS
	CALL RDREG3		; ...
	JUMPN T1,[IOPIOF	;SEE IF ANY THERE
		CALL SCHSEK	;YES, ONLY DO SEEKS
		IOPION		;INTERRUPTS OK NOW
		POP P,P4	;RESTORE ACS
		POP P,P3
		JRST ASYNS1]	;LOOP TO SEE IF ANY MORE STATUS
	CALL PHYRWD		;LAST ONE, START IO
	POP P,P4		;RESTORE AC'S
	POP P,P3
Q2RET:	POP P,Q2		;RESTORE Q2
	RET			; AND RETURN TO CALLER
;HARCHK - CHECKS FOR ERRORS AND PUTS THE DRIVE STATUS IN Q2
; P1/CDB, P2/KDB, P3/UDB, Q1/FTN CODE, P4/IORB
;	CALL HARCHK
; RETURN+1: SOME HARD ERROR FOUND
; RETURN+2: GOOD RETURN WITH DRIVE STATUS IN Q2

HARCHK:	MOVX T1,<IS.DVE!IS.DTE>	;CLEAR DEVICE AND DATA
	ANDCAM T1,IRBSTS(P4)	; IN IRBSTS
	MOVX T1,US.WLK		;SEE IF THE UNIT IS
	TDNE T1,UDBSTS(P3)	; WRITE LOCKED?
	MOVX Q2,DS.WLK		;YES, LIGHT A BIT
	TXNE Q1,TB.TM		;WRITE TM OPERATION
	TXO Q2,DS.TM		;YES, SET WHERE IT WILL BE SEEN
	REDRG DXSTR		;READ IN THE DX20 STATUS REGISTER
	TXNN T1,SR.CER		;ANY ERROR TO INVESTIGATE?
	RETSKP			;NO ERRORS
	REDRG DXERR		;READ THE DX20 ERROR REGISTER
	TXNE T1,<ER.SPT!ER.MPE>	;IS THE DX20 HALTED?
	JRST HARCH1		;YES, GO START IT
	TXNE T1,<ER.ILF!ER.ILR!ER.RMR!ER.CPE> ;ILLEGAL FUNCTION, ILLEGAL REG, REG MOD REFUSED,
				; OR CONTROL BUS PARITY ERROR?
	JRST HARCH2		;YES, FATAL ERROR
	LOAD T2,ECC		;GET THE ERROR CLASS CODE
	JUMPLE T2,ECCERR	;0 ERROR CLASS CODE IS A FATAL ERROR
	CAILE T2,ECCSZ		;LEGAL CODE?
	JRST ECCERR		;NO, FATAL ERROR
	JRST @ECCTBL-1(T2)	;DISPATCH TO ERROR CLASS CODE

;HERE IF DX20 IS HALTED
;
HARCH1:	REDRG DXGP6		;READ IN AS THIS MIGHT CONTAIN AN ERROR CODE
	BUG (DX2DIE,<<T1,D>>)
	MOVEI T1,STADDR		;DX20 STARTING ADDRESS
	CALL STDX		;START THE DX20 RUNNING AGAIN
HARCH2:	CALL RDALL		;READ ALL DX20 REGISTERS AND EXTENDED STATUS
HERR:	MOVX T3,<IS.DVE!IS.ERR!IS.NRT> ;FLAG A FATAL
	IORM T3,IRBSTS(P4)	; ERROR IN THE IORB
	MOVX T3,US.REW		;CLEAR REWINDING
	ANDCAM T3,UDBSTS(P3)	; IN THE UDB
	MOVX T1,US.WLK		;IF WRITE LOCKED IS
	TDNE T1,UDBSTS(P3)	; SET IN THE UDB, SET
	IORM T1,IRBSTS(P4)	; WRITE LOCKED IN THE IORB
	TXO Q2,DS.ERR		;FLAG AN ERROR OCCURRED
	RET			;NONSKIP RETURN INDICATES FATAL ERROR
;ERROR CLASS CODE DISPATCH TABLE
;
ECCTBL:	ECC1			;(1) UNUSUAL DEVICE STATUS (EXAMINE ENDING STATUS REG)
	CLRERR			;(2) SHORT RECORD (NOT AN ERROR)
	CLRERR			;(3) LONG RECORD (FATAL)
				; (ERROR BITS WILL BE SET BY CKERR)
	FTLERR			;(4) DRIVE SELECTION ERROR (FATAL)
	CLRERR			;(5) TAPE MOTION (RECOVERABLE)
	NOTMOV			;(6) NO TAPE MOTION (RECOVERABLE)
	FTLERR			;(7) PARITY ERROR (FATAL)
	FTLERR			;(8) FATAL ERROR
	ECCSZ==.-ECCTBL		;LENGTH OF TABLE

;RDALL - READS ALL THE DX20 REGISTERS AND
; THE EXTENDED STATUS INTO THE KDB
; P1/CDB, P2/KDB, P3/UDB
;	CALL RDALL
; RETURN+1: ALWAYS
;
RDALL:	CALL DX2RDR		;READ DX20 REGISTERS
	MOVX T2,DXERR		;ZERO THE DX20
	CALL WTREG		; ERROR REGISTER
	CALLRET DX2REX		;READ THE EXTENDED STATUS
;HERE IF ERROR CLASS 1
;
ECC1:	REDRG DXGP0		;READ THE ENDING STATUS
	TXNN T1,ES.UEX		;UNIT EXCEPTION?
	JRST ECC1A		;NO
	TXNE Q1,TB.RD!TB.SPC	;READ OR SPACE OPERATION?
	TXO Q2,DS.TM		;YES, THEN LIGHT TAPE MARK BIT
	TXNE Q1,TB.WRT		;WRITE OPERATION?
	TXO Q2,DS.EOT		;YES, THEN LIGHT EOT BIT
ECC1A:	TXNN T1,ES.UCK		;UNIT CHECK IN ENDING STATUS?
	JRST CLRERR		;CLEAR ERROR REGISTER AND
				; SKIP RETURN
	PUSH P,T1		;SAVE ENDING STATUS ACROSS SUBROUTINE CALL
	CALL RDALL		;READ ALL DX20 REGISTERS AND EXTENDED STATUS
	POP P,T1		;RESTORE ENDING STATUS
	MOVE T2,K.DEST(P2)	;GET SENSE BYTES 0 - 3
	TXNE T2,S0.EC		;EQUIPMENT CHECK?
	JRST HERR		;YES, FATAL ERROR
	TXNE T2,S0.BOC		;BUS OUT CHECK?
	JRST ERRBOC		;YES, ANALYZE IT FURTHER
	TXNE T2,S0.IR		;INTERVENTION REQUIRED?
	JRST ERRIRQ		;YES, ANALYZE IT FURTHER
ECC1B:	TXNE T2,<S0.CR!S1.NC>	;COMMAND REJECT OR NOT CAPABLE?
	JRST HERR		;YES, FATAL ERROR
	TXNE T2,S0.OR		;OPERATION REJECTED?
	JRST ERROVR		;YES, ANALYZE IT FURTHER
	TXNE T2,S1.BOT		;AT BOT?
	JRST ERRBOT		;YES
	TXNE T2,S0.DC		;DATA CHECK
	JRST ERRDC		;YES, ANALYZE IT FURTHER
	JRST HERR		;FATAL ERROR
;HERE IF AT BOT
;
ERRBOT:	TXO Q2,DS.BOT		;YES, FLAG AT BOT
	RETSKP			;SKIP RETURN

;HERE IF BUS OUT CHECK
;
ERRBOC:	TXNN T1,ES.DVE		;DEVICE END?
	JRST NOTMOV		;NO, REISSUE COMMAND
	TXNN Q1,TB.WRT		;WRITE TYPE OPERATION?
	JRST NOTMOV		;NO, REISSUE COMMAND
	JRST RTYERR		;YES, RETRIABLE ERROR

;HERE IF INTERVENTION REQUIRED
;
ERRIRQ:	TXNN T1,ES.DVE		;DEVICE END?
	JRST HERR		;NO, HARD ERROR
	TXNN Q1,<TB.UNL!TB.REW>	;REWIND OR UNLOAD COMMAND?
	JRST ECC1B		;NO, LOOK AT SOME MORE SENSE BYTES
	JRST RSKP		;YES, JUST CONTINUE

;HERE IF OVERRUN
;
ERROVR:	TXNN Q1,TB.DOP		;DATA OPERATION?
	JRST NOTMOV		;NO, TAPE HASN'T MOVED
	JRST RTYERR		;YES, RETRIABLE ERROR

;HERE IF DATA CHECK
;
ERRDC:	TXO Q2,<DS.DC!DS.RTY!DS.ERR> ;FLAG DATA CHECK
	MOVX T1,<IS.DTE!IS.ERR>	;FLAG DATA ERROR
	IORB T1,IRBSTS(P4)	; IN THE IORB
	TXNN Q1,TB.RD		;READ OPERATION?
	RETSKP			;SKIP RETURN
	LDB T1,[POINTR K.DEST(P2),S2.TIE] ;GET THE TIE BYTE
	HRROM T1,U.ETIE(P3)	;REMEMBER TIE INFO
	RETSKP			;GIVE SKIP RETURN

ECCERR: BUG(DX2IEC,<<T1,D>>)
	JRST HARCH2

;HERE IF TAPE HASN'T MOVED
;
NOTMOV:	JRST HERR		;CALL IT HARD FOR NOW
	MOVX T1,UDB.NM		;SET FLAG IN
	IORM T1,UDBERR(P3)	; UDB TO INDICATE TAPE HASN'T MOVED
	TXO Q2,<DS.NMV!DS.ERR>	;FLAG NOT MOVED AND ERROR
	MOVX T1,<IS.ERR!IS.DVE>	;DEVICE ERROR
	IORM T1,IRBSTS(P4)	;SET IN THE IORB
	JRST CLRERR		;CLEAR ERROR, AND SKIP RETURN

RTYERR:	TXO Q2,<DS.RTY!DS.ERR>	;FLAG RETRIABLE AND ERROR
	MOVX T1,<IS.DVE!IS.DTE!IS.ERR> ;FLAG AN
	IORM T1,IRBSTS(P4)	; ERROR IN THE IORB
	RETSKP			;SKIP RETURN

FTLERR:	CALL RDALL		;READ ALL REGISTERS
	CALLRET HERR		;FLAG AS HARD ERROR

CLRERR:	MOVX T2,DXERR		;ZERO THE
	CALL WTREG		; ERROR REGISTER
	RETSKP			;SKIP RETURN
;DX2RDR - READS DX20 REGISTERS 0-6,20-24,26-37 INTO K.DREG IN THE KDB
; ALSO, K.DCNI, K.DCS1, AND K.DDBF INTO KDB
; P1/CDB, P2/KDB, P3/UDB
;	CALL DX2RDR
; RETURN+1: ALWAYS

DX2RDR:	SAVEQ			;SAVE ALL Q REGISTERS
	PUSH P,P2		;REMEMBER CURRENT KDB POINTER
	SETZB T4,Q1		;ZERO COUNTER,AC TO TEST AFTER SHIFT
	MOVX Q2,SAVBIT		;A BIT FOR EACH REGISTER TO SAVE
DX2RD1:	LSHC Q1,1		;SHIFT IN A BIT FROM Q2
	JUMPE Q1,DX2RD2		;JUMP IF THIS REG IS NOT TO BE SAVED
	HLLZ T2,T4		;GET REGISTER TO READ
	CALL RDREG		;READ A DX20 REGISTER
	MOVEM T1,K.DREG(P2)	;SAVE REGISTER IN THE KDB
	ADDI P2,1		;UPDATE KDB POINTER FOR NEXT TIME
	SETZ Q1,		;ZERO TEST AC
DX2RD2:	ADD T4,[BYTE (6) 1 (36-6) 1] ;UPDATE REGISTER NUMBER
	JUMPN Q2,DX2RD1		;DONE SAVING ALL REGISTERS?
	POP P,P2		;RESTORE KDB POINTER
	CALL ERRCNI		;GET CONI AND DATAI
	MOVEM T1,K.DCNI(P2)	;SAVE IN KDB
	MOVEM T2,K.DCS1(P2)	; ...
	MOVEM T3,K.DDBF(P2)	; ...
	RET

;DX2REX - READS IN THE EXTENDED STATUS TABLE INTO THE KDB
; P1/CDB, P2/KDB, P3/UDB
;	CALL DX2REX
; RETURN+1:ALWAYS

DX2REX:	PUSH P,Q1		;WILL USE Q1 & Q2
	PUSH P,Q2		;SO, SAVE THEM
	MOVE Q2,K.DXAD(P2)	;GET UNIT # FOR THIS DX20
	MOVSI Q1,-LK.DX2+K.DEST ;Q1 AS COUNTER AND INDEX
DX2RE1:	HRRZ T1,Q1		;GET INDEX FOR EXTENDED STATUS
	CALL GETEXS		;READ IN THE SENSE BYTES
	 JRST DX2RE2		;FAIL
	ADD Q1,P2		;ADD BASE ADDR. OF KDB
	MOVEM T1,K.DEST(Q1)	;STORE SENSE BYTES IN KDB
	SUB Q1,P2		;RESTORE Q1
	AOBJN Q1,DX2RE1		;LOOP BACK FOR THE NEXT 4 BYTES
DX2RE2:	POP P,Q2		;RESTORE Q1&Q2
	POP P,Q1		;
	RET			;RETURN
;DRVSRC - FIND THE UDB GIVEN THE DRIVE NUMBER OF A DRIVE.
;GIVEN THE 8-BIT DRIVE NUMBER, THIS ROUTINE RETURNS THE UDB FOR
;THAT DRIVE.  INDEXING INTO K.DUDB WILL NOT WORK SINCE A TABLE
;256 ENTRIES LONG WOULD BE NEEDED.
;  T4/	DRIVE NUMBER, P2/  KDB
;RETURNS:
;  +1:	NO UDB FOUND WITH THIS DRIVE NUMBER
;  +2:	P3/  ADDRESS OF THE FOUND UDB
;DESTROYS T1.




DRVSRC:	MOVSI T1,-NUMDRV	;BUILD AOBJN POINTER
	ADDI T1,K.DUDB(P2)	;POINT TO UDB TABLE
	SKIPE P3,(T1)		;ANY UDB THERE?
	CAME T4,UDBSLV(P3)	;YES, IS IT THIS UNIT?
	AOBJN T1,.-2		;NO, LOOK MORE
	JUMPL T1,RSKP		;GOOD RETURN IF FOUND IT
	RET			;ERROR RETURN
;GTRDEN - DETERMINE DENSITY OF TAPE AND STORE IN UDB
;CALLED AFTER DATA-TRANSFER AND SKIP-RECORD OPERATIONS
; P1/CDB, P2/KDB, P3/UDB
;	CALL GTRDEN
; RETURNS +1: ALWAYS, DENSITY STORED IN U.HDEN

GTRDEN:	PUSH P,Q2		;SAVE Q2
	MOVE Q2,K.DXAD(P2)	;GET DX20 UNIT# FOR GTSNS
	HRRZ T4,UDBSLV(P3)	;GET SLAVE# FOR GTSNS
	LOAD T1,USTYP,(P3)	;GET UNIT TYPE
	JRST @GTRDND-.UTT70(T1)	;DISPATCH TO DRIVE-SPECIFIC CODE

GTRDND:	IFIW!GRD70		;TU70
	IFIW!GRD71		;TU71
	IFIW!GRD72		;TU72
	IFIW!GRD73		;TU73

GRD70:	CALL GTSNS		;GET SENSE BYTES IN T1
	 JRST GTRDEX		;ERROR
	MOVEI T2,.SJDN8		;ASSUME 800 BPI
	JRST GTRDE1

GRD72:
GRD73:	CALL GTSNS		;GET SENSE BYTES
	 JRST GTRDEX		;ERROR
	MOVEI T2,.SJD62		;ASSUME 6250 BPI
GTRDE1:	TXNE T1,S3.D16		;1600-BPI FLAG SET?
	MOVEI T2,.SJD16		;YES, SAY 1600
	MOVEM T2,U.HDEN(P3)	;STORE IN UDB
GRD71:
GTRDEX:	POP P,Q2		;RESTORE Q2
	RET
	SUBTTL DISPATCH FOR DX20

DX2DSP::JRST DX2INI		;0 - INITIALIZATION
	JRST DX2SIO		;1 - START I/O
	JRST DX2INT		;2 - HANDLE INTERRUPT (DATA OPERATION OR SPACE)
	JRST DX2ERR		;3 - ERROR RECOVERY
	JRST DX2HNG		;4 - HUNG DEVICE
	RET			;5 - NOT USED
	RET			;6 - NOT USED
	JRST DX2SIO		;7 - START POSITION OPERATION
	JRST DX2ATN		;10 - ATTENTION INTERRUPT (CALLED AS MANY
				; TIMES AS THERE ARE DX20 DRAS BITS UP)
	JRST DX2PRQ		;11 - SKIP IF POSITION REQUIRED
	RET			;12 - STACK SECOND COMMAND, FAIL FOR DX20
	JRST DX2EXT		;13 - CHECK LEGALITY AND EXISTANCE OF A UNIT

DX2HNG:	MOVX T1,<IS.DVE!IS.ERR!IS.NRT> ;SET FATAL BITS
	IORM T1,IRBSTS(P4)	;AND REFRESH IT
	RET

;HERE TO DETERMINE IF THIS REQUEST SHOULD GO ON PWQ OR TWQ

DX2PRQ:	LDB T1,IRYFCN		;GET FUNCTION
	MOVE T1,DX2FTB(T1)	;GET TABLE ENTRY
	TXNN T1,TB.DOP		;DATA OPERATION?
	RETSKP			;NO - POSITION ALWAYS REQUIRED
	HRRZ T2,UDBPWQ(P3)	;YES - ANY PENDING POSITION OPERATIONS?
	JUMPE T2,R		;NONE - APPEND TO TWQ
	CAIN T2,(P4)		;AT HEAD OF PWQ?
	RET			;YES - NEXT TRANSFER
	RETSKP			;APPEND TO PWQ


;HERE TO SEE IF A PARTICULAR UNIT EXISTS ON THIS DX20.
;  Q2/	UNIT TO CHECK
;RETURNS:
;  +1:	T1/ 0	UNIT IS ILLEGAL
;	T1/ -1	NONEXISTANT UNIT
;  +2:	UNIT EXISTS


DX2EXT:	SKIPL T4,Q2		;MOVE TO RIGHT AC AND CHECK LEGALITY
	CAIL T4,MAXDRV
	 JRST RFALSE		;UNIT NUMBER IS ILLEGAL
	CALL DRVSRC		;SEE IF THIS UNIT IS EXISTANT
	 JRST RTRUE		;NO
	RETSKP			;YES, SKIP RETURN
	SUBTTL DX20 INITIALIZING ROUTINE

;DX2INI - INITIALIZATION ROUTINE
;THIS ROUTINE IS CALLED ONCE PER DX20 DRIVE ON THE SYSTEM
; AND BUILDS A KDB FOR THE DX20 AND A UDB FOR EACH TAPE DRIVE
; THAT HAS TUA OR TUB SET IN SENSE BYTE 1.
; P1/CDB Q2/DX20 NUMBER
;	CALL DX2INI
; RETURN +1: ALWAYS
; T1/KDB

DX2INI:	SAVEQ			;SAVE REGISTERS
	JUMPGE P6,INILB		;CHECK FOR ONLY 1 UNIT
	MOVE P2,CDBIUN(P1)	;GET KDB ADDRESS IF IT EXISTS
	ADD P2,Q2		;POINT TO CORRECT UNIT
	MOVE P2,0(P2)		;GET ENTRY
	SKIPE P3,P2		;FOUND ONE?
	JRST INILA		;ALREADY GOT ONE
INILB:	CALL CHKMIC		;CHECK THE MICROCODE IN DX20
	  JRST [BUG(DX2MCF)
		RET]
	MOVX T1,LK.DX2		;LENGTH OF KDB
	CALL PHYALC		;RESERVE SPACE
	  RET			;RETURN IF NO SPACE FOUND
	MOVE P2,T1		;SAVE ADDRESS OF KDB IN PROPER AC
	MOVE P3,T1		;NEED POINTER OF KDB ALSO IN P3
	MOVEI T1,.BTKDB		;MARK AS A KDB
	DPB T1,USYBKT		;SET .BTKDB IN KDB
	CALL GTVER		;PUT MICROCODE VERSION NUMBER IN T2
	MOVEM T1,K.DVER(P2)	;SAVE DX20 MICROCODE VERSION IN THE KDB
	MOVEI T1,STADDR		;STARTING ADDRESS OF DX20
	CALL STDX		;START THE DX20 MICROCODE
	MOVX T1,.UTDX2		;SET UP UNIT TYPE IN KDB
	STOR T1,USTYP,(P2)	;THIS IS A DX20 CONTROLER
	MOVSI T1,-NUMDRV	;SET UP AOBJN INDEX
	HRRI T1,K.DUDB(P2)	;MAKE RH POINT TO UDB ENTRIES IN KDB
	MOVEM T1,KDBIUN(P2)	;INITIAL POINTER
	MOVEM T1,KDBCUN(P2)	;CURRENT POINTER
	HRRZM Q2,K.DXAD(P2)	;SAVE KDB ADDRESS
	MOVEI T1,DX2DSP		;INSERT DISPATCH VECTOR
	MOVEM T1,KDBDSP(P2)	; ...
	SETZM K.DNUM(P2)	;CLEAR NUMBER OF UDB'S IN EXISTANCE
INILA:	MOVE Q1,P5		;GET SLAVE NUMBER
	SKIPGE P6		;ONLY 1 UIT
	TLOA Q1,-1		;YES DO ONLY 1 TIME
	MOVSI Q1,-MAXDRV	;SLAVE INDEX
INILP:	HRRZ T4,Q1		;GET CURRENT SLAVE #
	CALL GTSNS		;GET SENSE BYTES(0-3) IN T1
	  JRST NODRV		;FAIL TO GET SENSE BYTES, TRY NEXT
	TXNN T1,S1.TUA+S1.TUB	;IS IT IN EXISTENCE?
	JRST NODRV		;NO, JUMP
	MOVE Q3,T1		;SAVE SENSE BYTES 0-3
	MOVE T3,K.DNUM(P2)	;GET NUMBER OF DRIVES FOUND SO FAR
	CAIL T3,NUMDRV		;ROOM IN K.DUDB TABLE?
	JRST TOORET		;NO, GO COMPLAIN
	SKIPN T3,MTINDX		;GET AOBJN INDEX TO LOGICAL TABLE
	HRLOI T3,-MTAN-1	;IF 1ST TIME THRU
	AOBJP T3,TOORET		;LOSE IF TOO MANY DRIVES
	MOVEM T3,MTINDX		;SAVE CURRENT LOGICAL INDEX
	MOVE T3,[DX2DSP,,LU.DX2] ;SET UP ADDRESS,,LENGTH
	CALL PHYUDB		;AND ASK FOR UDB ALLOCATION
	  RET			;RETURN IF NO SPACE FOUND
	AOS T3,K.DNUM(P2)	;ADVANCE TO NEXT FREE UDB ENTRY
	ADDI T3,K.DUDB-1(P2)	;POINT TO THE NEW TABLE ENTRY
	HRRZM P3,(T3)		;SAVE LINK
	HRRZM P2,UDBKDB(P3)	;SAVE BKWDS LINK
	MOVE T3,MTINDX		;GET CURRENT LOGICAL INDEX
	HRLZM P1,MTCUTB(T3)	;SAVE LINK TO CDB IN LOGICAL TABLE
	HRRM P3,MTCUTB(T3)	;SAVE LINK TO UDB
	MOVX T3,US.TAP		;T3 AS MASK FOR UDBSTS, ITS TAPE UNIT
	TXNE Q3,S1.FP		;WRITE-PROTECTED?
	TXO T3,US.WLK		;YES, MARK IT
	HLLM T3,UDBSTS(P3)	;SAVE STATUS IN UDB
	SETOM U.HDEN(P3)	;INDICATE UNKNOWN DENSITY
	MOVEI T1,1		;INDEX FOR SENSE BYTES 4 - 7
	CALL GETEXS		;READ IN SENSE BYTES 4 - 7 INTO T1
	 JRST UPERR		;UPDATE FAILED
	MOVX T2,.UTT70		;ASSUME TU70 (800/1600 9 TRK)
	TXNE T1,S6.DD		;IS IT 1600/6250?
	MOVX T2,.UTT72		;CALL IT A TU72 (1600/6250 9TRK)
	TXNE T1,S6.7TK		;IS IT A 7 TRK DRIVE?
	MOVX T2,.UTT71		;CALL IT A TU71 (200/556/800 7TRK)
	STOR T2,USTYP,(P3)	;PUT UNIT TYPE IN UDB
	MOVE T1,[	UC.800!UC.160!UC.CD!UC.AA!UC.IC!UC.HD ;TU70
			UC.200!UC.556!UC.800!UC.6B!UC.7TK ;TU71
			UC.160!UC.625!UC.CD!UC.AA!UC.IC!UC.HD ;TU72
			UC.160!UC.625!UC.CD!UC.AA!UC.IC!UC.HD ]-.UTT70(T2) ;TU73
	MOVEM T1,UDBCHR(P3)	;STORE DENSITYS DRIVE IS CAPABLE OF
				; IN THE UDB
	MOVEI T1,3		;INDEX=3 FOR SENSE BYTES
	CALL GETEXS		;READ IN SENSE BYTES 12 - 15
	  JRST UPERR		;JUMP, ERROR
	ANDI T1,377		;TAKE BYTE 15 ONLY
	MOVE Q3,T1		;TUCK IT AWAY FOR AWHILE
	MOVEI T1,4		;INDEX=4 FOR SENSE BYTES
	CALL GETEXS		;READ IN SENSE BYTES 16 - 19
	  JRST UPERR		;ERROR, JUMP
	LSH T1,-^D26		;BYTE 16 AS LOW ORDER BYTE
	LSH Q3,^D8		;MAKE BYTE 15 HIGH ORDER BYTE
	IOR T1,Q3		;CONCATENATE INTO T1, AS SERIAL NUMBER
	JUMPN T1,GOTSER		;0 IF TU70, OR TU71
	HRRZ T1,Q1		;GET PHYSICAL UNIT NUMBER ON THIS DX20
	HRRZ T2,Q2		;GET DX20 NUMBER ON THIS CHANNEL
	IMULI T2,^D100		;MAKE KONTROLLER IN THE 100s
	ADD T1,T2		;INCLUDE KONTROLLER NUMBER
	HRRZ T2,CDBADR(P1)	;GET THE RH20 CONTROLLER NUMBER
	IMULI T2,^D1000		;MAKE RH20 CONTROLLER NUMBER IN 1000s
	ADD T1,T2		;PRESTO  RH20#,DX20#,TAPE#
GOTSER:	MOVEM T1,UDBDSN(P3)	;STORE SERIAL NUMBER FOR THE TAPE UNIT
	HRRZM Q1,UDBSLV(P3)	;SET UP SLAVE ADDRESS
NODRV:	MOVX T2,DXERR		;CLEAR THE DX20
	CALL WTREG3		; ERROR REGISTER
	AOBJN Q1,INILP		;TRY NEXT SLAVE
	MOVE T1,P2		;TELL RETURN TO PUT KDB INTO CDB
	RET
	
TOORET:	BUG(DX2N2S)		;COMPLAIN ABOUT EXCESS OF DRIVES
	MOVE T1,P2		;TELL RETURN TO PUT KDB INTO CDB
	RET

UPERR:	BUG(DX2UPE)
	RET			;RETURN
;CHKMIC - CHECKS THE MICROCODE IN DX20, TO SEE IF IT IS THE RIGHT ONE
; BY LOOKING INTO CRAM LOCATIONS 7 - 11
; P1/CDB, Q2/DX20 UNIT NUMBER
;	CALL CHKMIC
; RETURN+1: ERROR RETURN
; RETURN+2: GOOD RETURN

CHKMIC:	MOVX T2,DXMTR!MR.RES	;RESET THE
	CALL WTREG3		; DX20
	MOVX T2,DXDR1!D1.IRE!D1.PCE!D1.PCI!7 ;SETUP PC AND
	CALL WTREG3		; FLAGS INTO THE PC REG
	RDRG DXDR0		;READ IR REG. SO TO GET C(LOC 7) OF CRAM
	PUSH P,T1		;SAVE IT
	RDRG DXDTR		;GET DRIVE TYPE REG.
	POP P,T2		;RESTORE LOCATION 7 OF CRAM
	CAME T1,T2		;DRIVE TYPE MATCH?
	  RET			;NO, ERROR RETURN
	RDRG DXDR7		;CHECK ANY PARITY ERROR
	TXNE T1,1B22		;IRPER=1B22
	  RET			;ERROR
	RDRG DXDR0		;GET LOC.10
	CAIE T1,100		;IS LOCATION 10 = 100?
	  RET			;NO, ERROR
	RDRG DXDR7		;CHECK IR PARITY ERROR
	TXNE T1,1B22		;IRPER=1B22
	  RET			;ERROR RETURN
	RDRG DXDR0		;GET LOC.11
	CAIE T1,042562		;042562 IS THE MAGIC NUMBER
	  RET			;ERROR
	RDRG DXDR7		;CHECK IR PARITY ERROR
	TXNE T1,1B22		;IRPER=1B22
	  RET			;ERROR
	RETSKP			;GOOD RETURN
	SUBTTL START I/O ROUTINE

;DX2SIO - ROUTINE TO START I/O
; P1/CDB, P2/KDB, P3/UDB, P4/IORB
;IF IN ERROR RECOVERY, GET FUNCTION FROM RH(UDBERR)
;	CALL DX2SIO
; RETURN +1: ERROR - COULDN'T START I/O
; RETURN +2: SUCCESS THROUGH CHSTRT

DX2SIO:	HRRZ Q1,UDBERR(P3)	;GET FUNCTION IF ERROR RECOVERY
	SKIPN Q1		;IN ERROR RECOVERY?
	LOAD Q1,ISFCN,(P4)	;NO, GET FN FROM IORB
	SKIPG Q1,DX2FTB(Q1)	;VALID FN?
	JRST BADSIO		;REFUSE TO START IT

	SKIPGE IRBSTS(P4)	;MAKE SURE PAGEM NOT SET
	JRST BADSIO		;IS SET REFUSE IT
	CALL DX2CON		;CONNECT TO DRIVE (AND CLEAR ERRORS)
	 RET			;ERROR
	MOVX T2,DO.FC		;IN CASE WE DON'T WANT TO LOAD FC
	TXNE Q1,TB.NFC		;DO WE LOAD FC WITH SOMETHING SPECIAL?
	JRST NOFC		;NO- LOAD 0
	TXNN Q1,TB.DOP		;DATA OPERATION?
	JRST DX2NDO		;NO, T2=-#RECORDS ON SPACE
	MOVN T2,IRBCNT(P4)	;BYTE COUNT FROM IORB
	LOAD T1,IRBDM,(P4)	;GET DATA MODE
	CAIE T1,.SJDMH		;IS IT HIGH DENSITY MODE?
	JRST DX2SI1		;NO, JUMP
	IDIVI T2,2		;EVEN BYTE(36-BIT) COUNT?
	JUMPN T3,BADSI1		;ODD IS BAD FOR HI-DEN. MOD
DX2SI1:	HLRZ T1,Q3		;GET MULTIPLIER
	JUMPE T1,DX2DO		;SAVE TIME IF FRAMES=BYTES
	IMUL T2,T1		;CALCULATE # FRAMES
	JRST DX2DO		;WE'RE A DATA OPERATION

BADSIO:	BUG(DX2IFS,<<Q1,D>>)
BADSI1:	MOVX T1,<IS.ERR!IS.DVE!IS.NRT> ;MARK AN ERROR OCCURED
	IORM T1,IRBSTS(P4)	;IN IORB
	RET


DX2NDO:	SKIPE UDBERR(P3)	;IN ERROR RECOVERY?
	SKIPA T2,[-1]		;YES, SPACE 1 RECORD
	MOVN T2,IRBCNT(P4)	;NO, DO # RECORDS FROM IORB
DX2DO:	ANDI T2,177777		;16 BITS OF FRM COUNT
	HRLI T2,(DO.FC)		;DO FRM COUNT TO FRM COUNT REGISTER
NOFC:	ANDI Q1,77		;6 BITS OF DX20 FN
	HRRZM P3,K.SUDB(P2)	;SAVE CURRENT UDB IN KDB
	JRST CHSTRT		;NOW START THINGS MOVING
;DX2CON - LOAD DRIVE NUMBER, DATA MODE AND DRIVE NUMBER INTO
; THE DX20. IF DOING ERROR RECOVERY AND THERE IS A TRACK-IN-ERROR
; BYTE (U.ETIE IS NEGATIVE) LOAD IT INTO THE DX20 AFTER
; LOADING THE DRIVE REGISTER.
; P1/CDB, P2/KDB, P3/UDB, & P4/IORB, AND Q1/ FUNCTION TABLE ENTRY
;	CALL DX2CON
; RETURN+1: ERROR
; RETURN+2: GOOD RETURN
; Q3/NUMBER OF FRAMES PER BYTE

DX2CON:	CALL HLTCHK		;MAKE SURE MICROCODE IS GOING
	 JRST BADSI1		;NO, ABORT THE I/O
	HRRZ T1,UDBSLV(P3)	;GET THE SLAVE NUMBER INTO T1
				; THIS AC WILL BE USED ALSO TO PUT
				; THE DRIVE MODE AND DATA MODE INTO
	LOAD T4,USTYP,(P3)	;GET THE DRIVE TYPE
	SUBI T4,.UTT70		;MAKE 0 FOR TU70, 1 FOR TU71, 2 FOR TU72
				; AND 3 FOR TU73
	MOVE Q2,T4		;NEED ANOTHER COPY LATER
	MOVE Q3,UDBSTS(P3)	;GET THE STATUS FROM THE UDB
	MOVX T2,TB.RD!TB.WRT	;IF A TU71 THEN WE NEED TO DO A MODE
				; SET FOR EACH READ OR WRITE OPERATION
	CAIN Q2,.UTT71-.UTT70	;IS IT A TU71 (7 TRACK)
	JRST DX2CO2		;YES
	TXNN Q3,US.BOT		;AT BOT?
	JRST NOMOD		;NO, MODE SET NOT REQUIRED THEN
	MOVX T2,TB.WRT		;ONLY DO MODE SET ON TU70, TU72, TU73
				; IF A WRITE OPERATION OFF OF BOT
DX2CO2:	TDNN Q1,T2		;NEED TO DO A MODE SET?
	JRST NOMOD		;NO
	LSH T4,1		;MUL BY 2 FOR TABLE OF DENSITYS
				; THERE ARE 2 ENTRYS FOR EACH DRIVE
				; TYPE. (ODD AND EVEN PARITY)
	LOAD T3,IRBPAR,(P4)	;GET 1 BIT OF PARITY INFORMATION
	ADD T4,T3		;POINT TO THE ODD OR EVEN ENTRY
	LOAD T2,IRBDN,(P4)	;GET THE DENSITY REQUESTED
	CAILE T2,MAXDN		;DO WE ALLOW IT?
	JRST BADSI1		;NO, ILLEGAL DENSITY
	LDB T3,DENPNT(T4)	;GET ENTRY FROM THE DENSITY TABLE
				; (T2 IS USED AS AN INDEX IN THE
				; BYTE POINTER IN DENTAB)
	CAIN T3,DRV.IL		;ILLEGAL DENSITY FOR THIS DRIVE TYPE?
	JRST BADSI1		;YES
	STOR T3,DRVMOD		;PUT DRIVE MODE IN T1
NOMOD:	TXNN Q1,TB.RD!TB.WRD	;READ OR WRITE DATA OPERATION?
	JRST NODMOD		;NOT A DATA TYPE OPERATION SO
				; DON'T CHECK IF DATA MODE IS LEGAL
	LOAD T2,IRBDM,(P4)	;GET THE DATA MODE REQUESTED
	CAILE T2,MAXFN		;DO WE ALLOW IT?
	JRST BADSI1		;NO
	SKIPG Q3,@FMTTAB(Q2)	;GET A COPY OF THE DX20 CODE FOR THIS
				; TYPE OF DRIVE AND MODE REQUESTED
				; (T2 IS USED AS AN INDEX IN FMTTAB)
				;NEGATIVE INDICATES THE DATA MODE IS
				; ILLEGAL FOR THIS TYPE OF DRIVE
	JRST BADSI1		;ILLEGAL DATA MODE
	STOR Q3,DATMOD		;STORE DATA MODE IN T1
NODMOD:	WRTRG DXGP1,(T1)	;TELL DX20 - DATA MODE, DRIVE MODE, DRIVE NUMBER
	SKIPL T2,U.ETIE(P3)	;TRACK IN ERROR?
	RETSKP			;GIVE WIN RETURN
	TXO T2,TE.TIE		;YES, REQUEST TIE RECOVERY
	HRLI T2,(DXGP3)		;REGISTER 23
	CALL WTREG		;TELL DX20 TIE RECOVERY
	SETZM U.ETIE(P3)	;CLEAR
	RETSKP			;SKIP RETURN
	SUBTTL ENTER HERE FROM RH20 COMMAND DONE INTERRUPT

;DX2INT - COME HERE TO PROCESS A DONE INTERRUPT.
; P1/CDB, P2/KDB
; IF K.SUDB IS -1 IN THE LH THEN THERE WAS AN ATTENTION
; INTERRUPT PRECEDING THE DONE INTERRUPT AND A CHECK MUST
; BE MADE FOR ERRORS. THIS ALLOWS FASTER PROCESSING OF THE
; DONE INTERRUPT (NORMAL CASE) BUT DEPENDS UPON THE DX20
; GIVING AN ATTENTION INTERRUPT IF THERE IS AN ERROR 
; CONDITION.  THIS ROUTINE IS ONLY ENTERED FOR DATA TYPE
; OPERATIONS.
;	CALL DX2INT
; RETURN+1: ERROR
; P3/UDB P4/IORB
; RETURN+2: NO ERROR
; P3/UDB P4/IORB

DX2INT:	PUSH P,Q2		;
	PUSH P,Q1		;WILL USE Q1 & Q2
	SKIPN P3,K.SUDB(P2)	;UDB SAVED ON THIS DX20?
	JRST DX2INU		;NO, ERROR
	SETZM K.SUDB(P2)	;CLEAR THE CURRENT UDB
	CALL SETIRB		;GET IORB POINTER INTO P4
	HRRZ T4,UDBERR(P3)	;GET FTN CODE IF ERROR RECOVERY
	SKIPN T4		;IN ERROR RECOVERY?
	LOAD T4,ISFCN,(P4)	;NO, GET FTN CODE FROM IORB
	MOVE Q1,DX2FTB(T4)	;GET FTN TABLE ENTRY IN Q1
	SETZ Q2,		;CLEAR FLAG WORD
	TLZN P3,-1		;WAS THERE AN ATTENTION INTERRUPT?
	JRST DXENTY		;NO
	CALL HARCHK		;GO CHECK IF ANY FATAL ERROR
				; AND SETUP DRIVE STATUS IN Q2
	 JRST INTRET		;ERROR, JUST RETURN
	TXNE Q2,DS.NMV		;TAPE MOVED?
	JRST INTRET		;NO, RECOVERABLE ERROR
DXENTY:	TXNE Q1,TB.REV		;ARE WE BACKWARDS?
	SOSA UDBPS2(P3)		;YES, THEN SUBTRACT 1 RECORD
	AOS UDBPS2(P3)		;NO, ADD 1
	JUMPE Q2,CKCON1		;QUICK PATH? (BIT 14 NOT SET IN STATUS REG)
	TXNN Q2,DS.TM		;IS IT TAPE MARK?
	JRST NOTM		;NOT TM
	TXNE Q1,TB.REV		;ARE WE REVERSE
	SOSA UDBPS1(P3)		;YES, BACK UP 1 FILE
	AOS UDBPS1(P3)		;NO, FORWARD 1 FILE
NOTM:	TXNE Q2,DS.BOT		;AT BOT?
	CALL ATBOT		;YES, ZERO COUNTERS
NOBOT:	TXNE Q2,DS.RTY		;RETRIABLE ERROR?
	JRST INTRET		;YES, ERROR BITS SET IN IORB
CKCONI:	TXNN Q1,TB.DOP		;DATA OPERATION?
	JRST NOTWRT		;NO, DON'T CHECK CHANNEL
CKCON1:	CALL CKERR		;SEE IF ANY CHANNEL ERRORS
	 SKIPA			;YES
	JRST NODERS		;NO CHANNEL ERRORS
	MOVX T3,<IS.ERR!IS.DTE>	;YES, ERROR- DO RETRY
	IORM T3,IRBSTS(P4)	;SET IORB ERR (DATA ERR)
	CALL RDALL		;GET ALL REGISTERS INTO THE KDB
	JRST INTRET		;JUST RETURN
				; DON'T BOTHER SETTING UP STATUS BITS

;HERE WHEN DONE INTERRUPT AND NO SAVED UDB

DX2INU:	BUG(DX2NUD)
	JRST INTRX		;GO CHECK ERROR AND ASYNCHR. STATUS
NODERS:	TXNN Q1,TB.RD		;ARE WE READING?
	JRST SPENTY		;NO, DON'T TELL ABT FRM COUNT
	MOVX T1,US.BOT		;WERE WE AT BOT?
	TDNE T1,UDBSTS(P3)	; ???
	CALL GTRDEN		;YES - TRY TO FIGURE OUT DENSITY
	MOVX T2,DO.FC		;GET FRM COUNT
	CALL RDREG		;
	ADDM T1,UDBRED(P3)	;ACCUMULATE FRAMES READ
	AOS UDBRCT(P3)		;UPDATE READ COUNT
	CALL CHKMOD		;GET AND CHECK DATA MODE
	CAIN T2,.SJDMH		;HI-DENSITY MODE?
	LSH T1,1		;MUL BY 2 SINCE WHEN CALCULATING
				; NUMBER OF BYTES READ WE FIGURE FOR 2 WORDS
	JUMPE T3,NODIV		;SAVE TIME IF FRAMES=BYTES
	IDIV T1,T3		;CALCULATE # BYTES
	SKIPE T2		;REMAINDER?
	ADDI T1,1		;YES, ANOTHER BYTE
NODIV:	MOVEM T1,IRBCNT(P4)	;TELL HOW MANY FRAMES ON READ
SPENTY:	TXNN Q1,TB.WRD		;WRITE DATA?
	JRST NOTWRT		;NO
	CALL CHKMOD		;GET AND CHECK DATA MODE
	MOVE T1,IRBCNT(P4)	;GET NUMBER OF FRAMES
	CAIN T2,.SJDMH		;HI-DENSITY MODE
	LSH T1,-1		;
	IMUL T1,T3		;MAKE FRAMES
	ADDM T1,UDBWRT(P3)	;ACCUMULATE FRAMES WRITTEN
	AOS UDBWCT(P3)		;UPDATE WRITE COUNT
NOTWRT:	MOVX T2,<IS.BOT!IS.EOT!IS.TPM!IS.WLK> ;ZERO BITS
	ANDCAM T2,IRBSTS(P4)	;DO IT TO IT
	MOVX T3,<US.BOT>	;CLEAR BITS
	ANDCAM T3,UDBSTS(P3)	; IN THE UDB
	JUMPE Q2,INTRET		;QUICK WAY THROUGH?
	TXNN Q2,DS.BOT		;AT BOT?
	TXZ T2,IS.BOT		;NO
	TXNE Q1,TB.WRT		;ARE WE WRITING?
	TXNN Q2,DS.EOT		;AND AT EOT?
	TXZ T2,IS.EOT		;NO TO EITHER
	TXNN Q2,DS.TM		;TP MK 
	TXZ T2,IS.TPM		;NO, CLEAR TM FLAG
	TXNE Q1,TB.REV		;SPACE REVERSE OR READ REVERSE
	TXNN Q2,DS.BOT		;AND AT BOT?
	SKIPA			;NO TO EITHER
	TXO T2,IS.TPM		;YES TO BOTH,RETURN TAPE MARK
	TXNN Q2,DS.WLK		;WRITE LOCKED?
	TXZ T2,IS.WLK		;NO
	IORM T2,IRBSTS(P4)	;AND SAVE IT (LEAVE ERR SET IF IT WAS SET)
	TXNN Q2,DS.BOT		;AT BOT?
	TXZ T3,US.BOT		;NO, CLEAR BIT
	IORM T3,UDBSTS(P3)	;SAVE IT
INTRET:	SKIPN UDBERR(P3)	;IN ERROR RECOVERY?
	JRST INTR1		;NO, JUMP
	MOVX T3,<IS.ERR!IS.DTE!IS.DVE> ;YES, IN ERROR RECOVERY
	TDNN T3,IRBSTS(P4)	;WAS IN ERROR?
	CALL DX2RDR		;NO, COPY REGISTERS FOR ERROR BLOCK LOGGING
INTR1:	CALL ASYNST		;GO TO TAKE CARE OF ANY ASYNCHRONOUS
				; STATUS AND CLEAR THE ATTENTION BIT
INTR3:	TXNE Q2,DS.ERR		;ANY KIND OF ERROR?
	JRST INTR4		;YES, THEN NEVER SKIP RETURN
	TXNE Q1,TB.DOP		;DATA OPERATION?
	AOS -2(P)		;YES, SKIP RETURN FROM CMD DONE INT
INTR4:	POP P,Q1		;POP STACK
	POP P,Q2		;
	RET			;RETURN

;COMES HERE WHEN INTERRUPT AND NO UDB SAVED


INTRX:	MOVE Q2,K.DXAD(P2)	;GET UNIT NUMBER OF DX20
	RDRG DXSTR		;GET STATUS REGISTER
	TXNN T1,SR.CER		;COMPOSITE ERROR BIT SET?
	JRST INTRX2		;NO, GO CHECK ASYNCHR. STATUS
	MOVE T4,T1		;REMEMBER THE STATUS REGISTER
	RDRG DXERR		;READ IN ERROR REGISTER
	BUG(DX2NUE,<<T4,D>,<T1,D>>)
	MOVX T2,DXERR		;CLEAR THE DX20
	CALL WTREG3		; ERROR REGISTER
INTRX2:	SETZB Q1,Q2		;ZERO FUNCTION AND STATUS
	JRST INTR1		;CHECK ASYNST STATUS


;COME HERE TO CHECK IF MODE IS LEGAL
;C(P3) = UDB C(P4) = IORB
;	CALL CHKMOD
;RETURN+1: ALWAYS
;C(T2) DATA MODE FROM IORB
;C(T3) NUMBER OF FRAMES PER BYTE
;C(T4) 0 FOR TU70, 1 FOR TU71, 2 FOR TU72
;
CHKMOD:	LOAD T4,USTYP,(P3)	;GET TYPE OF DRIVE
	SUBI T4,.UTT70		;MAKE 0, 1, OR 2. (TU70, TU71, TU72)
	LOAD T2,IRBDM,(P4)	;GET DATA MODE
	CAIG T2,MAXFN		;RANGE CHECK THE FUNCTION
	SKIPGE T3,@FMTTAB(T4)	;GET BYTES,,DX20 FUNCTION
	JRST CHKMO1		;ILLEGAL
	HLRZS T3		;RETURN FRAMES PER BYTE IN T3
	RET			;RETURN
CHKMO1:	BUG(DX2IDM,<<T2,D>>)
	SETZ T3,		;ACT LIKE WORDS
	RET			;RETURN
SUBTTL	ATTENTION INTERRUPT HANDLING

;DX2ATN - COME HERE ON AN ATTENTION INTERRUPT
; THIS ROUTINE IS CALLED FOR ANY NONE DATA OPERATION AND ANY
; DATA OPERATION THAT HAS AN ERROR ASSOCIATED WITH IT.
; P1/CDB, P2/KDB
;IF ERR, IS.ERR AND EITHER <IS.DVE OR IS.DTE> WILL BE SET IN THE IORB
;IF IS.ERR NOT SET, WE ARE FINISHED WITH THIS IORB
; RETURN +1: IF ERROR
; P3/UDB IF ANY
; P4/0 IF DATA TYPE OPERATION
; RETURN +2: IF NO ERROR
; P3/UDB

DX2ATN:	PUSH P,Q2		;SAVE Q2
	MOVE Q2,K.DXAD(P2)	;GET OUR MASSBUS ADDRESS
	MOVX T2,1		;
	LSH T2,(Q2)		;MASK TO CLEAR OUR ATTENTION BIT
	TXO T2,DXASR		;CLEAR THE ATTENTION
	CALL WTREG3		; BIT FOR THIS DX20
	PUSH P,Q1
	SETZ Q2,		;CLEAR FLAG WORD
	HRRZ P3,K.SUDB(P2)	;GET ACTIVE UDB (IF ANY)
	JUMPE P3,INTRX		;IF NO UDB, JUMP
	MOVX T1,US.ACT		;UNIT ACTIVE?
	TDNE T1,UDBSTS(P3)	; ??
	JRST CKNDOP		;YES
	BUG(DX2UNA)
	SETZB P3,K.SUDB(P2)	;RESET SAVED UDB
	JRST INTRX		;CHECK ERROR & ASYN. STATUS
CKNDOP:	CALL SETIRB		;GET CURRENT IORB
	HRRZ Q1,UDBERR(P3)	;GET FUNCTION CODE
	SKIPN Q1		;IN ERROR RECOVERY?
	LOAD Q1,ISFCN,(P4)	;NO, GET IT FROM IORB
	MOVE Q1,DX2FTB(Q1)	;GET FUNCTION ENTRY
	TXNN Q1,TB.DOP		;DATA OPERATION?
	JRST NDOP		;NO

	MOVEI P4,0		;YES, ENSURE RECALL AT INTERRUPT ENTRY
	HRROS K.SUDB(P2)	;FLAG ATTN INT
	JRST INTR4		;AND EXIT AS SOON AS POSSIBLE
NDOP:	SETZM K.SUDB(P2)	;CLEAR SAVED UDB
	CALL HARCHK		;ANY FATAL ERRORS? (PUT DRIVE STATUS IN Q2,
				; DX2FTB ENTRY IN Q1)
	  JRST INTRET		;YES, FATAL ERROR FOUND & RETURN

	TXNE Q1,TB.TM		;WRITE TM OPERATION?
	JRST DXENTY		;YES, USE DATA ROUTINES
	TXNE Q1,TB.ERA		;ERASE OPERATION?
	JRST NOTWRT		;YES, DON'T CHECK TAPE POSITION
	TXNE Q1,TB.REW		;REWIND?
	JRST REWSTA		;YES, CLEAR REC CNTRS
	MOVX T1,US.BOT		;WERE WE AT BOT?
	TDNE T1,UDBSTS(P3)	; ???
	CALL GTRDEN		;YES - GET HARDWARE DENSITY
	MOVX T2,DO.FC
	CALL RDREG
	MOVN T3,T1		;NEGATE FRM COUNT
	ANDI T3,177777		;ITS ONLY 16 BIT NEG NR
	TXNE Q2,DS.TM		;FILE MARK?
	SUBI T3,1		;SPACING OVER A FILE MARK DOESN'T
				; COUNT IN THE REGISTER BUT WE TREAT
				; FILE MARKS AS RECORDS
	SKIPE T1,UDBERR(P3)	;ARE WE IN ERR RECOVERY?
	JRST RTYATN		;YES
	EXCH T3,IRBCNT(P4)	;SAVE RESIDUE (# RECORDS NOT SPACED)
	SUB T3,IRBCNT(P4)	;CALCULATE # RECORDS MOVED
	TXNE Q1,TB.REV		;IN REVERSE DIR?
	MOVNS T3		;YES, NEGATE
	ADDM T3,UDBPS2(P3)	;UPDATE REC COUNT
	MOVE T3,IRBCNT(P4)	;GET FRM COUNT AGAIN
	JUMPE T3,NOCKER		;IF ALL RECORDS SPACED, DON'T CHECK ERR
RES1:	TXNN Q2,DS.BOT!DS.EOT!DS.TM ;EARLY TERM OK IF EOT, BOT, OR TM
RESERR:	JRST [	MOVX T1,IS.ERR!IS.DVE!IS.NRT ;INDICATE ERRORS
		IORM T1,IRBSTS(P4)
		JRST SPENTY]

	; ...
	; ...
;ALL RECORDS SPACED, DON'T BOTHER CHKING ERROR BITS


NOCKER:	TXNN Q2,DS.TM		;TAPE MK?
	JRST NOSTM		;NO
	TXNE Q1,TB.REV		;IN REVERSE DIR?
	SOSA UDBPS1(P3)		;YES, THEN -1
	AOS UDBPS1(P3)		;NO, THEN +1 FILE
NOSTM:	TXNE Q2,DS.BOT		;AT BOT?
REWENT:	CALL ATBOT		;CLEAR COUNTERS
	JRST SPENTY		;NOW SET STATUS AND RET

REWSTA:	MOVX T1,US.REW		;SET REWINDING
	IORM T1,UDBSTS(P3)	; IN THE UDB
	JRST REWENT		;

				;COME HERE AT END OF SPACE DURING RETRY
RTYATN:	JUMPN T3,RTYAT2		;FRAME COUNT 0?
	TXNN Q1,TB.REV		;IN REVERSE DIRECTION?
	AOSA T1,UDBPS2(P3)	;NO FORWARD THE RECORD COUNTER
	SOS T1,UDBPS2(P3)	;YES, BACK IT UP
	TXNN Q2,DS.BOT		;AT BOT?
	JUMPGE T1,NOCKER	;ONLY JUMP IF RECORD COUNT
				; DIDN'T GO NEGATIVE
	JRST RESERR		;CONFUSED ERROR RECOVERY
RTYAT2:	SKIPE U.ETCF(P3)	;TAPE CLEANER SEQUENCE?
	TXNN Q2,DS.BOT		;YES, DID WE BACK INTO BOT?
	JRST RESERR		;NOT CLEANER SEQ
	JRST REWENT		;UPDATE OUR POSITION

ATBOT:	SETZM UDBPS1(P3)	;FILE 0
	SETZM UDBPS2(P3)	;RECORD 0
	SETOM U.HDEN(P3)	;INDICATE UNKNOWN HARDWARE DENSITY
	RET			;RETURN TO CALLER
	SUBTTL ERROR RETRY ENTRY POINT

;DX2ERR - HERE TO ATTEMPT ERROR RECOVERY
; P1/CDB, P2/KDB, P3/UDB, Q1/ERROR BLOCK ADDRESS IF ANY
;	CALL DX2ERR
; RETURN+1:
; RETURN+2:

DX2ERR:	SAVEQ
	CALL SETIRB		;GET OUR IORB
	HRRZ Q1,UDBERP(P3)	;GET ERROR BLOCK IF PRESENT
	HLLZ T1,IRBSTS(P4)	;GET IORB STATUS
	HRRZ T4,UDBERR(P3)	;GET FUNCTION IF ERROR RECOVERY
	SKIPN T4		;IN ERROR RECOVERY?
	LOAD T4,ISFCN,(P4)	;NO, GET FN FROM IORB
	MOVE T4,DX2FTB(T4)	;NOW TABLE ENTRY
	TXNN T1,<IS.NRT!IS.IER>	;FATAL OR INHIBIT ERR RECOVERY?
	JRST DXERTY		;NO, RETRY THE ERROR
	SKIPE U.EBP(P3)		;WAS FATAL ERR DURING RETRY?
	JRST ABTNOS		;YES, WE ALREADY HAVE BEGIN DATA
	AOS (P)			;SKIP RET FROM BEGLOD - DONE WITH IORB
	JRST BEGLOD		;LOAD UP ERR BLK FOR FATAL ERR

				;DO RETRY
DXERTY:	HLR T4,T4		;COPY LH OF FNTBL
	TRZ T4,777770		;SAVE ONLY RETRY INDEX IN RH
	SKIPE UDBERC(P3)	;1ST TIME FOR HERE?
	JRST NOT1ST		;NO
	SETZM U.ETCF(P3)	;NOT DOING TAPE CLEAN
	SKIPN T1,RTYBPT(T4)	;GET RETRY BYTE POINTER
	JRST [	BUG(DX2IDX)
		JRST ABTNOS]	;CALL IT FATAL
	MOVEM T1,U.EBP(P3)	;SAVE IT
	MOVE T1,UDBPS2(P3)	;GET # RECORDS
	SUBI T1,1		;CALCULATE WHERE WE SHOULD BE AFTER REPOS
	TXNE T4,TB.REV		;IF IN FORWARD, WE WANT (CUR POSITION-1)
	ADDI T1,2		;IF REVERSE, WE WANT (CUR POSITION+1)
	MOVEM T1,U.EPOS(P3)	;WHERE WE SHOULD BE SOMEDAY
	MOVEI T1,RTYWRT+1	;ON WRITE, THIS MANY RETRIES
	TXNN T4,TB.WRT		;ARE WE RIGHT (WRITE)?
	MOVE T1,[RTYCLN+1,,RTYOP+1] ;NO, THIS IS FOR READ
	MOVEM T1,UDBERC(P3)	;THE RETRY COUNTER
	CALL BEGLOD		;LOAD UP ERR BLK WITH BEGIN DATA
	JRST NXTBYT		;1ST TIME THRU DX2ERR
NOT1ST:	MOVE T1,U.EBP(P3)	;GET RETRY BYTE POINTER
	ILDB T1,T1		;LOOK AT NEXT OPERATION
	CAIE T1,RTY.DN		;END OF RETRY
	JRST CKBOT		;NO
	HLLZ T1,IRBSTS(P4)	;GET IORB STATUS
	TXNN T1,IS.DTE		;WAS THERE DATA ERR?
	JRST RTYNOE		;NO, WE'VE RECOVERED!
	MOVE T1,RTYBPT(T4)	;GET BYTE POINTER
	MOVEM T1,U.EBP(P3)	;RESET IT
	SETZM U.ETCF(P3)	;NOT DOING TAPE CLN SEQUENCE
	HRRZ T1,UDBERC(P3)	;GET ABORT COUNTER
	SUBI T1,1		;ANOTHER RETRY - SEE IF WE'VE LOST
	HRRM T1,UDBERC(P3)	;SAVE IT
	JUMPN T1,NXTBYT		;IF NOT 0, TRY AGAIN
	TXNE T4,TB.DOP		;DATA OPERATION?
	TXNN T4,TB.RD		;WRITE OR READ?
	JRST ABTRTY		;NON DATA OR WRITE - WE'VE FAILED
	HLRZ T1,UDBERC(P3)	;GET TAPE CLNR COUNTER
	SOJE T1,ABTRTY		;RUN OUT OF RETRIES? - YES
	HRLM T1,UDBERC(P3)	;NO, UPDATE CLN COUNTER
	MOVX T1,RTYOP+1		;NOW RESET (RH) COUNTER
	HRRM T1,UDBERC(P3)	;FOR NEXT CLEAN RETRY
	MOVE T1,RTYBPT+1(T4)	;GET CLEANER SEQ BYTE POINTER
	MOVEM T1,U.EBP(P3)	;SAVE FOR USE LATER
	SETZM E.EBC(P3)		;RESET COUNT FOR USE IF WE HIT BOT
	SETOM U.ETCF(P3)	;WE ARE DOING A CLEAN
	JRST NXTBYT		;NOW DO NEXT OPERATION

CKBOT:	SKIPN U.ETCF(P3)	;DOING TAPE CLEAN?
	JRST NXTBYT		;NO DON'T CHECK BOT
	HLLZ T1,IRBSTS(P4)	;GET STATUS
	TXNE T1,IS.BOT		;OR DID WE HIT BOT?
	SKIPA T1,[CLNREC]	;YES, FIGURE OUT HOW TO FUDGE BYTE POINTER
	JRST NXTBYT		;NO, CONTINUE NORM RETRY
	LOAD T3,ISFCN,(P4)	;GET ORIGINAL FN
	MOVE T3,DX2FTB(T3)	;GET FLAGS
	TXNE T3,TB.WRT		;IS IT A WRITE?
	JRST NXTBYT		;WRITE RETRY WON'T EVER HIT BOT SO NO FUDGE
	TXNN T3,TB.REV		;ADD 1 IF FORWARD
	ADDI T1,1		;DO IT ON FORWARD
	SUB T1,E.EBC(P3)	;SUBT # RECORDS SPACED
	LSH T1,1		;TIMES 2 (COMMENTS ASSUME CLNREC=5)
	ADDI T1,1		;ON FORWARD, SKIP (6-CNT)*2+1 BYTES
	CAIL T1,1		;ON REVERSE, SKIP (5-CNT)*2+1 BYTES
	CAILE T1,^D9		;RESULT MUST BE BETWEEN 1 AND 9
	JSP CX,CNFERR		;BAD INCR, WE ARE CONFUSED
	ADJBP T1,U.EBP(P3)	;ADJUST POINTER
	MOVEM T1,U.EBP(P3)	; AND PUT ADJUSTED POINTER BACK
NXTBYT:	AOS E.EBC(P3)		;ANOTHER BYTE FOR THE COUNTER
	ILDB T3,U.EBP(P3)	;GET NEXT FUNCTION
	CAIE T3,RTY.CP		;IS IT CHECK POSITION OPERATION?
	JRST NOTCKP		;NO
	MOVE T1,UDBPS2(P3)	;YES, GET OUR POSITION
	CAMN T1,U.EPOS(P3)	;ARE WE WHERE WE WANT TO BE?
	JRST NXTBYT		;YES, ALL OK
	JSP CX,CNFERR		;POSITION CONFUSED,SIGNAL ERROR
	JRST ABTNOS		;BOMB OUT

NOTCKP:	CAIE T3,RTY.DN		;END OF RETRY?
	SKIPG T3		;IS FUNCTION VALID?
	JRST [	BUG(DX2IRF)
		JRST ABTNOS]	;IMAGINE FATAL
	HRRM T3,UDBERR(P3)	;SAVE FUNCTION
;**;[1855] Replace one line at NOTCKP: +5L	RAS	23-APR-81
	CALL SETIO		;[1855] Reset overdue timer
	CALL CDSSIO(T1)		;START IO
	 JRST ABTNOS		;COULDN'T START UP RETRY OPERATION
	RET			;AND WAIT


RTYNOE:	TXNE T1,IS.NRT		;HARD ERRS SHOULDN'T EVER GET HERE
	BUG(DX2NRT)
	MOVX T1,IS.ERR		;WE DID IT! CLEAR ERR BIT
	ANDCAM T1,IRBSTS(P4)	;AND SKP RETURN
	TXNN T4,TB.WRT		;ARE WE WRTING?
	AOSA UDBSRE(P3)		;NO, A SOFT READ ERR
	AOS UDBSWE(P3)		;YES, A SOFT WRITE ERR
	JRST ABTNOS
;HERE WHEN ERROR RECOVERY GETS CONFUSED(FLAKEY HARDWARE W I L L DO IT)

CNFERR:	BUG(DX2RFU)
	MOVSI T1,(IS.ERR!IS.NRT) ;INDICATE RATHER HARD ERR
	IORM T1,IRBSTS(P4)	; ...
	JRST ABTNOS		;AND ABORT
ABTRTY:				;WE RAN OUT OF RETRIES
	TXNN T4,TB.WRT		;ARE WE WRTING?
	AOSA UDBHRE(P3)		;NO, A HARD READ ERR
	AOS UDBHWE(P3)		;YES, A HARD WRITE ERR
ABTNOS:	AOS (P)			;SKIP RET FROM ENDLOD
	HRRZ Q1,UDBERP(P3)	;GET ERROR BLOCK
	SKIPN U.EBP(P3)		;DONE ANY RETRIES?
	JRST ENDLOD		;NO, LOAD UP ERR BLK WITH END DATA
	TXNN T4,TB.WRT		;YES, IN A WRITE?
	JRST RDCNT		;NO
	MOVEI T1,RTYWRT+1	;YES, CALCULATE # RETRIES DONE
	SUBM T1,UDBERC(P3)	;RESIDUE
	JRST ENDLOD		;NOW LOAD UP ERR BLK

RDCNT:	HLRZ T1,UDBERC(P3)	;GET CLN COUNTER
	IMULI T1,RTYOP		;CONVRT JUST TO # RETRIES
	ADD T1,UDBERC(P3)	;ADD IN REGULAR RETRIES
	MOVEI T2,<RTYCLN+2>*RTYOP+1 ;COUNT AT START
	SUB T2,T1
	HRRZM T2,UDBERC(P3)	;SAVE # RETRIES
	JRST ENDLOD		;NOW LOAD UP ERR BLK
;BEGLOD - ROUTINE TO LOAD UP THE ERROR BLOCK AT
; THE START OF THE ERROR
; Q1/ERROR BLOCK ADDRESS
;	CALL BEGLOD
; RETURN+1: ALWAYS

BEGLOD:	JUMPE Q1,R		;IF NO ERROR BLOCK, PUNT
	MOVE T1,Q1		;COPY ERROR BLOCK
	MOVE T2,[-NITAB,,ITAB]	;POINTER TO INFORMATION TABLE
	CALL SEBCPY		;COPY INFORMATION
	 JFCL
	MOVS T1,UDBPS1(P3)	;GET FILE 
	HRR T1,UDBPS2(P3)	;AND RECORD (JUST AFTER ERROR)
	MOVEM T1,SEBDAT+MB%LOC(Q1) ;AND SAVE AS LOCATION OF ERROR
	MOVE T1,[XWD ^D22,DX%MBR] ;COUNT,,OFFSET FOR DX20 MB REGISTER
	MOVEM T1,SEBDAT+DX%MBI(Q1) ;STORE IN ERROR BLOCK
	MOVE T1,[XWD ^D20,DX%ESR] ;COUNT,,OFFSET FOR EXTENDED STATUS TABLE
	MOVEM T1,SEBDAT+DX%ESI(Q1) ;STORE IN ERROR BLOCK
	MOVEI T1,SEBDAT+DX%MBR(Q1) ;MOVE REGISTERS TO HERE
	MOVEM T1,T2		;SAVE FOR RH OF BLT
	ADDI T2,^D22+^D20-1	;22 REGISTERS(WORDS)+20 WORD EXTENDED STATUS TABLE
	HRLI T1,K.DREG(P2)	;GET REGISTERS FROM HERE
	HRLI T2,(BLT T1,)	;SET UP INST FIELD
	XCT T2			;DO IT
	RET


;ENDLOD - ROUTINE TO LOAD UP THE ERROR BLOCK AT
; THE END OF THE ERROR
; Q1/ERROR BLOCK ADDRESS IF ANY
;	CALL ENDLOD
; RETURN+1: ALWAYS

ENDLOD:	SETZM U.EBP(P3)		;ZERO, SO IF ERROR WITH IS.NRT
				; SET ERROR DATA IS LOGGED AS
				; BEGINNING DATA IN ERROR BLOCK
	SETZM U.ETIE(P3)	;MAKE SURE TIE FLAG CLEAR
	JUMPE Q1,R		;IF NO ERROR BLOCK, CANT SAVE DATA
	MOVE T3,[-^D22,,K.DREG]	;CASE FOR START
	ADD T3,P2		;POINTS TO REGISTER DATA
	MOVEI T2,SEBDAT+DX%MBR(Q1) ;REGISTER DATA GOES HERE
ENDLD1:	MOVE T1,(T3)		;GET REGISTER
	HRLM T1,(T2)		;PUT IT
	ADDI T2,1		;NEXT WD
	AOBJN T3,ENDLD1		;DONE?
	MOVE T1,K.DCNI(P2)	;GET CONI
	MOVEM T1,SEBDAT+MB%CIF(Q1) ;SAVE
	MOVE T1,K.DCS1(P2)	;GET TCR
	MOVEM T1,SEBDAT+MB%D1F(Q1) ;SAVE
	MOVE T1,K.DDBF(P2)	;GET BAR
	MOVEM T1,SEBDAT+MB%D2F(Q1) ;SAVE
	RET


;TABLE OF ITEMS TO COPY INTO ERROR BLOCK

ITAB:	SEBPTR MB%CS0,SBTWD,CDBCS0(P1) ;CHANNEL STATUS 0
	SEBPTR MB%CS1,SBTWD,CDBCS1(P1) ;CHANNEL STATUS 1
	SEBPTR MB%CS2,SBTWD,CDBCS2(P1) ;CHANNEL STATUS 2
	SEBPTR MB%CC1,SBTWD,CDBCC1(P1) ;CCW 1
	SEBPTR MB%CC2,SBTWD,CDBCC2(P1) ;CCW 2
	SEBPTR MB%ICR,SBTWD,CDBICR(P1) ;INITIAL CONTROL REGISTER
	SEBPTR MB%CNI,SBTWD,K.DCNI(P2) ;CONI INITIAL
	SEBPTR MB%D1I,SBTWD,K.DCS1(P2) ;TCR
	SEBPTR MB%D2I,SBTWD,K.DDBF(P2) ;BAR/DBF
	SEBPTR DX%VER,SBTWD,K.DVER(P2) ;VERSION NUMBR

NITAB==.-ITAB
	SUBTTL DX20 FUNCTION TABLE

;EACH ENTRY MUST BE NON-0

;1B0				;ILLEGAL FUNCTION
	TB.WRT==1B1		;THIS FUNCTION WRITES ON TAPE
	TB.REV==1B2		;THIS OPERATION MOVES TAPEIN REVERSE DIRECTION
	TB.DOP==1B3		;THIS IS A DATA OPERATION
	TB.SPC==1B4		;THIS IS A SPACE OPERATION
	TB.RD==1B5		;THIS IS A READ
	TB.ERA==1B6		;ERASE OPERATION
	TB.TM==1B7		;WRITE TAPE MARK
	TB.NFC==1B8		;DON'T LOAD FRM COUNT WHEN DOING OPERATION
	TB.REW==1B9		;OPERATION IS A REWIND
	TB.WRD==1B10		;THIS FUNCTION WRITES DATA ON TAPE
	TB.UNL==1B11		;UNLOAD COMMAND

;BITS 15,16,17 CONTAIN AN INDEX TO RTYBPT TO TELL US HOW
;TO RETRY AN OPERATION (0 IF NO RETRY)

;BITS 30-35 HAS MAJOR FUNCTION CODE FOR DX20
; BITS 21-26 HAS MINOR FUNCTION CODE FOR DX20

DX2FTB:	1B0			;0- ILLEGAL
	<TB.DOP!TB.RD>!2B17!XF.RDF ;1- READ FORWARD (IRFRED)
	1B0			;2- ILL (RD FMT)
	<TB.WRT!TB.WRD!TB.DOP>!1B17!XF.WTF ;3- WRITE FORWARD (IRFWRT)
	1B0			;4- ILL (WRT FMT)
	1B0			;5- ILL (SEEK)
	TB.SPC!XF.SPF		;6- SPCE FORWARD(BLOCK)
	<TB.REV!TB.SPC>!XF.SPR	;7- SPCE REVERSE(BLOCK)
	<TB.WRT!TB.TM>!6B17!XF.WTM ;10- WRITE TM
	<TB.WRT!TB.ERA>!XF.ERA	;11- ERASE
	<TB.NFC!TB.REW>!XF.REW	;12- REWIND
	<TB.NFC!TB.UNL>!XF.UNL	;13- UNLOAD
	<TB.REV!TB.DOP!TB.RD>!4B17!XF.RDR ;14- READ REVERSE
	1B0			;15- ILL (RECOVERY RD)
	1B0			;16- ILL
	1B0			;17- ILL
;CONVERT SOFTWARE MODE CODE TO TU70S FMT CODE (1B0 IS ILLEGAL)
;LH IS #FRAMES/BYTE (0 MEANS FRAMES=BYTES), RH IS TX02 FORMAT TYPE

M70FMT:	1B0			;(0) ILLEGAL
	XWD 5,DAT.CD		;(1) DUMP MODE
	1B0			;(2) SIXBIT
	DAT.AS			;(3) ANSI ASCII
	DAT.IC			;(4) INDUSTRY COMPATIBLE
	XWD ^D9,DAT.HD		;(5) HI-DENSITY

	MAXFN==.-M70FMT-1

M71FMT:	1B0			;(0) ILLEGAL
	1B0			;(1) DUMP MODE
	DAT.SB			;(2) SIXBIT
	1B0			;(3) ANSI ASCII
	1B0			;(4) INDUSTRY COMPATIBLE
	1B0			;(5) HI-DENSITY

FMTTAB:	M70FMT(T2)		;TU70
	M71FMT(T2)		;TU71
	M70FMT(T2)		;TU72
	M70FMT(T2)		;TU73
DEFINE DEN(E9PG,O9PG,E9NP,O9NP,E7NP,O7NP),<
	BYTE (6) E9PG,O9PG,E9NP,O9NP,E7NP,O7NP
>;END DEFINE DEN

;TABLE OF DENSITYS FOR EACH TYPE OF DRIVE
;
DENTAB:	DEN DRV.IL,DRV.IL,DRV.IL,DRV.IL,DRV.IL,DRV.IL ;(0) DRV.ILEGAL DENSITY
	DEN DRV.IL,DRV.IL,DRV.IL,DRV.IL,DRV.E2,DRV.O2 ;(1) 200 BPI
	DEN DRV.IL,DRV.IL,DRV.IL,DRV.IL,DRV.E5,DRV.O5 ;(2) 556 BPI
	DEN DRV.IL,DRV.IL,DRV.IL,DRV.NR,DRV.E8,DRV.O8 ;(3) 800 BPI
	DEN DRV.IL,DRV.PE,DRV.IL,DRV.PE,DRV.IL,DRV.IL ;(4) 1600 BPI
	DEN DRV.IL,DRV.GC,DRV.IL,DRV.IL,DRV.IL,DRV.IL ;(5) 6250 BPI
	MAXDN==.-DENTAB-1

;TABLE OF POINTERS TO DENTAB
; T2 CONTAINS THE DENSITY FROM THE IORB
;
DENPNT:	POINT 6,DENTAB(T2),23	;TU70 (9TRK 800/1600 ODD PARITY)
	POINT 6,DENTAB(T2),17	;TU70 (9TRK 800/1600 EVEN PARITY)
	POINT 6,DENTAB(T2),35	;TU71 (7TRK 200/556/800 ODD PARITY)
	POINT 6,DENTAB(T2),29	;TU71 (7TRK 200/556/800 EVEN PARITY)
	POINT 6,DENTAB(T2),11	;TU72 (9TRK 1600/6250 ODD PARITY)
	POINT 6,DENTAB(T2),5	;TU72 (9TRK 1600/6250 EVEN PARITY)
	POINT 6,DENTAB(T2),11	;TU73 (9TRK 1600/6250 ODD PARITY)
	POINT 6,DENTAB(T2),5	;TU73 (9TRK 1600/6250 EVEN PARITY)
;RETRY TABLES TO TELL HOW TO RETRY

RTYBPT:	0			;ILLEGAL RETRY
	POINT 4,TBRWRT		;WRITE RETRY
	POINT 4,TBRRF		;READ FORWARD RETRY
	POINT 4,TBRRFC		;READ FORWARD TAPE CLEAN
	POINT 4,TBRRR		;READ REVERSE RETRY
	POINT 4,TBRRRC		;READ REVERSE TAPE CLEAN
	POINT 4,TBRWTM		;WRITE TAPE MARK
	0			;ILLEGAL

;THE FOLLOWING MACROS HELP ME GET AROUND SOME SHORTCOMINGS IN MACRO:
;NOTE: THE MACRO'S MUST BE FIXED IN THE UNLIKELY EVENT THAT
;SOMEBODY WANTS TO CHANGE TO A BYTE SIZE WHICH DOESN'T GO
;EVENLY INTO 36(10). RIGHT NOW IT'S 4.

	DEFINE FOO (XXA) <
		WD==0
		BYC==0
		ZZ==0		;FLIP-FLOP
	IRP XXA,<
	IFE ZZ,<RP==XXA>
	IFN ZZ,<FOO1 RP,XXA>
	ZZ==ZZ+1
	IFE ZZ-2,<ZZ==0>>
	IFN BYC,<EXP WD>>

	DEFINE FOO1 (A1,A2) <
	REPEAT A1,<
		WD==WD+<A2>B<4*BYC+3>
		BYC==BYC+1
	IFGE BYC-^D9, <
			EXP WD
			WD==0
			BYC==0>>>

TBRWRT:	BYTE (4) IRFBSB,IRFERG,RTY.CP,IRFWRT,RTY.DN
				;WRITE RETRY - SPACE REVERSE, ERASE, CHECK POSITION, WRITE
TBRWTM:	BYTE (4) IRFBSB,IRFERG,RTY.CP,IRFWTM,RTY.DN
				;WRITE TM RETRY - SPACE REVERSE, ERASE, CHECK POS, WTM, EOR
TBRRF:	BYTE (4) IRFBSB,RTY.CP,IRFRED,RTY.DN
				;READ FORWARD RETRY - SPACE REVERSE, CHECK POSITION, READ FORWARD
TBRRR:	BYTE (4) IRFFSB,RTY.CP,IRFRDR,RTY.DN
				;READ REVERSE RETRY - SPACE FORWARD, CHECK POSITION, READ REVERSE

TBRRFC:	FOO<CLNREC+1,IRFBSB, CLNREC,IRFFSB, 1,RTY.CP, 1,IRFRED, 1,RTY.DN>
				;RD FORWARD TAPE CLEAN: 6 SP REVERSE, 5 SP FORWARD, CHECK POSITION, RD FORWARD
TBRRRC:	FOO<CLNREC,IRFBSB, CLNREC+1,IRFFSB, 1,RTY.CP, 1,IRFRDR, 1,RTY.DN>
				;RD REVERSE TAPE CLEAN: 5 SP REVERSE, 6 SP FORWARD, CHECK POSITION, RD REVERSE
	TNXEND
	END