Google
 

Trailing-Edge - PDP-10 Archives - bb-m780d-sm - monitor-sources/phyx2.mac
There are 47 other files named phyx2.mac in the archive. Click here to see a list.
; UPD ID= 8595, RIP:<7.MONITOR>PHYX2.MAC.5,  11-Feb-88 16:57:21 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 8440, RIP:<7.MONITOR>PHYX2.MAC.4,   4-Feb-88 16:17:11 by GSCOTT
;TCO 7.1210 - Set DX2DIE, DX2DNF, DX2FGS, DX2FUS, DX2HLT, DX2MCF, DX2N2S, 
; DX2NUD, DX2NUE, DX2UNA, and DX2UPE normally not dumpable.
; UPD ID= 137, RIP:<7.MONITOR>PHYX2.MAC.3,  23-Sep-87 17:33:30 by GSCOTT
;More of TCO 7.1054
; UPD ID= 115, RIP:<7.MONITOR>PHYX2.MAC.2,  16-Sep-87 19:01:57 by GSCOTT
;TCO 7.1054 - Fix BUG. documentation and data output, remove unused code.
; UPD ID= 2167, SNARK:<6.1.MONITOR>PHYX2.MAC.20,   5-Jun-85 10:49:36 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 1928, SNARK:<6.1.MONITOR>PHYX2.MAC.19,   7-May-85 21:56:29 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1716, SNARK:<6.1.MONITOR>PHYX2.MAC.18,   5-Apr-85 14:11:12 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 4829, SNARK:<6.MONITOR>PHYX2.MAC.17,  17-Sep-84 10:44:39 by PURRETTA
;Update copyright notice
; UPD ID= 4601, SNARK:<6.MONITOR>PHYX2.MAC.16,  27-Jul-84 08:25:31 by HAUDEL
;TCO 6.2089 - ADD DATA ITEMS TO DX2FGS BUGCHK
; UPD ID= 4192, SNARK:<6.MONITOR>PHYX2.MAC.15,   9-May-84 12:07:08 by MOSER
;6.1562 - REMOVE IOOFF AND IOON USE OLD METHOD
; UPD ID= 3776, SNARK:<6.MONITOR>PHYX2.MAC.14,  28-Feb-84 10:28:16 by MOSER
;TCO 6.1562 - USE IOOFF AND IOON MACROS
; UPD ID= 3127, SNARK:<6.MONITOR>PHYX2.MAC.13,   9-Nov-83 13:26:12 by MCLEAN
;TCO 6.1853 MISSING (P3) IN WSTATF ALSO MISSING SOME IFIW'S.
; UPD ID= 3111, SNARK:<6.MONITOR>PHYX2.MAC.12,   7-Nov-83 21:26:14 by MCLEAN
;ADD PORT RELEASE DISPATCH
; UPD ID= 2780, SNARK:<6.MONITOR>PHYX2.MAC.11,  29-Jul-83 15:39:15 by HAUDEL
;TCO 6.1754 - Change HLTCHK to require Q2 and not P3 setup
; UPD ID= 2779, SNARK:<6.MONITOR>PHYX2.MAC.10,  29-Jul-83 15:31:41 by HAUDEL
;TCO 6.1745 - Change MAXDRV on DX20 to 37 octal
; UPD ID= 2581, SNARK:<6.MONITOR>PHYX2.MAC.9,  14-Jun-83 10:32:21 by HAUDEL
;TCO 6.1668 - Add SAVEQ at DX2SIO:
; UPD ID= 2264, SNARK:<6.MONITOR>PHYX2.MAC.8,  13-Apr-83 12:08:29 by HAUDEL
;TCO 6.1538 - Reset the rewind timer bits
; UPD ID= 2263, SNARK:<6.MONITOR>PHYX2.MAC.7,  13-Apr-83 11:56:54 by HAUDEL
;TCO 6.1583 - Change routine call from PHYRWD to PHYRW1
; UPD ID= 2262, SNARK:<6.MONITOR>PHYX2.MAC.6,  13-Apr-83 11:23:48 by HAUDEL
;TCO 6.1581 - Make changes for new microcode that supports dual port TX03
; UPD ID= 1852, SNARK:<6.MONITOR>PHYX2.MAC.5,  22-Feb-83 09:09:26 by DONAHUE
;Fix last edit 
; UPD ID= 1603, SNARK:<6.MONITOR>PHYX2.MAC.3,  29-Dec-82 13:47:09 by DONAHUE
;TCO 6.1410 - Change references to MTINDX to use STKVAR's 
; UPD ID= 908, SNARK:<6.MONITOR>PHYX2.MAC.2,   9-Jun-82 23:38:05 by MURPHY
;TCO 6.1147 - Move bugdefs from BUGS.MAC to here and put them in-line.
; UPD ID= 444, SNARK:<5.MONITOR>PHYX2.MAC.13,  27-Jan-82 07:05:44 by WACHS
;TCO 5.1704 - set .UTT73 in UDB if drive is a TU73
; UPD ID= 260, SNARK:<5.MONITOR>PHYX2.MAC.12,  14-Oct-81 12:02:22 by WACHS
;TCO 5.1575 - check MTCUTB before storing in it
; UPD ID= 1904, SNARK:<5.MONITOR>PHYX2.MAC.11,  29-Apr-81 08:29:41 by WACHS
; UPD ID= 1901, SNARK:<5.MONITOR>PHYX2.MAC.10,  29-Apr-81 07:58:46 by WACHS
; UPD ID= 1872, SNARK:<5.MONITOR>PHYX2.MAC.9,  23-Apr-81 08:45:08 by UHLER
;TCO 5.1294 - Make the DX2FGS timer be 6000 to avoid problems on systems that
;share tape subsystems.
; UPD ID= 1860, SNARK:<5.MONITOR>PHYX2.MAC.8,  21-Apr-81 13:50:57 by SCHMITT
;TCO 5.1292 - Reset overdue timer before starting I/O when retrying
; UPD ID= 1823, SNARK:<5.MONITOR>PHYX2.MAC.7,  17-Apr-81 09:53:59 by WACHS
;TCO 5.1288 Maintain statistics by recording mode
; UPD ID= 1212, SNARK:<5.MONITOR>PHYX2.MAC.6,  31-Oct-80 07:08:45 by UHLER
;TCO 5.1184 - DON'T READ REGISTER 30 UNLESS THE DX20 IS ALREADY HALTED
; UPD ID= 738, SNARK:<5.MONITOR>PHYX2.MAC.4,   7-Jul-80 00:47:32 by DBELL
;TCO 5.1096 - ADD DX2CCK ROUTINE TO CHECK FOR HALTED MICROCODE
; UPD ID= 528, SNARK:<5.MONITOR>PHYX2.MAC.3,  19-May-80 16:46:09 by DBELL
;TCO 5.1042 - READ ASYCHRONOUS STATUS REGISTER TWICE IF NECESSARY
; UPD ID= 367, SNARK:<4.1.MONITOR>PHYX2.MAC.24,  26-Mar-80 11:08:31 by DBELL
;TCO 4.1.1119 - MAKE CHANGES NECESSARY FOR RP20 DISKS
;<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

;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1978, 1988.
;	ALL RIGHTS RESERVED.
;
;	THIS SOFTWARE IS FURNISHED UNDER A  LICENSE AND MAY BE USED AND  COPIED
;	ONLY IN  ACCORDANCE  WITH  THE  TERMS OF  SUCH  LICENSE  AND  WITH  THE
;	INCLUSION OF THE ABOVE  COPYRIGHT NOTICE.  THIS  SOFTWARE OR ANY  OTHER
;	COPIES THEREOF MAY NOT BE PROVIDED  OR OTHERWISE MADE AVAILABLE TO  ANY
;	OTHER PERSON.  NO  TITLE TO  AND OWNERSHIP  OF THE  SOFTWARE IS  HEREBY
;	TRANSFERRED.
;
;	THE INFORMATION IN THIS  SOFTWARE IS SUBJECT  TO CHANGE WITHOUT  NOTICE
;	AND SHOULD  NOT  BE CONSTRUED  AS  A COMMITMENT  BY  DIGITAL  EQUIPMENT
;	CORPORATION.
;
;	DIGITAL ASSUMES NO  RESPONSIBILITY FOR  THE USE OR  RELIABILITY OF  ITS
;	SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.


	SEARCH PROLOG,PHYPAR,SERCOD ;SYSTEM PARAMETERS
	TTITLE (PHYX2,,< - Device Dependent Code for DX20A/TX02/TU70/71/72/73>)
	SUBTTL E. OUYANG/Ed Fortmiller  24 FEB 78

	DX2VER==1		;EDIT VERSION

	ENTRY DXADSP		;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	Table of Contents

;		     Table of Contents for PHYX2
;
;				  Section		      Page
;
;
;    1. Device Dependant Table Defs  . . . . . . . . . . . . .   3
;    2. Massbus-DX20 Register Definitions  . . . . . . . . . .   5
;    3. DX20 Error Recovery Defs . . . . . . . . . . . . . . .  12
;    4. Macros To Manipulate DX20 Registers  . . . . . . . . .  13
;    5. STDX - Start the DX20  . . . . . . . . . . . . . . . .  14
;    6. GTVER - Get microcode version number . . . . . . . . .  15
;    7. GTSNS - Get Sense Bytes  . . . . . . . . . . . . . . .  16
;    8. HLTCHK - See if microcode running  . . . . . . . . . .  19
;    9. ASYNST - Asynchronous Status handler . . . . . . . . .  21
;   10. HARCHK - Check for hard errors . . . . . . . . . . . .  23
;   11. DX2RDR - Save DX20 Registers in KDB  . . . . . . . . .  29
;   12. DX2REX - Save extended status in KDB . . . . . . . . .  30
;   13. DRVSRC - Find the UDB from drive number  . . . . . . .  31
;   14. GTRDEN - Save tape density in UDB  . . . . . . . . . .  32
;   15. DXADSP - PHYSIO Dispatch Table for DX20A . . . . . . .  33
;   16. DX2INI - DX20 Initializing Routine . . . . . . . . . .  35
;   17. DX2CCK - Once an minute check  . . . . . . . . . . . .  39
;   18. CHKMIC - Check microcode . . . . . . . . . . . . . . .  40
;   19. DX2SIO - Start I/O Routine . . . . . . . . . . . . . .  41
;   20. DX2INT - Done Interrupt Handler  . . . . . . . . . . .  45
;   21. DX2ATN - Attention Interrupt Handling  . . . . . . . .  51
;   22. DX2ERR - Error Retry Entry Point . . . . . . . . . . .  54
;   23. DX20 Function Tables . . . . . . . . . . . . . . . . .  62
;   24. DX20 Error Recovery Tables . . . . . . . . . . . . . .  65
;   25. End of PHYX2 . . . . . . . . . . . . . . . . . . . . .  67
	SUBTTL Device Dependant Table Defs

;DX20 STARTING ADDRESS

	STADDR==6		;DX20 STARTING ADDRESS
	STMAX==^D10		;NUMBER OF TIMES TO RESTART MICROCODE
	MAXDRV==^D45		;TOTAL NUMBER OF DRIVES PER DX20(37 OCTAL)
				;37 COVERS ALL SLAVE ADDRESSES
	NUMDRV==^D16		;MAXIMUM NUMBER OF DRIVES WHICH CAN BE
				;USED DUE TO TABLE SPACE LIMITATIONS

;UDB EXTENSIONS

	U.HDEN==UDBDDM		;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.STCT==K.DXAD+1	;NUMBER OF TIMES MICROCODE IS RESTARTED
	K.DCNI==K.STCT+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>>
	REG.'REGS==SAVNUM	;DEFINE OFFSET OF THIS REGISTER
	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)
;	THIS REGISTER HAS STATUS INFORMATION WHEN A TAPE FINISHES
;	REWINDING OR COMES ONLINE. THE ES.XXX BIT DEFINITIONS ARE
;	THE SAME AS THOSE FOR REGISTER 20. DX20 MICROCODE VERSION 10.1
;	OR GREATER IS NEEDED.


;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==14		;TU72
	S6M.73==15		;TU73 (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 Macros 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
	SUBTTL STDX - Start the DX20

;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
	SUBTTL GTVER - Get microcode version number

;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
	SUBTTL GTSNS - Get Sense Bytes

;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:	STKVAR <DRVSLV>		;SAVE SLAVE NUMBER AND UNIT NUMBER
	HRLM Q2,DRVSLV		;SAVE UNIT NUMBER
	HRRM T4,DRVSLV		;SAVE SLAVE NUMBER
	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,6000		;LOOP COUNT=6000
				; (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
;Here when we can't read the sense bytes for this drive.

	POP P,P4		;FAIL, THEN RESTORE P4
	RDRG DXDR1		;READ REGISTER 31
	MOVE T4,T1		;SAVE RESULTS IN T4.
	RDRG DXGP1		;READ REGISTER 21.
	MOVE T3,T1		;SAVE RESULTS IN 34
	HRRZ T1,CDBADR(P1)	;[7.1054] Get channel number 
	MOVE T2,DRVSLV		;[7.1054] Put unit,,slave in T2
	BUG.(CHK,DX2FGS,PHYX2,HARD,<PHYX2 - Fail to get sense bytes>,<<T1,CHAN>,<T2,DRIVE>,<T3,REG21>,<T4,REG31>>,<

Cause:	TOPS-20 could not read the sense bytes for a magtape drive.

Action:	There could be a DX20, TX02, or drive problem.  Look out for other
	DX2xxx BUGCHKs.  Call Field Service.

Data:	CHAN  - Channel number
	DRIVE - DX20,,slave number that the monitor is working with
	REG21 - Reg 21 of DX20 (unit and slave that DX20 is working with)
	REG31 - Reg 31 of DX20 (PC of the DX20)
>,,<DB%NND>)			;[7.1210][7.1054] Put out BUGCHK
	RET			;JUST RETURN
	ENDSV.

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
	HRRZ T1,CDBADR(P1)	;[7.1054] Get channel number
	BUG.(CHK,DX2FUS,PHYX2,HARD,<PHYX2 - Fail to update sense bytes>,<<T1,CHAN>,<Q2,DX20>>,<

Cause:	GETEXS could not update the DX20 sense bytes because the DX20 would
	not respond to the request.

Action:	The DX20 may be broken.  Look out for other DX2xxx BUGs.
	Call Field Service.

Data:	CHAN - Channel number
	DX20 - DX20 number
>,,<DB%NND>)			;[7.1210][7.1054] 

	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
	SUBTTL HLTCHK - See if microcode running

;HLTCHK - SEES IF THE MICROCODE IS STILL RUNNING IN THE DX20
; P1/	CDB
; P2/	KDB
; Q2/   DX20 NUMBER
;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 RDREG3		; 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
;Here from HLTCHK when the DX20 is discovered to be down.

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.(CHK,DX2HLT,PHYX2,HARD,<PHYX2 - DX20 halted>,<<T1,CHAN>,<T2,DX20>,<T3,REG1>,<T4,2AND26>>,<

Cause:	The DX20 controller's microcode is no longer running.  This could
	be due to one or more of the following:

	o The DX20 has been powered down.  Reload the microcode with DX20LD.
	o The DX20 microcode has detected a fatal error.
	o The microcode could have been halted by a program such as DX20LD.
	o The DX20 is seeing microbus parity errors while fetching an
	  instruction from its memory.

Action:	The DX20 may be having problems, look for other DX2xxx BUGCHKs.
	If the DX20 won't run or starts halting frequently, call Field 
	Service.

Data:	CHAN   - Channel number
	DX20   - DX20 number
	REG1   - Contents of device register 1 (status register).
	2AND26 - Device register 2 in left half (error register), and
		 device register 26 in right half (possible error code).
>,,<DB%NND>)			;[7.1210][7.1054]
	POP P,T4		;RESTORE AC
	RET			;ERROR RETURN
	SUBTTL ASYNST - Asynchronous Status handler

;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
	MOVX T2,DXGP4		;SET UP IN CASE NEED TO READ REGISTER AGAIN
	TXNN T1,ES.UEX!ES.UCK!ES.DVE!ES.CHE!ES.BSY!ES.CUE!ES.SM!ES.ATN	;FLAGS?
	CALL RDREG3		;NO, READ AGAIN SINCE DX20 WASN'T DONE YET
	PUSH P,P3		;PRESERVE P3
	PUSH P,P4		; AND P4
	PUSH P,T1		;SAVE THE STATUS
	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 ASYNS2		;[7.1054] Couldn't find that UDB
	POP P,T1		;GET THE STATUS BACK
	MOVX T2,<US.BOT!US.WLK> ;GET MASK
	ANDCAM T2,UDBSTS(P3)	;CLEAR THESE BITS FIRST
	TXNN T1,ES.ATN		;UNIT AT BOT?
	TXZ T2,US.BOT		;NO, CLEAR BOT BIT
	TXNN T1,ES.SM		;FILE-PROTECTED AS IN SENSE BYTE
	TXZ T2,US.WLK		;NO, CLEAR US.WLK IN MASK
	IORM T2,UDBSTS(P3)	;MARK INTO UDB
	MOVX T2,US.REW!US.ORC	;SAY NO LONGER REWINDING
	ANDCAM T2,UDBSTS(P3)	;SO CLEAR THE BITS
	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	;NO INTS NOW
		CALL SCHSEK	;YES, ONLY DO SEEKS
		IOPION		;OK TO INT AGAIN
		POP P,P4	;RESTORE ACS
		POP P,P3
		JRST ASYNS1]	;LOOP TO SEE IF ANY MORE STATUS
	CALL PHYX2R		;LAST ONE, START IO
	POP P,P4		;RESTORE AC'S
	POP P,P3
Q2RET:	POP P,Q2		;RESTORE Q2
	RET			; AND RETURN TO CALLER

PHYX2R:	SAVEQ
	JRST PHYRW1		;GO TO THE PHYRWD CODE
;Here when the drive number wasn't found in the UDBs.

ASYNS2:	HRRZ T1,CDBADR(P1)	;[7.1054] Get channel number
	BUG.(CHK,DX2DNF,PHYX2,HARD,<PHYX2 - Drive number not found in UDBs>,<<T1,CHAN>,<Q2,DX20>,<T4,UNIT>>,<

Cause:	A DX20 returned an 8-bit drive number, and routine DRVSRC was
	called to determine which UDB was associated with that drive
	number.  None of the currently existing UDBs had that number.

Action:	The DX20 or TX02 may be having problems, look for other DX2xxx
	BUGCHKs.  Call Field Service.

Data:	CHAN - Channel number
	DX20 - DX20 number
	UNIT - The unit number that was not found
>,,<DB%NND>)			;[7.1210] [7.1054] Can't find it
	MOVX T2,1		;[7.1054] Get bit ready
	LSH T2,(Q2)		;[7.1054] Mask to clear our attention bit
	TXO T2,DXASR		;[7.1054] Clear the attention
	CALL WTREG3		;[7.1054] (T2,P1,Q2/) bit for this DX20
	POP P,T1		;[7.1054] Restore T1 with status
	POP P,P4		;[7.1054] Restore acs
	POP P,P3		;[7.1054] that were pushed
	JRST ASYNS1		;[7.1054] and look for more status
	SUBTTL HARCHK - Check for hard errors

;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 unknown error class code

ECCERR: HRRZ T2,CDBADR(P1)	;[7.1054] Load channel number
	MOVE T3,K.DXAD(P2)	;[7.1054] Get unit number of DX20
	BUG.(CHK,DX2IEC,PHYX2,HARD,<PHYX2 - Illegal error class code>,<<T2,CHAN>,<T2,DX20>,<T1,DXERR>>,<

Cause:	The error class code returned by the DX20 is illegal.

Action:	The DX20 may be having problems, look for other DX2xxx BUGCHKs.
	Call Field Service.

Data:	CHAN  - Channel number
	DX20  - DX20 number
	DXERR - DX20 error register
>)				;[7.1054] 
	JRST HARCH2
;HERE IF DX20 IS HALTED
;
HARCH1:	REDRG DXGP6		;READ IN AS THIS MIGHT CONTAIN AN ERROR CODE
	HRRZ T2,CDBADR(P1)	;[7.1054] Get channel number
	MOVE T3,K.DXAD(P2)	;[7.1054] Get unit number of DX20
	BUG.(CHK,DX2DIE,PHYX2,HARD,<PHYX2 - DX20 halted>,<<T2,CHAN>,<T3,DX20>,<T1,REG26>>,<

Cause:	During a check for DX20 errors, HARCHK discovered that the DX20 was
	not running.  This could be due to one or more of the following:

	o The DX20 has been powered down.  Reload the microcode with DX20LD.
	o The DX20 microcode has detected a fatal error.
	o The microcode could have been halted by a program such as DX20LD.
	o The DX20 is seeing microbus parity errors while fetching an
	  instruction from its memory.

Action:	The DX20 may be having problems, look for other DX2xxx BUGCHKs.
	If the DX20 won't run or starts halting frequently, call Field 
	Service.

Data:	CHAN  - Channel number
	DX20  - DX20 number	
	REG26 - Extended status register (register 26) contents
>,,<DB%NND>)			;[7.1210] 
	MOVEI T1,STADDR		;DX20 STARTING ADDRESS
	CALL STDX		;START THE DX20 RUNNING AGAIN

HARCH2:	CALL RDALL		;READ ALL DX20 REGISTERS AND EXTENDED STATUS

NOTMOV:				;[7.1054] Here if tape hasn't moved, call
				;[7.1054] it a hard error
HERR:	MOVX T3,<IS.DVE!IS.ERR!IS.NRT> ;FLAG A FATAL
	IORM T3,IRBSTS(P4)	; ERROR IN THE IORB
	MOVX T3,US.REW!US.ORC	;CLEAR REWINDING BITS
	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:	IFIW!ECC1		;(1) UNUSUAL DEVICE STATUS (EXAMINE ENDING STATUS REG)
	IFIW!CLRERR		;(2) SHORT RECORD (NOT AN ERROR)
	IFIW!CLRERR		;(3) LONG RECORD (FATAL)
				; (ERROR BITS WILL BE SET BY CKERR)
	IFIW!FTLERR		;(4) DRIVE SELECTION ERROR (FATAL)
	IFIW!CLRERR		;(5) TAPE MOTION (RECOVERABLE)
	IFIW!NOTMOV		;(6) NO TAPE MOTION (RECOVERABLE)
	IFIW!FTLERR		;(7) PARITY ERROR (FATAL)
	IFIW!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
;HERE IF TAPE HASN'T MOVED
;
REPEAT 0,<			;[7.1054] Code not used
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
>				;[7.1054] end of repeat 0

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
	SUBTTL DX2RDR - Save DX20 Registers in KDB

;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
	CAMN T2,[DXDR0]		;ABOUT TO READ REGISTER 30?
	TDZA T1,T1		;YES, READ IT 
	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)	; ...
	DMOVE T1,K.DREG+REG.0(P2) ;GET CONTROL AND STATUS REGISTERS
	TXNN T1,GO		;IS GO STILL UP?
	TXNE T2,SR.RUN		;NO, IS THE MICROPROCESSOR STILL RUNNING
	RET			;YES, CAN'T READ REGISTER 30 THEN
	MOVX T2,DXDR1		;SETUP TO READ THE PC REGISTER
	CALL RDREG		;READ IT
	TXZ T1,D1.IRE		;TURN OFF IR ENABLE
	MOVX T2,DXDR1		;SET TO WRITE PC REGISTER
	IOR T2,T1		;WITH ALL THE BITS BUT IR ENABLE
	CALL WTREG		;WRITE IT BACK
	MOVX T2,DXDR0		;SETUP TO READ THE IR
	CALL RDREG		;READ IT NOW
	MOVEM T1,K.DREG+REG.30(P2) ;STORE IT WHERE IT BELONGS
	RET
	SUBTTL	DX2REX - Save extended status in KDB

;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
	SUBTTL DRVSRC - Find the UDB from drive number

;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
	SUBTTL GTRDEN - Save tape density in UDB

;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 DXADSP - PHYSIO Dispatch Table for DX20A

DXADSP::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
	JRST DX2CCK		;14 - CHECK FOR HALTED MICROCODE
	JRST R			;15 - RELEASE PORT
;Here on hung unit - just set the fatal error bits

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 DX2INI - 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.  CALL:
;  P1/	CDB
;  Q2/	DX20 NUMBER
;  P5/	UNIT NUMBER TO BE INITIALIZED, OR -1 FOR ALL UNITS
;	CALL DX2INI
; RETURN +1: ALWAYS
; T1/KDB

DX2INI:	SAVEQ			;SAVE REGISTERS
	STKVAR <MTINDX>		;INDEX INTO MTCUTB
	JUMPL P5,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 INIMCF		;[7.1054] Microcode isn't OK
	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,.UTDXA		;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,DXADSP		;INSERT DISPATCH VECTOR
	MOVEM T1,KDBDSP(P2)	; ...
	SETZM K.DNUM(P2)	;CLEAR NUMBER OF UDB'S IN EXISTANCE
INILA:	SKIPL Q1,P5		;GET POSSIBLE SPECIFIC SLAVE NUMBER
	TLOA Q1,-1		;WAS ONE, DO ONLY 1 TIME
	MOVSI Q1,-MAXDRV	;WANTS ALL DRIVES, SET UP AOBJN 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
	HRLOI T3,-MTAN-1	;IF 1ST TIME THRU
INILP1:	AOBJP T3,TOORET		;LOSE IF TOO MANY DRIVES
	SKIPE MTCUTB(T3)	;IS THIS ENTRY ALREADY IN USE?
	JRST INILP1		;YES, TRY NEXT
	MOVEM T3,MTINDX		;SAVE CURRENT LOGICAL INDEX
	MOVE T3,[DXADSP,,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, 125 IPS)
	TXC T1,<S6M.73>B27
	TXCN T1,<S6M.73>B27	;IS IT A TU73?
	MOVX T2,.UTT73		;CALL IT A TU73 (1600/6250 9 TRK, 200 IPS)
	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
	
;Here when microcode check failed.

INIMCF:	HRRZ T1,CDBADR(P1)	;[7.1054] Get channel number
	BUG.(CHK,DX2MCF,PHYX2,HARD,<PHYX2 - DX20 microcode check failure>,<<T1,CHAN>,<Q2,DX20>>,<

Cause:	A check of CRAM locations 7 through 11 in the DX20 indicates that
	the microcode running in the DX20 is bad.

Action:	Unless the DX20 has just been powered up, the DX20 could be
	broken.  Try reloading the microcode and watch for other DX2xxx
	BUGCHKs.  If this error persists the DX20 is broken, call 
	Field Service.

Data:	CHAN - Channel number
	DX20 - DX20 unit number
>,,<DB%NND>)			;[7.1210][7.1054] 
	RET			;[7.1054] 

TOORET:	BUG.(INF,DX2N2S,PHYX2,HARD,<PHYX2 - More TU70s than table space, excess ignored>,,<

Cause:	DX2INI was called to build a KDB and a UDB for a tape drive. This
	BUG indicates that the MTCUTB table of CDBs and UDBs is already
	full.

Action:	MTCUTB is of length MTAN and it is full.

Cure:	The monitor must be rebuilt with a greater value for MTAN to 
	accommodate more tape drives.
>,,<DB%NND>)			;[7.1210] 
	MOVE T1,P2		;TELL RETURN TO PUT KDB INTO CDB
	RET

UPERR:	HRRZ T1,CDBADR(P1)	;[7.1054] Get channel number
	BUG.(CHK,DX2UPE,PHYX2,HARD,<PHYX2 - Fail to update sense bytes during initialization>,<<T1,CHAN>,<Q2,DX20>>,<

Cause:	GETEXS failed to read in the extended status bytes for a DX20
	during initialization.

Action:	The DX20 may be having problems, look for other DX2xxx BUGCHKs.
	Call Field Service.

Data:	CHAN - Channel number
	DX20 - DX20 number
>,,<DB%NND>)			;[7.1210][7.1054] 
	RET			;RETURN
	SUBTTL DX2CCK - Once an minute check

;DX2CCK - CALLED ONCE A MINUTE FROM PHYCHK TO SEE IF THE DX20
;HAS HALTED, AND IF SO TO TRY AND RESTART IT.
;ARGUMENTS:
;  P1/	CDB
;  P2/	KDB
;  P3/	UDB (ANY ONE WILL DO)
;RETURNS:
;  +1:	ALWAYS
;TRASHES Q2

DX2CCK:	MOVE Q2,K.DXAD(P2)	;GET CONTROLLER NUMBER
	CALL HLTCHK		;IS MICROCODE STILL HAPPY?
	 CALL CHKMIC		;OR IS IT REAL SICK?
	  RET			;YES, NOTHING TO DO
	AOS T1,K.STCT(P2)	;INCREMENT RESTART COUNTER
	CAILE T1,STMAX		;TOO MANY UPS AND DOWNS?
	RET			;YES, LET DX20 REST IN PEACE THEN
	MOVEI T1,STADDR		;GET START ADDRESS
	CALL STDX		;RESTART THE MICROCODE
	MOVX T1,KS.HLT		;GET HALT FLAG
	ANDCAM T1,KDBSTS(P2)	;SAY MICROCODE IS RUNNING AGAIN
	RET			;AND RETURN
	SUBTTL CHKMIC - Check microcode

;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 DX2SIO - 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:	SAVEQ
	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:	CALL FNDCKU		;[7.1054](P1,P2,P3/T1,T2,T3) Get c/k/u numbers
	BUG.(CHK,DX2IFS,PHYX2,SOFT,<PHYX2 - Illegal function at start IO>,<<T1,CHAN>,<T2,DX20>,<T3,UNIT>,<Q1,FNCCOD>>,<

Cause:	DX2SIO was called to start IO for a DX20. This bug indicates that
	either the function code in the IORB was invalid or the short form
	(PAGEM) bit was set in the IORB status word.

Action:	If this BUGCHK persists, change it to a BUGHLT and find out who is
	setting up the IORB incorrectly.

Data:	CHAN   - Channel number
	DX20   - DX20 number
	UNIT   - Tape drive unit
	FNCCOD - Function code
>)
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,KDBACT(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:	MOVE Q2,K.DXAD(P2)	;GET CONTOLLER NUMBER
	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 DX2INT - Done Interrupt Handler

;DX2INT - COME HERE TO PROCESS A DONE INTERRUPT.
; P1/CDB, P2/KDB
; IF KDBACT 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,KDBACT(P2)	;UDB SAVED ON THIS DX20?
	JRST DX2INU		;NO, ERROR
	SETZM KDBACT(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:	HRRZ T1,CDBADR(P1)	;[7.1054] Get channel number
	MOVE T2,K.DXAD(P2)	;[7.1054] Get controller number
	BUG.(CHK,DX2NUD,PHYX2,HARD,<PHYX2 - Channel done interrupt but no unit active>,<<T1,CHAN>,<T2,DX20>>,<

Cause:	DX2INT was called to process a channel done interrupt for a DX20,
	but there was no known active UDB on the controller.

Action:	The DX20 is probably broken.  Look for other DX2xxx BUGCHKs.
	Call Field Service.

Data:	CHAN - Channel number
	DX20 - DX20 number
>,,<DB%NND>)			;[7.1210][7.1054] 
	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
	SKIPG T2,U.HDEN(P3)	;HARDWARE KNOW WHAT THE DENSITY IS?
	LOAD T2,IRBDN,(P4)	;NO, GET THE SOFTWARE DENSITY
	ADDM T1,@RSTATF-1(T2)	;ACCUMULATE FRAMES READ BY DENSITY
	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
	LOAD T2,IRBDN,(P4)	;GET DENSITY
	ADDM T1,@WSTATF-1(T2)	;ACCUMULATE FRAMES WRITTEN BY DENSITY
	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
	HRRZ T2,CDBADR(P1)	;[7.1054] Get channel number
	BUG.(CHK,DX2NUE,PHYX2,HARD,<PHYX2 - DX20 detected hardware problem>,<<T2,CHAN>,<Q2,DX20>,<T4,STSREG>,<T1,ERRREG>>,<

Cause:	A channel done interrupt for a DX20 was being processed, but there
	was no known active UDB on the controller and the composite error
	bit in the DX20 status register was set.  The DX20 runs internal
	diagnostics, and will set this bit when it discovers an error.  If
	the status register contains 100 (octal) and the error register
	contains 6000 (octal) then the DX20 is probably seeing internal
	microbus parity errors.  Otherwise, the error register contains
	the error code.

Action:	The DX20 is probably broken, look for other DX2xxx BUGCHKs.
	Look at the error register and call Field Service.

Data:	CHAN   - Channel number
	DX20   - DX20 number
	STSREG - Status register
	ERRREG - Error register
>,,<DB%NND>)			;[7.1210][7.1054] 
	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, 2 OR 3. (TU70, TU71, TU72, TU73)
	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:	HRRZ T1,CDBADR(P1)	;[7.1054] Get channel number
	MOVE T3,K.DXAD(P2)	;[7.1054] Get unit number
	BUG.(CHK,DX2IDM,PHYX2,HARD,<PHYX2 - Illegal data mode at done interrupt>,<<T1,CHAN>,<T3,DX20>,<T2,DATMOD>>,<

Cause:	At a done interrupt, the data mode in the IORB was found to be
	illegal.

Action:	The DX20 could be broken.  Look for other DX2xxx BUGCHKs.
	Call Field Service.

Data:	CHAN   - Channel number
	DX20   - DX20 number
	DATMOD - Data mode in IORB
>)				;[7.1054] 
	SETZ T3,		;ACT LIKE WORDS
	RET			;RETURN
	SUBTTL DX2ATN - 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,KDBACT(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
	CALL FNDCKU		;[7.1054](P1,P2,P3/T1,T2,T3) Get c/k/u numbers
	BUG.(CHK,DX2UNA,PHYX2,HARD,<PHYX2 - Attention interrupt and UDB not active>,<<T1,CHAN>,<T2,DX20>,<T3,UNIT>>,<

Cause:	At a done interrupt, the UDB marked as active in the KDB was not
	itself marked as active.

Action:	The DX20 or TX02 may be broken.  Look for other DX2xxx BUGCHKs.
	Call Field Service.

Data:	CHAN - Channel number
	DX20 - DX20 number
	UNIT - Tape drive unit
>,,<DB%NND>)			;[7.1210][7.1054]
	SETZB P3,KDBACT(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 KDBACT(P2)	;FLAG ATTN INT
	JRST INTR4		;AND EXIT AS SOON AS POSSIBLE
NDOP:	SETZM KDBACT(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 DX2ERR - 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
	HRRZ T1,T4
	SKIPN T1,RTYBPT(T1)	;GET RETRY BYTE POINTER
	JRST ILERTY		;[7.1054] Illegal retry pointer
	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!
	HRRZ T1,T4		;GET INDEX ONLY
	MOVE T1,RTYBPT(T1)	;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
	HRRZ T1,T4		;GET INDEX ONLY
	MOVE T1,RTYBPT+1(T1)	;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 ILLRF		;[7.1054] No, it is illegal
	HRRM T3,UDBERR(P3)	;SAVE FUNCTION
	CALL SETIO		;SET UP FOR I/O
	CALL CDSSIO(T1)		;START IO
	 JRST ABTNOS		;COULDN'T START UP RETRY OPERATION
	RET			;AND WAIT
;Here when an illegal retry function is seen

ILLRF:	CALL FNDCKU		;[7.1054] (P1,P2,P3/T1,T2,T3) Get cku numbers
	BUG.(CHK,DX2IRF,PHYX2,HARD,<PHYX2 - Illegal function during retry>,<<T1,CHAN>,<T2,DX20>,<T3,UNIT>>,<

Cause:	During error recovery, an illegal retry function was discovered.

Action:	The DX20 is probably broken.  Look for other DX2xxx BUGCHKs.
	Call Field Service.

Data:	CHAN - Channel number
	DX20 - DX20 number
	UNIT - Tape drive unit
>)
	JRST ABTNOS		;[7.1054] Fatal error

;Here when the retry byte pointer index from IRBSTS was illegal.

ILERTY:	CALL FNDCKU		;[7.1054] (P1,P2,P3/T1,T2,T3) Get cku numbers
	BUG.(CHK,DX2IDX,PHYX2,HARD,<PHYX2 - Illegal retry byte pointer index>,<<T1,CHAN>,<T2,DX20>,<T3,UNIT>,<T4,FUNC>>,<

Cause:	While trying to do error recovery for a non-fatal DX20 error, it
	was found that the byte pointer to the retry type was zero.  This
	indicates that a retry is not possible for this error type.  The
	index is retrived from IRBSTS of the IORB.

Action:	The DX20 could be broken.  Look for other DX2xxx BUGCHKs.
	Call Field Service.

Data:	CHAN - Channel number
	DX20 - DX20 number
	UNIT - Tape drive unit
	FUNC - Bad function code from the IORB
>)
	JRST ABTNOS		;[7.1054] Call it fatal
;Here when retry finished without errors (we recovered)

RTYNOE:	TXNE T1,IS.NRT		;HARD ERRS SHOULDN'T EVER GET HERE
	CALL RTYNRT		;[7.1054] No retry was set
	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

RTYNRT:	CALL FNDCKU		;[7.1054] (P1,P2,P3/T1,T2,T3) Get cku numbers
	BUG.(CHK,DX2NRT,PHYX2,HARD,<DX2ERR - IS.NRT set on successful retry>,<<T1,CHAN>,<T2,DX20>,<T3,UNIT>>,<

Cause:	A retry from a DX20 error was performed successfully, but the IORB
	indicates that this should have been a hard error.

Action:	The DX20 or TX02 may be broken.  Look for other DX2xxx BUGCHKs.
	Call Field Service.

Data:	CHAN - Channel number
	DX20 - DX20 number
	UNIT - Tape drive unit
>)				;[7.1054] 	

;Here when error recovery gets confused (flakey hardware  W I L L  do it)

CNFERR:	CALL FNDCKU		;[7.1054] (P1,P2,P3/T1,T2,T3) Get cku numbers
	BUG.(CHK,DX2RFU,PHYX2,HARD,<PHYX2 - Error recovery confused>,<<T1,CHAN>,<T2,DX20>,<T3,UNIT>>,<

Cause:	The error recovery procedure specified in the UDB is incorrect.

Action:	DX20 or TX02 hardware may be flakey.  Look for other DX2xxx 
	BUGCHKs.  Call Field Service.

Data:	CHAN - Channel number
	DX20 - DX20 number
	UNIT - Tape drive unit
>)				;[7.1054] 
	MOVSI T1,(IS.ERR!IS.NRT) ;INDICATE RATHER HARD ERR
	IORM T1,IRBSTS(P4)	; ...
	JRST ABTNOS		;AND ABORT
;Here when we have run out of retries for this operation.

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 Tables

;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:	IFIW!M70FMT(T2)		;TU70
	IFIW!M71FMT(T2)		;TU71
	IFIW!M70FMT(T2)		;TU72
	IFIW!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)


;TABLE OF FRAMES READ/WRITTEN BY MODE (NRZI, PE, GCR)
RSTATF:	IFIW!UDBRNR(P3)		;(1) 200BPI - NRZI
	IFIW!UDBRNR(P3)		;(2) 556BPI - NRZI
	IFIW!UDBRNR(P3)		;(3) 800BPI - NRZI
	IFIW!UDBRPE(P3)		;(4) 1600BPI - PE
	IFIW!UDBRGC(P3)		;(5) 6250BPI - GCR
WSTATF:	IFIW!UDBWNR(P3)		;200 - NRZI
	IFIW!UDBWNR(P3)		;556 - NRZI
	IFIW!UDBWNR(P3)		;800- NRZI
	IFIW!UDBWPE(P3)		;1600 - PE
	IFIW!UDBWGC(P3)		;6250 - GCR
	SUBTTL DX20 Error Recovery Tables

;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>>>

;WRITE RETRY - SPACE REVERSE, ERASE, CHECK POSITION, WRITE
TBRWRT:	BYTE (4) IRFBSB,IRFERG,RTY.CP,IRFWRT,RTY.DN

;WRITE TM RETRY - SPACE REVERSE, ERASE, CHECK POS, WTM, EOR
TBRWTM:	BYTE (4) IRFBSB,IRFERG,RTY.CP,IRFWTM,RTY.DN

;READ FORWARD RETRY - SPACE REVERSE, CHECK POSITION, READ FORWARD
TBRRF:	BYTE (4) IRFBSB,RTY.CP,IRFRED,RTY.DN

;READ REVERSE RETRY - SPACE FORWARD, CHECK POSITION, READ REVERSE
TBRRR:	BYTE (4) IRFFSB,RTY.CP,IRFRDR,RTY.DN

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

;RD REVERSE TAPE CLEAN: 5 SP REVERSE, 6 SP FORWARD, CHECK POSITION, RD REVERSE
TBRRRC:	FOO<CLNREC,IRFBSB, CLNREC+1,IRFFSB, 1,RTY.CP, 1,IRFRDR, 1,RTY.DN>
	SUBTTL End of PHYX2

	TNXEND
	END