Google
 

Trailing-Edge - PDP-10 Archives - BB-M081Z-SM - monitor-sources/phym78.mac
There are 27 other files named phym78.mac in the archive. Click here to see a list.
; Edit= 8990 to PHYM78.MAC on 2-Nov-88 by LOMARTIRE
;Merge Production changes to BUG text
; Edit= 8913 to PHYM78.MAC on 17-Aug-88 by GSCOTT
;Update BUG. documentation. 
; Edit= 8830 to PHYM78.MAC on 14-Apr-88 by GSCOTT (TCO 7.1275)
;Install TCO 7.1275 into autopatch sources. 
; UPD ID= 8699, RIP:<7.MONITOR>PHYM78.MAC.10,  14-Apr-88 14:35:36 by GSCOTT
;TCO 7.1275 - Wait 40000 times for DI.TMR (TM ready) after DO.TMC (TM clear) 
; is set - this is what TOPS-blue does when it wants to reset the TM78.
; Output drive number on a TM8SNS. 
; UPD ID= 8588, RIP:<7.MONITOR>PHYM78.MAC.9,  11-Feb-88 16:55:41 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 8435, RIP:<7.MONITOR>PHYM78.MAC.8,   4-Feb-88 15:14:21 by GSCOTT
;TCO 7.1210 - Set REVLEV, TM8AEI, TM8AFU, TM8FKR, TM8N2S, TM8NUD, TM8REW,
; and TM8SNS normally not dumpable.
; UPD ID= 8430, RIP:<7.MONITOR>PHYM78.MAC.6,   4-Feb-88 14:08:14 by GSCOTT
;TCO 7.1214 - Output TM78 status bits when we get a TM8FKR
; UPD ID= 264, RIP:<7.MONITOR>PHYM78.MAC.3,   6-Nov-87 10:51:20 by GSCOTT
;TCO 7.1116 - Add TM8CHK routine to fix lost done interrupts, fix up BUGs.
; Fix SUBTTLs, add table of contents, don't refer to the TU78 as a drive, just
; say "tape drive" which will apply to either TU78 or TU79.
; *** Edit 7457 to PHYM78.MAC by GSCOTT on 23-Apr-87, for SPR #21597
; Make SET ONLINE command work for drives connected to TM02/TM03/TM78 
; Edit 7142 to PHYM78.MAC by EVANS on 29-Aug-85, for SPR #20701 (TCO 6-1-1533 )
; Count number of physical records read or written.
; UPD ID= 2159, SNARK:<6.1.MONITOR>PHYM78.MAC.32,   5-Jun-85 10:41:20 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 1922, SNARK:<6.1.MONITOR>PHYM78.MAC.31,   7-May-85 21:17:21 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1828, SNARK:<6.1.MONITOR>PHYM78.MAC.30,  25-Apr-85 16:38:16 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1794, SNARK:<6.1.MONITOR>PHYM78.MAC.29,  23-Apr-85 13:17:36 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1745, SNARK:<6.1.MONITOR>PHYM78.MAC.28,   9-Apr-85 15:43:58 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 4824, SNARK:<6.MONITOR>PHYM78.MAC.27,  17-Sep-84 10:43:15 by PURRETTA
;Update copyright notice
; UPD ID= 4646, SNARK:<6.MONITOR>PHYM78.MAC.26,   2-Aug-84 11:12:29 by HAUDEL
;TCO 6.2159 - CHANGE THE INTERRUPT DISPATCHING AC, THAT IS SET UP FROM ICDTBL,
;TO BA A LOCAL INDEX AND NOT A GLOBAL ONE. INTRRO NEEDS THIS.
; UPD ID= 4614, SNARK:<6.MONITOR>PHYM78.MAC.25,  27-Jul-84 15:28:13 by HAUDEL
;TCO 6.2145 - PREVENT NOIORB FROM SPURIOUS REW INTERRUPT.
; UPD ID= 4600, SNARK:<6.MONITOR>PHYM78.MAC.24,  27-Jul-84 08:09:26 by HAUDEL
;TCO 6.2127 - ADD DATA ITEMS TO TM8AEI BUGCHK
; UPD ID= 4392, SNARK:<6.MONITOR>PHYM78.MAC.23,  27-Jun-84 12:10:04 by HAUDEL
;TCO 6.2019 - INCREMENT UDBPS2 WHEN WRITING A TM. THIS IS FOR LABELLED TAPES.
; UPD ID= 3659, SNARK:<6.MONITOR>PHYM78.MAC.22,   7-Feb-84 14:55:09 by HAUDEL
;More TCO 6.1818 - ADJUST CODE FOR SECTION 1 OPERATION.
; UPD ID= 3398, SNARK:<6.MONITOR>PHYM78.MAC.21,   3-Jan-84 11:42:26 by HAUDEL
;More TCO 6.1794 - Change REVLEV bugchk to buginf
; UPD ID= 3109, SNARK:<6.MONITOR>PHYM78.MAC.20,   7-Nov-83 21:24:02 by MCLEAN
;ADD PORT RELEASE DISPATCH
; UPD ID= 3020, SNARK:<6.MONITOR>PHYM78.MAC.19,  10-Oct-83 16:21:42 by MURPHY
;Clean up format.
; UPD ID= 3003, SNARK:<6.MONITOR>PHYM78.MAC.18,   5-Oct-83 20:13:19 by MCLEAN
;TCO 6.1818 RE-ADJUST CODE FOR SECTION 1 OPERATION
; UPD ID= 2928, SNARK:<6.MONITOR>PHYM78.MAC.17,  23-Sep-83 11:40:28 by HAUDEL
;TCO 6.1794 - Add REVLEV bugchk and make a 31 class error fatal.
; UPD ID= 2898, SNARK:<6.MONITOR>PHYM78.MAC.16,  16-Sep-83 14:37:50 by HAUDEL
;TCO 6.1757 - Save T4 in BEGLOD before call to SEBCPY
; UPD ID= 2615, SNARK:<6.MONITOR>PHYM78.MAC.15,  21-Jun-83 13:10:49 by HAUDEL
;TCO 6.1697 - Reset SAVFNC in TM8HNG code.
; UPD ID= 2614, SNARK:<6.MONITOR>PHYM78.MAC.14,  21-Jun-83 13:01:47 by HAUDEL
;TCO 6.1696 - Do not set KDBACT on SENSE operation after online interupt
; UPD ID= 2613, SNARK:<6.MONITOR>PHYM78.MAC.13,  21-Jun-83 12:32:25 by HAUDEL
;TCO 6.1695 - Add SOS (P) to Reread Opposite code
; UPD ID= 2579, SNARK:<6.MONITOR>PHYM78.MAC.12,  14-Jun-83 09:53:00 by HAUDEL
;TCO 6.1668 - Add SAVEQ at TM8SI0
; UPD ID= 2416, SNARK:<6.MONITOR>PHYM78.MAC.11,   4-May-83 08:16:44 by HAUDEL
;TCO 6.1640 - Change code after TM8NUD  bugchk
; UPD ID= 1980, SNARK:<6.MONITOR>PHYM78.MAC.10,  11-Mar-83 15:56:19 by HAUDEL
;TCO 6.1539 - Change SAVUDB,KDBACT,SAVFNC so that SENSE works correctly
; UPD ID= 1946, SNARK:<6.MONITOR>PHYM78.MAC.9,   9-Mar-83 10:24:35 by HAUDEL
;TCO 6.1512 - Add code for high density format mode,fix TCO 6.1410
; UPD ID= 1719, SNARK:<6.MONITOR>PHYM78.MAC.8,  28-Jan-83 14:20:04 by DONAHUE
;TCO 6.1431 - Clear the interrupt if no UDB is found
; UPD ID= 1604, SNARK:<6.MONITOR>PHYM78.MAC.7,  29-Dec-82 13:47:38 by DONAHUE
;TCO 6.1410 - Change references to MTINDX to use STKVAR's
; UPD ID= 1115, SNARK:<6.MONITOR>PHYM78.MAC.6,  26-Aug-82 14:07:43 by HAUDEL
;TCO 5.1.1056 - Add code to set device online after TM78 power turned on.
; UPD ID= 1077, SNARK:<6.MONITOR>PHYM78.MAC.5,  11-Aug-82 09:25:27 by WACHS
;TCO 5.1780 - Set up Q2 after extended status read interrupt
; UPD ID= 591, SNARK:<5.MONITOR>PHYM78.MAC.35,  29-Jun-82 04:25:25 by WACHS
; UPD ID= 965, SNARK:<6.MONITOR>PHYM78.MAC.4,  29-Jun-82 04:34:54 by WACHS
;TC0 5.1779 - Clear TU7ECD, TU7SNS before starting IO
;TCO 5.1778 - Inhibit error repositioning on last error retry
; UPD ID= 904, SNARK:<6.MONITOR>PHYM78.MAC.2,   9-Jun-82 23:25:34 by MURPHY
;TCO 6.1147 - Move bugdefs from BUGS.MAC to here and put them in-line.
; UPD ID= 501, SNARK:<5.MONITOR>PHYM78.MAC.34,   5-Mar-82 06:24:45 by WACHS
;TCO 5,1747 - Set up Q1 on interrupt from sense after read of 1st record
;TCO 5,1748 - Worry about RAEs if TM is powered off
; UPD ID= 488, SNARK:<5.MONITOR>PHYM78.MAC.33,  26-Feb-82 11:09:27 by WACHS
;TCO 5.1740 - Check for HOLD in TM status register
; UPD ID= 446, SNARK:<5.MONITOR>PHYM78.MAC.32,  29-Jan-82 05:15:56 by WACHS
;TCO 5.1710 - Set up UDBSLV
; UPD ID= 432, SNARK:<5.MONITOR>PHYM78.MAC.31,  22-Jan-82 08:34:50 by WACHS
;TCO 5.1696 Limit the number of async interrupts to a maximum of 8
; UPD ID= 266, SNARK:<5.MONITOR>PHYM78.MAC.30,  16-Oct-81 11:06:41 by WACHS
;TCO 5.1586 - Increase the retry counter to greater than the microcode's
; UPD ID= 208, SNARK:<5.MONITOR>PHYM78.MAC.29,  23-Sep-81 05:19:24 by WACHS
; UPD ID= 199, SNARK:<5.MONITOR>PHYM78.MAC.28,  21-Sep-81 06:45:53 by WACHS
;TCO 5.1517 Generate a PSI interrupt on REWIND, even if tape is at BOT
; UPD ID= 81, SNARK:<5.MONITOR>PHYM78.MAC.27,  27-Jul-81 09:17:38 by WACHS
;TCO 5.1435 Don't try to read status after TU fault b, MB fault
; UPD ID= 36, SNARK:<5.MONITOR>PHYM78.MAC.26,  16-Jul-81 09:39:10 by WACHS
; UPD ID= 35, SNARK:<5.MONITOR>PHYM78.MAC.25,  16-Jul-81 06:18:04 by WACHS
;TCO 5.1416 Fix bit to check for dual-ported drives
; UPD ID= 2302, SNARK:<5.MONITOR>PHYM78.MAC.24,   7-Jul-81 10:58:24 by WACHS
;TCO 5.1395 Save, restore CDBICR over call to read extended status
; UPD ID= 2041, SNARK:<5.MONITOR>PHYM78.MAC.23,  20-May-81 06:22:32 by WACHS
;TCO 5.1336 Add bits to ICDTBL for entry 22
; UPD ID= 2020, SNARK:<5.MONITOR>PHYM78.MAC.22,  19-May-81 03:43:46 by WACHS
;TCO 5.1333 More checking on done interrupts to make sure we did something
; UPD ID= 1820, SNARK:<5.MONITOR>PHYM78.MAC.21,  17-Apr-81 09:49:55 by WACHS
;TCO 5.1288 Maintain statistics by mode (PE, GCR)

;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1976, 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 (PHYM78,,< - Device Dependent Code For TM78/TU78/TU79 Magtapes >)
	SUBTTL T. WACHS 22-MAY-80
	Subttl	Table of Contents

;		     Table of Contents for PHYM78
;
;				  Section		      Page
;
;
;    1. Parameters . . . . . . . . . . . . . . . . . . . . . .   3
;    2. Device Dependent Table Defs  . . . . . . . . . . . . .   5
;    3. Dispatch For TM78  . . . . . . . . . . . . . . . . . .   6
;    4. Periodic Check Routine . . . . . . . . . . . . . . . .   7
;    5. Handle Hung Device . . . . . . . . . . . . . . . . . .   8
;    6. Check if Legal Unit  . . . . . . . . . . . . . . . . .   9
;    7. Check for Position Required  . . . . . . . . . . . . .  10
;    8. Reset TM78 . . . . . . . . . . . . . . . . . . . . . .  11
;    9. Start I/O Routine  . . . . . . . . . . . . . . . . . .  12
;   10. Interrupt Processing
;       10.1    Attention Interrupt  . . . . . . . . . . . . .  16
;       10.2    Command Done . . . . . . . . . . . . . . . . .  18
;       10.3    Analyze What Happened  . . . . . . . . . . . .  21
;       10.4    Action Routines  . . . . . . . . . . . . . . .  26
;   11. Error Recovery . . . . . . . . . . . . . . . . . . . .  29
;   12. TM78 Initializing Routine  . . . . . . . . . . . . . .  33
;   13. Tables To Control I/O  . . . . . . . . . . . . . . . .  39
	SUBTTL Parameters

	;DRIVE REGISTERS USED IN DATAO'S

	.DOCR==0B5		;DRIVE CONTROL REGISTER
	.DOICD==1B5		;INTERRUPT CODE (DATA XFER)
	   DO.ICD==77		;INTERRUPT CODE
	   DI.FCD==176000	;FAILURE CODE
	.DOFMT==2B5		;RECORD COUNT/FORMAT
	   DO.SER==100000	;SUPPRESS ERROR REPOSITIONING
	   DO.RC1==4		;RECORD COUNT RIGHTMOST BIT
	.DOER==3B5		;ERROR REGISTER
	.DOAS==4B5		;ATTENTION SUMMARY
	.DOBC==5B5		;BYTE COUNT
	.DODT==6B5		;DRIVE TYPE
	.DOSR==7B5		;STATUS REGISTER
	   DI.RDY==100000	;READY
	   DI.PRS==40000	;DRIVE PRESENT
	   DI.PE==4000		;PHASE ENCODED
	   DI.BOT==2000		;AT BOT
	   DI.FPT==400		;FILE PROTECTED
	   DI.AVL==200		;AVAILABLE (TO THIS MASSBUS)
	   DI.MNT==40		;IN MAINTENANCE MODE
	.DOSN==10B5		;SERIAL NUMBER
	.DODG==11B5		;DIAGNOSTIC
	.DODG2==12B5		;DIAGNOSTIC
	.DOICN==13B5		;INTERRUPT CODE (NON DATA-XFER)
	   DI.DRV==1400		;DRIVE NUMBER
	.DOND0==14B5		;NON DATA-XFER COMMAND, UNIT 0
	   DO.NDC==177400	;COUNT FIELD
	   DO.NDF==77		;FUNCTION CODE
	   NDCSHF==^D8		;SHIFT VALUE FOR COUNT
	.DOND1==15B5		;COMMAND, UNIT 1
	.DOND2==16B5		;COMMAND, UNIT 2
	.DOND3==17B5		;COMMAND, UNIT 3
	.DOIA==20B5		;INTERNAL ADDRESS
	.DOTMS==21B5		;TM STATUS
	   DI.TMR==1B20		;TM READY
	   DO.TMC==1B21		;TM CLEAR
	   DI.MPE==1B22		;[7.1214] Microcode parity error
	   DI.ILR==1B23		;[7.1214] Illegal massbus register accessed
	   DI.CPE==1B24		;[7.1214] Parity error while writing MB reg
	   DO.EVP==1B25		;[7.1214] (Diagnostic) write even parity MB ctl
	   DO.HLA==1B26		;HOLD ACKNOWLEDGED
	   DO.HLD==1B27		;HOLD

DO.ERD==177777			;BITS IN DATAO (MASSBUS IS 16 BITS)

	;DRIVE FUNCTIONS
	DF.NOP==3		;NO-OP
	DF.UNL==5		;UNLOAD
	DF.REW==7		;REWIND
	DF.SNS==11		;SENSE
	DF.DSE==13		;DATA SECURITY ERASE
	DF.WTM==15		;WRITE TAPE MARK (PE)
	DF.SPF==21		;SPACE FORWARD RECORD
	DF.SPR==23		;SPACE REVERSE RECORD
	DF.SFF==25		;SPACE FORWARD FILE
	DF.SRF==27		;SPACE REVERSE FILE
	DF.SFE==31		;SPACE FORWARD RECORD OR FILE
	DF.SRE==33		;SPACE REVERSE RECORD OR FILE
	DF.ERG==35		;ERASE 3 INCHES OF TAPE (PE)
	DF.CLF==41		;CLOSE FILE (PE) - 2 EOFS, BACKSP 1
	DF.LET==45		;SKIP TO LOGICAL EOT

	DF.WRT==61		;WRITE (PE)
	DF.RED==71		;READ
	DF.RRV==77		;READ REVERSE
	DF.XSN==73		;EXTENDED SENSE
	SUBTTL Device Dependent Table Defs

;****************************
;UDB EXTENSIONS
	TU7HDN==UDBDDM		;HARDWARE-DETERMINED DENSITY
				; NOTE THAT MAGTAP USES THIS WORD
	TU7SNS==TU7HDN+1	;NON-0 IF DOING A SENSE OPERATION
	TU7ECD==TU7SNS+1	;ERROR BITS FROM TABLE IF AN ERROR ON LAST IO
	TU7ESD==TU7ECD+1	;SAVED ERROR BITS WHILE DOING A SENSE
	TU7RRO==TU7ESD+1	;NON-0 IF IN REREAD OPPOSITE ERROR RECIVERY
	SAVFNC==TU7RRO+1	;CURRENT FUNCTION/FLAGS
	LU.TM8==SAVFNC+1	;LENGTH OF TM78 UDB

;****************************
;KDB DEVICE DEPENDENT PORTION
	TM8ADR==KDBDDP+4	;MASSBUS ADDRESS OF TM78
	SAVUDB==TM8ADR+1	;CURRENT UDB (0 IF NONE)
	SAVLSI==SAVUDB+1	;LAST INTERRUPT CODE 
	TM8XCW==SAVLSI+1	;CCW FOR READING EXTENDED SENSE INFO
	TM8SCW==TM8XCW+1	;SAVED CCW WHILE READING EXTENDED SENSE
	TM8ACT==TM8SCW+1	;COUNT OF ASYNCHRONOUS INTERRUPTS
	TM8CNI==TM8ACT+1	;CONI OF RH GOES HERE
	TM8CS1==TM8CNI+1	;DATAI RH CONTROL REGISTER
	TM8DBF==TM8CS1+1	;DATAI RH DATA REGISTER
	TM8REG==TM8DBF+1	;DRIVE REGISTERS GO HERE
	 DR.CR==0		;DRIVE CONTROL REGISTER
	 DR.ICD==1		;INTERRUPT CODE (DATA XFER)
	 DR.FMT==2		;RECORD COUNT/FORMAT
	 DR.ER==3		;ERROR REGISTER
	 DR.AS==4		;ATTENTION SUMMARY
	 DR.BC==5		;BYTE COUNT
	 DR.DT==6		;DRIVE TYPE
	 DR.SR==7		;STATUS REGISTER
	 DR.SN==10		;SERIAL NUMBER
	 DR.DG==11		;DIAGNOSTIC
	 DR.DG2==12		;DIAGNOSTIC
	 DR.ICN==13		;INTERRUPT CODE (NON DATA-XFER)
	 DR.ND0==14		;NON DATA-XFER COMMAND, UNIT 0
	 DR.ND1==15		;COMMAND, UNIT 1
	 DR.ND2==16		;COMMAND, UNIT 2
	 DR.ND3==17		;COMMAND, UNIT 3
	 DR.IA==20		;INTERNAL ADDRESS
	 DR.TMS==21		;TM STATUS
	TM8REV==TM8REG+22	;ROM REV LEVELS
	TM8XSN==TM8REV+2	;EXTENDED SENSE INFORMATION
	TM8ELN==TM8XSN+17-TM8REG ;LENGTH OF ERROR REGION
	LK.TM8==TM8XSN+17	;LENGTH OF KDB

	TM8SLC==4		;MAX NO OF DRIVES ON A TM78
	TM8AMX==10		;MAX NO OF ASYNC INTERRUPTS BEFORE STOPPING TM
RTYOP==^D55			;MAX NO OF RETRIES (IF NOT ERR CODE 22)
				;THIS MUST BE GTR THAN 50 (THE MICROCODE'S VALUE)
				; TO PREVENT OVERWRITING HARD ERROR RECORDS
ERSTRY==400			;BIT TO TELL PHYH2 ABOUT ALREADY-SET IOLIST
	SUBTTL Dispatch For TM78

TM8DSP::JRST TM8INI		;0 - INITIALIZATION
	JRST TM8SI0		;1 - START I/O
	JRST TM8INT		;2 - HANDLE INTERRUPT (DATA OPERATION)
	JRST TM8ERR		;3 - ERROR RECOVERY
	JRST TM8HNG		;4 - HUNG DEVICE
	RET			;5 - NOT USED
	RET			;6 - NOT USED
	JRST TM8SI0		;7 - START POSITION OPERATION
	JRST TM8ATN		;10 - ATTENTION INTERRUPT 
	JRST TM8PRQ		;11 - SKIP IF POSITION REQUIRED
	RET			;12 - STACK SECOND COMMAND, FAIL FOR TM78
	JRST TM8LGL		;13 - CHECK LEGALITY OF A UNIT
	JRST TM8CHK		;14 - [7.1116] Controller check
	JRST R			;15 - PORT RELEASE (UNUSED)
	SUBTTL Periodic Check Routine

;[7.1116] TM8CHK - Called here once a minute to check on KS.ACT bit.
;[7.1116] Cycles through UDBs and checks for any active.  If none are
;[7.1116] active and KS.ACT is set, clear it and BUGCHK.  This prevents
;[7.1116] jobs hung because of lost TM78 done interrupts.
;[7.1116]
;[7.1116] Call with:
;[7.1116]		P1/ CDB
;[7.1116]		P2/ KDB
;[7.1116] Smashes T1-T4

TM8CHK:	MOVX T4,KS.ACT		;[7.1116] Load kontroller active status bit
	TDNN T4,KDBSTS(P2)	;[7.1116] Does PHYSIO think we are busy?
	RET			;[7.1116] No, return now
	MOVX T3,US.ACT		;[7.1116] Load UDB status bit for later tests
	MOVE T1,KDBIUN(P2)	;[7.1116] Load AOBJN word to UDB addresses

TM8CH1:	SKIPN T2,(T1)		;[7.1116] Is there a UDB for this unit?
	JRST TM8CH2		;[7.1116] Nope
	TDNE T3,UDBSTS(T2)	;[7.1116] Skip if unit is not active
	RET			;[7.1116] Return if an active UDB, it's OK
TM8CH2:	AOBJN T1,TM8CH1		;[7.1116] Loop for all units

;[7.1116] KS.ACT set but no UDBs were active.  Clear KS.ACT and BUGCHK.

	HRRZ T1,CDBADR(P1)	;[7.1116] Get channel number
	HRRZ T2,TM8ADR(P2)	;[7.1116] Get kontroller number
	MOVE T3,SAVUDB(P2)	;[7.1116] Load saved UDB (probably 0)
	BUG.(CHK,TM8AFU,PHYM78,SOFT,<PHYM78 - Active found up with no active units>,<<T1,CHAN>,<T2,CONT>>,<

Cause:	This BUGCHK happens when the KS.ACT bit is on in the KDB but US.ACT
	wasn't set in any UDBs during a periodic check.  This is not expected
	to happen.  KS.ACT is cleared and normal tape operation is restored.

Action:	The hardware may be flakey or broken.  Field Service should check out
	the TM78 hardware.  If the hardware checks out OK, change this BUGCHK
	to a BUGHLT and submit an SPR along with the dump and how to reproduce
	the problem.

Data:	CHAN - Channel number
	CONT - Controller number
	SAVUDB - Contents of SAVUDB

>,,<DB%NND>)			;[7.1210][7.1116] 
	ANDCAM T4,KDBSTS(P2)	;[7.1116] Turn off KS.ACT in the KDB
	RET			;[7.1116] Return to caller
	SUBTTL Handle Hung Device

;[7457] TM8HNG - Called here when device is hung
;[7457] Call with:
;[7457]		P1/ CDB
;[7457]		P2/ KDB
;[7457]		P3/ UDB
;[7457] 	P4/ IORB

TM8HNG:	MOVX T1,IS.NRT!IS.ERR!IS.DVE ;SET FATAL BITS
	IORM T1,IRBSTS(P4)	;AND REFRESH IT
	HRRZ T2,CDBICP(P1)
	SKIPE T1,TM8SCW(P2)	;IS THERE A SAVED CCW (USING A FAKE FOR EXTENDED STATUS)?
	MOVEM T1,(T2)		;YES, PUT BACK THE REAL CCW
	SETZM TM8SCW(P2)	;NO SAVED CCW NOW
	SETZM TU7SNS(P3)	;MAKE SURE THESE FLAGS ARE CLEAR
	SETZM TU7RRO(P3)
	SETZM  SAVFNC(P3)
	RET
	SUBTTL Check if Legal Unit

;[7457] TM8LGL - Called here to check if legal unit
;[7457] Call with:
;[7.1116] 	Q2/ unit number
;[7457] Just checks unit number and lets PHYSIO do the work

TM8LGL:	CAILE Q2,3		;ONLY 4 UNITS ARE LEGAL
	JRST RFALSE		;BUT PHYSIO THINKS 8 ARE OK
	JRST EXTUDB		;GO SEE WHAT PHYSIO THINKS
	SUBTTL Check for Position Required

;HERE TO DETERMINE IF THIS REQUEST SHOULD GO ON PWQ OR TWQ
TM8PRQ:	LDB T1,IRYFCN		;GET FUNCTION
	SKIPL FNCTBL(T1)	;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
	SUBTTL Reset TM78

;ROUTINE TO RESET THE TM78 AND WAIT FOR DONE
;RETURNS +1 (ALWAYS) WITH T4 NON-0 IF WE WON, =0 IF WE LOST

TM8ZAP:	MOVE T2,[.DOTMS!DO.TMC]	;Light the TM clear bit for the TM78
	CALL WTREG3		;(T2,Q2,P1/)
	MOVEI T4,40000		;[7.1275][7.1116] Wait a very very long time
TM8ZA1:	MOVSI T2,(.DOTMS)	;Select the TM status register
	PUSHJ P,RDREG3		;(T2,Q2,P1/T1) Read the TM78 status register
	TRNE T1,DI.TMR		;[7.1116] TM ready?
	RET			;[7.1116] Yes, return
	SOJG T4,TM8ZA1		;[7.1116] No, try again

;The TM78 didn't respond to the reset.  It appears to be taking a dirt nap.

	ANDX T1,DI.TMR!DI.MPE!DI.ILR!DI.CPE ;[7.1214] Clear all but good bits
	HRRZ T2,CDBADR(P1)	;[7.1214][7.1116] Get channel number
	BUG.(CHK,TM8FKR,PHYM78,HARD,<PHYM78 - TM78 failed kontroller reset>,<<T1,STATUS>,<T2,CHAN>,<Q2,CONT>>,<

Cause:	This BUGCHK happens when the monitor is attempting to reset a TM78
	controller and the controller failed to become ready after a very long
	wait.  The first word of additional data shows the TM78 status
	register.  If any bits are set in this word, there is a serious TM78
	hardware failure.

Action:	The TM78 or other hardware may be flakey or broken.  Field Service
	should check out the TM78.

Data:	STATUS - TM78 status (register 3)
	CHAN - Channel number
	CONT - Controller number

>,,<DB%NND>)			;[7.1275][7.1210][7.1214][7.1116] 
	RET			;[7.1116] Return to caller
	SUBTTL Start I/O Routine

;C(P4)=IORB C(P1)=CDB C(P2)=KDB C(P3)=UDB
;IF IN ERR RECOVERY, GET FN FROM RH(UDBERR)
;RET MEANS RE-CALL IN 1 MIN TO TRY AGAIN
;PUTS TM78 FN IN Q1, AND DATAO IN T2
;RETSKP (CHSTRT) MEANS OK, IT'S STARTED

TM8SI0:	SAVEQ
	SETZM TU7ECD(P3)	;MAKE SURE FLAGS ARE ZERO AT START
	SETZM TU7SNS(P3)

TM8SIO:	MOVX T2,.DOTMS		;READ STATUS REGISTER
	CALL RDREG
	JUMPE T1,CLRCHL		;IF POWERED DOWN, RESET RH INTERRUPT ENABLE
	TRNE T1,DI.TMR		;TM READY?
	TRNE T1,DO.HLD		;HOLD OFF?
	RET			;NO, "PROBLEM ON DEVICE"
				;START OF TCO 5.1.1056
	MOVX T2,US.OFS		;GET THE OFFLINE/ONLINE STATUS BIT
	ANDCAM T2,UDBSTS(P3)	;MAKE SURE DRIVE ISN'T MARKED OFFLINE.
				;END OF TCO 5.1.1056
	SKIPN Q1,UDBERR(P3)	;YES. GET FUNCTION IF ERROR RECOVERY
	LOAD Q1,ISFCN,(P4)	;NO, GET FN FROM IORB
	SKIPE Q1,FNCTBL(Q1)	;VALID FN?
	SKIPGE IRBSTS(P4)	;MAKE SURE PAGEM NOT SET
	JRST BADSIO		;IF SET REFUSE IT
	LOAD T1,IRBDN,(P4)	;DENSITY
	CAIG T1,MAXDEN
	SKIPGE T1,DENTBL(T1)	;LEGAL?
	JRST ILLFNC
	TXNE Q1,TB.WRT		;WRITE?
	TRO Q1,(T1)		;YES, SET GCR/PE IN FUNCTION
	LOAD T1,IRBPAR,(P4)	;GET PARITY
	JUMPE T1,TM8SI1		;GO IF ODD PARITY
ILLFNC:	MOVX T1,IS.ERR!IS.NRT!IS.DVE
	IORM T1,IRBSTS(P4)	;BAD PARITY/DENSITY - HARD ERROR
	RET
TM8SI1:	SKIPGE TM8ACT(P2)	;HOLD SET?
	CALL CLRHLD		;YES, CLEAR IT
	SETZM TM8ACT(P2)	;INDICATE NO ASYNC INTERRUPTS
	JUMPL Q1,TM8SI4		;GO IF A DATA OP
	SKIPN UDBERR(P3)	;NON-DATA. IN ERROR RECOVERY?
	SKIPA T2,IRBCNT(P4)	;NO, GET RECORD COUNT FROM IORB
	MOVEI T2,1		;YES, ONLY DO 1 RECORD
	LSH T2,NDCSHF		;PUT COUNT WHERE THE HDWRE WANTS IT
	ANDI T2,DO.NDC		;8 BITS-WORTH
	TRO T2,(Q1)		;PUT FUNCTION INTO COMMAND
	CAME Q1,REWFNC		;REWIND?
	JRST TM8SI2		;NO
	SETZM UDBPS2(P3)	;YES, SET AT 0TH REC, 0TH FILE
	SETZM UDBPS1(P3)
	JRST TM8SI2		;AND KEEP ON
;HERE TO DO A SENSE ON A GIVEN DRIVE

SENSE:	MOVEM Q1,TU7SNS(P3)	;LET EVERYONE KNOW WHAT WE'RE DOING
	MOVEI T2,DF.SNS		;FUNCTION = SENSE
TM8SI2:	HLL T2,UDBSLV(P3)	;POINT AT RIGHT REGISTER FOR THIS DRIVE
	MOVX T1,US.OFS
	CAMN Q1,UNLFNC		;UNLOAD?
	IORM T1,UDBSTS(P3)	;YES, SET THE DRIVE OFF-LINE
	MOVEM Q1,SAVFNC(P3)	;SAVE WHAT WE'RE DOING
	SETOM Q1		;ONLY 1 COMMAND
	JRST TM8SI5		;GO DO IT
;HERE TO START A DATA OPERATION

TM8SI4:	LOAD T4,IRBDM,(P4)	;MODE
	CAIG T4,MAXMOD		;LEGAL?
	SKIPGE T4,MODTBL(T4)
	JRST ILLFNC		;NO, RETURN AN ERROR
	HRRZ T2,UDBSLV(P3)	;GET THE UNIT NUMBER
	TRO T2,DO.RC1(T4)	;SET 1 RECORD AND THE FORMAT
	MOVE T1,IRBSTS(P4)
	SKIPE T3,UDBERR(P3)	;IN ERROR RECOVERY?
	MOVE T3,UDBERC(P3)	;YES, GET RETRY COUNT
	CAIE T3,RTYOP		;INHIBIT ERROR RETRY IF LAST RETRY
	TXNE T1,IS.IER		;INHIBITING ERROR RETRY?
	TRO T2,DO.SER		;YES, TELL THE HARDWARE
	HRLI T2,(.DOFMT)	;WRITE TO FORMAT REGISTER
	CALL WTREG		;DO IT
	MOVE T2,IRBCNT(P4)	;GET WORDCOUNT
	TRNN T4,40000		;IS MODE HIGH DENSITY?
	JRST TM8SI6		;NO.
	TRNE T2,1		;YES. IS WORD COUNT EVEN?
	JRST BADSIO		;NO.
	LSH T2,-1		;YES. MULTIPLY BY 9/2

TM8SI6:	HLRZS T4		;FRAMES PER WORD
	IMULI T2,(T4)		;FRAME COUNT
	ANDI T2,DO.ERD		;ENSURE ONLY 16 BITS-WORTH
	HRLI T2,(.DOBC)		;WRITE BYTE COUNT REGISTER
	MOVEM Q1,SAVFNC(P3)	;SAVE FUNCTION WE'RE DOING
	ANDI Q1,77
	HRRZM P3,SAVUDB(P2)	;SAVE ADDRESS ON DATA TRANSFER OPERATION

TM8SI5:	MOVE T3,SAVFNC(P3)	;GET THE FUNCTION
	ANDI T3,77		;MASK OUT ALL BITS BUT FUNCTION CODE BITS
	CAIE T3,DF.SNS		;IS FUNCTION A SENSE AFTER ONLINE?
	HRRZM P3,KDBACT(P2)	;NO. SAVE WHAT SLAVE WE'RE DOING IT TO
	JRST CHSTRT
BADSIO:	BUG.(CHK,TM8ISI,PHYM78,HARD,<PHYM78 - Illegal function at start IO>,,<

Cause:	This BUGCHK can be caused by trying to write an odd number of words to
	a tape drive that is set for the high density mode.  If T2 is odd, this
	is probably the cause.

Action:	If this BUGCHK is reproducable, set it dumpable, and send in an SPR
	with the dump and how to reproduce the problem.
>)				;[7.1116]
	MOVX T1,IS.ERR!IS.NRT!IS.DVE ;MARK AN ERROR OCCURED
	IORM T1,IRBSTS(P4)	;IN IORB
	RET
	SUBTTL Interrupt Processing -- Attention Interrupt

;COMES HERE ON AN ATA INTERRUPT (INCLUDING SPACING OPS)
;C(P1)=CDB C(P2)=KDB
;WILL SET C(P4)= 0 IF NONE
;SETS C(P3)=UDB
;ALWAYS RET (NEVER SKP RET'S)
;IF ERR, IS.ERR AND EITHER <IS.DVE OR IS.DTE> WILL BE SET
;IF IS.ERR NOT SET, WE ARE FINISHED WITH THIS IORB

TM8ATN:	SAVEQ			;SAVE SOME REGS
	MOVE Q2,TM8ADR(P2)	;GET UNIT NUMBER
	MOVX T2,.DOICN		;READ NON-DATA INTERRUPT CODE
	CALL RDREG3
	LDB P3,[POINT 2,T1,27]	;DRIVE NUMBER
	ADDI P3,KDBUDB(P2)	;+ START OF DRIVES
	SKIPN P3,(P3)		;POINT P3 AT UDB
	JRST NOUDB		;IT'S A NEW ONE ON ME!
TM8AT1:	CALL ANLYZE		;FIGURE OUT WHAT HAPPENED
	  JRST ATDONE		;RETURN, WILL GET ANOTHER INTERRUPT
	MOVX T1,US.BOT+US.PSI
	CAMN Q1,REWFNC		;WAS FUNCTION A REWIND?
	IORM T1,UDBSTS(P3)	;YES, SET BOT, FOR POSSIBLE PSI
	CALL ATDONE		;CLEAR THE ATTENTION BIT NOW
	SKIPN TU7SNS(P3)	;DOING A SENSE?
	JRST TM8AT2		;NO
	SKIPE TU7ECD(P3)	;YES, IF NOT SENSE AFTER READ OF 1ST RECORD
	JUMPE Q3,RSKP		;GET TO TM8ERR IF SENSE AFTER RH20 ERROR
	MOVE Q1,TU7SNS(P3)	;SENSE AFTER 1ST RECORD. RESET Q1
	JRST TM8IN2		;KEEP ON GOING (ITS "REALLY" A DATA INTERRUPT)
TM8AT2:	TXNN Q1,TB.DAT		;NO. DATA OP?
	RET			;NO. WE'RE DONE
TM8ATX:	MOVX T1,IS.ERR!IS.DVE;DATA OP, ATTEN INTERRUPT - ERROR
	IORM T1,IRBSTS(P4)
	RET			;TELL UPPER LEVEL WE HAVE A PROBLEM

ATDONE:	MOVE Q1,TM8ADR(P2)	;RESTORE Q1 (ANLYZE WIPES IT)
	MOVEI T2,1		;POSITION A BIT
	LSH T2,(Q1)		;TO CLEAR THE RIGHT ATTENTION BIT
	HRLI T2,(.DOAS)
	CALLRET WTREG3		;CLEAR THE ATTEN AND RETURN TO PHYH2
;HERE WHEN WE GET AN ON-LINE INTERRUPT FROM AN UNKNOWN SLAVE

NOUDB:	LDB P3,[POINT 2,T1,27]	;GET UNIT
	ANDI T1,DO.ICD		;GET INTERRUPT CODE
	CAIE T1,ICDND1		;IS IT ONE FOR WHICH THE DRIVE ADDRESS ISNT VALID?
	CAIN T1,ICDND2
	SKIPA P3,KDBACT(P2)	;YES, HAVE TO GET THE DRIVE A DIFFERENT WAY
	JRST NOUDB1		;NO, THIS REALLY IS A NEW DRIVE
	JUMPN P3,TM8AT1		;GO IF WE WERE WORKING ON A DRIVE
	MOVE T1,KDBIUN(P2)	;NOT WORKING ON A DRIVE. FIND ONE
	SKIPE P3,(T1)		;FIND THE FIRST (LOWEST NUMBER) DRIVE ON THE TM
	JRST TM8AT1		;GO BLAME THE ERROR ON THAT
	AOBJN T1,.-2		;THIS DRIVE DOESN'T EXIST, TRY NEXT
	CALLRET ATDONE		;NO DRIVES AT ALL! FORGET IT
NOUDB1:	CALL ATDONE		;CLEAR THIS ATTENTION
	MOVEI T2,DR.ND0(P3)
	ROT T2,-6		;DO A SENSE ON THE DRIVE
	HRRI T2,DF.SNS
	CALL WTREG3		; SINCE WE CAN'T READ STATUS WITHOUT IT
	MOVEI T4,400000		;WAIT FOR THE ATTENTION AFTER THE SENSE FINISHES
NOUDB2:	MOVX T2,.DOAS
	CALL RDREG3
	TRNN T1,377		;ATTEN?
	SOJG T4,NOUDB2		;NO, WAIT A BIT
	MOVE Q1,P3		;YES, SET Q1=UNIT NO
	CALL INIUNI		;BUILD THE UDB
	AOS MTAJB0		;TELL WORLD TO LOOK FOR A NEW UNIT
	SETZ P4,		;SO PHYSIO WONT GET UPSET
	JRST ATDONE		;CLEAR THE ATTEN AND RETURN, DISMISSING INTERRUPT
	SUBTTL Interrupt Processing -- Command Done

;ENTER HERE FROM RH20 COMMAND DONE INTERRUPT
;C(P1)=CDB  C(P2)=KDB
TM8INT:	SAVEQ			;SAVE REGS
	SKIPN P3,SAVUDB(P2)	;ARE WE DOING SOMETHING?
	JRST TM8INU		;NO, WE OUGHTN'T BE HERE
	SKIPE Q1,TU7SNS(P3)	;DOING A SENSE?
	TXNN Q1,TB.XSN		;YES, AN EXTENDED SENSE?
	JRST TM8IN1		;NO
	HRRZ T1,CDBICP(P1)	;YES, PUT BACK THE REAL CCW
	MOVE T2,TM8SCW(P2)	; (WE OVERWROTE IT TO READ EXTENDED SENSE BYTES)
	MOVEM T2,(T1)
	SETZM TM8SCW(P2)	;THE WORLD IS NOW BACK TOGETHER
	MOVE Q2,TM8ADR(P2)	;POINT Q2 AT UNIT
	CALL ANLYZ1		;KEEP ON WITH THE ORIGINAL INTERRUPT
	  JRST [SETZ P4,	;ASYNC - FORGET IT
		 RET]
	JRST TM8IN2		;NORMAL RETURN - KEEP ON

;HERE ON A "NORMAL" DONE INTERRUPT (NO EXTENDED SENSE GOING)

TM8IN1:	MOVX T2,.DOICD		;GET THE INTERRUPT REASON
	MOVE Q2,TM8ADR(P2)	;WHAT UNIT TO GET IT FOR
	CALL RDREG3
	CALL ANLYZE		;FIGURE OUT WHAT HAPPENED
	  JRST [SETZ P4,	;ASYNC OR ANOTHER COMING
		 RET]
	TRNE Q3,(IS.ERR)	;IF THE TM78 SAW AN ERROR
	JRST TM8IN2		; DON'T WORRY ABOUT WHETHER THE RH20 SAW ONE TOO
	CALL CKERR		;CHECK FOR RH20 ERRORS
	  JRST TM8RDH		;CHAN ERROR. READ REGS
TM8IN2:	SKIPGE P5,TU7HDN(P3)	;GET DENSITY
	LOAD P5,IRBDN,(P4)	;HARDWARE DOESN'T KNOW, GET IT FROM IORB
	CAIN P5,.SJD16		;1600 BPI (PE MODE)?
	SKIPA P5,P3		;YES, SET TO ACCUMULATE PE FRAMES
	MOVEI P5,1(P3)		;NO, SET TO ACCUMULATE GCR FRAMES
	TXNN Q1,TB.RD		;READ?
	JRST TM8IN4		;NO
	SKIPN TU7SNS(P3)	;YES, ALREADY DONE A SENSE?
	TRNE Q3,(IS.ERR)	;NO, ERROR?
	TDZA T2,T2		;NO
	MOVE T2,UDBPS2(P3)	;GOOD READ, NO SENSE JUST DONE.  GET POSITION
	SKIPN UDBPS1(P3)	;AT FILE 0, RECORD 1?
	SOJE T2,[SETZ P4,	;YES. DO A SENSE TO DETERMINE DENSITY
		    JRST SENSE]	;AND TELL PHYSIO ANOTHER INTERRUPT IS COMING
	MOVX T2,.DOBC		;NOT AFTER 1ST RECORD. READ BYTE COUNT
	CALL RDREG3
	TRNE Q3,(IS.ERR)	;IF RECORD IS NOT IN ERROR,
	JRST TM8IN5		;ERROR. DO NOT ACCUMULATE
	ADDM T1,UDBRED(P3)	; ACCUMULATE FRAMES READ
	ADDM T1,UDBRPE(P5)	;ACCUMULATE FRAMES READ IN PE/GCR
	AOS UDBRCT(P3)		;[7142] COUNT A  RECORD READ
TM8IN5:	LOAD T4,IRBDM,(P4)
	HLRZ T3,MODTBL(T4)	;COMPUTE WORDS READ
	SOJE T3,TM8IN3		;SAVE TIME IF BYTES=FRAMES
	CAIN T4,IRMHID		;IS MODE HIGH DENSITY?
	LSH T1,1		;YES. THEN MULTIPLY BY 2/9
	IDIVI T1,1(T3)
	JUMPE T2,TM8IN3		;GO IF AN INTEGRAL NUMBER OF BYTES
	ADDI T1,1
TM8IN3:	MOVEM T1,IRBCNT(P4)	;SAVE WORDCOUNT
TM8IN4:	TXNN Q1,TB.WRT		;WRITE?
	JRST DTDONE		;NO
	LOAD T4,IRBDM,(P4)	;YES, ACCUMULATE BYTES WRITTEN
	HLRZ T3,MODTBL(T4)
	IMUL T3,IRBCNT(P4)
	CAIN T4,IRMHID		;IS MODE HIGH DENSITY?
	LSH T3,-1		;YES. THEN DIVIDE BY 2
	ADDM T3,UDBWRT(P3)
	ADDM T3,UDBWPE(P5)	;ACCUMULATE BYTES WRITTEN IN PE OR GCR
	AOS UDBWCT(P3)		;[7142] COUNT A RECORD WRITTEN
DTDONE:	SETZM TU7ECD(P3)	;CLEAN UP ANY TEMPS
	SETZM TU7SNS(P3)
	SETZM SAVUDB(P2)
	TRNN Q3,(IS.ERR)	;ERROR?
	RETSKP			;NO, TELL PHYH2/PHYSIO ALL IS GOOD
	MOVEM Q3,TU7ECD(P3)	;ERROR - MAKE SURE TM8ERR KNOWS ABOUT IT
	RET			;AND SIGNIFY BY NON-SKIP

;HERE ON DONE INTERRUPT, NO UDB IS CURRENT

TM8INU:	HRRZ T1,CDBADR(P1)	;[7.1116] Load channel number
	HRRZ T2,TM8ADR(P2)	;[7.1116] Load kontroller number
	BUG.(CHK,TM8NUD,PHYM78,HARD,<PHYM78 - Channel done interrupt but no unit active>,<<T1,CHAN>,<T2,CONT>>,<

Cause:	A command done interrupt was issued by an RH20 channel but there was no
	unit active on that channel.  If an OVRDTA had previously occured, and
	the device finally responds, this BUGINF happens.  This usually
	indicates a hardware failure.

Action:	Field Service should check the devices on the channel listed in the
	additional data; any channel/controller/unit listed in OVRDTA BUGCHKs
	should be suspected.

Data:	CHAN - Channel number
	CONT - Controller number
>,,<DB%NND>)			;[7.1210][7.1116]
	SETZ P4,
	RET			;SIGNIFY ERROR
	SUBTTL Interrupt Processing -- Analyze What Happened

;SUBROUTINE TO FIGURE OUT WHAT HAPPENED 
;ENTER T1=INTERRUPT CODE REGISTER
;EXIT Q1=FUNCTION, Q3=INTERRUPT TABLE CONTENTS
;NON-SKIP IF ANOTHER INTERRUPT IS COMING, OR IT REQUIRES NO ACTION
;SKIP (WITH P4=IORB) IF IT IS "REAL"

ANLYZE:	MOVE Q1,SAVFNC(P3)	;FUNCTION WE DID
	SETZ P4,		;IN CASE WE NON-SKIP RETURN
	SKIPN TU7SNS(P3)	;DOING A SENSE?
	JRST ANLYZ4		;NO
	TRNE T1,76		;IS IT A DONE?
	RET			;NO, IGNORE IT
	MOVE Q1,TU7SNS(P3)	;YES, GET UPDATED BITS
	PUSH P,T1		;SAVE INTERRUPT CODE
	TXNN Q1,TB.RRG		;SENSE SO WE CAN READ REGS 7-10?
	JRST ANLYZ2		;NO
	CALL RDREG2		;YES, READ THEM NOW
	POP P,T1		;RESORE INTERRUPT CODE
	MOVE T2,TU7ECD(P3)	;EXTRA INTERRUPT FLAGS
	TLNN T2,-1		;RH20 ERROR?
	JUMPN T2,[MOVEI P4,1	;YES, SET LH(TU7ECD) NON-0
		    HRLM P4,TU7ECD(P3) ;SO TM8ERR WILL KNOW WHERE WE ARE
		    CALLRET SETIRB] ;DISMISS INTERRUPT, COME BACK AT TM8ERR
ANLYZ1:	MOVE Q3,TU7ESD(P3)	;GET UPDATED ERROR BITS
	SKIPGE CDBXFR(P1)	;DOING A DATA XFER?
	JRST ANLYZ6		;NO. CANT READ THE ERROR LOG NOW
	TXNE Q3,IC.XSN		;NEED AN EXTENDED SENSE?
	TXOE Q1,TB.XSN		;YES, HAVE WE JUST DONE IT?
	JRST ANLYZ6		;DONT NEED IT OR JUST DID IT - KEEP ON
	JRST ANLY12		;GO DO AN EXTENDED SENSE

;HERE FOR A SENSE WHEN DRIVE COMES ON-LINE OR AFTER READING 1ST RECORD

ANLYZ2:	MOVX T2,.DOSR		;READ THE STATUS REGISTER
	CALL RDREG3
	JUMPL Q1,ANLYZ3		;GO IF A DATA OPERATION
	MOVX T2,US.WLK!US.BOT	;ON-LINE SENSE - CLEAR/SET WRITE LOCK, BOT
	ANDCAM T2,UDBSTS(P3)
	TRNN T1,DI.FPT
	TXZ T2,US.WLK		;NOT WRITE-LOCKED
	TRNN T1,DI.BOT
	TXZ T2,US.BOT		;NOT AT BOT
	IORM T2,UDBSTS(P3)	;SET STATUS
	POP P,(P)		;MAKE THE STACK RIGHT
	SETZM TU7SNS(P3)	;DONE WITH THE SENSE
	SETZM SAVFNC(P3)	;INDICATE WE AREN'T USING DRIVE
	TXNN T2,US.BOT		;AT BOT?
	RET			;NO
	SETZM UDBPS1(P3)	;YES, CLEAR COUNTERS
	SETZM UDBPS2(P3)	; OF RECORD, FILE
	SETOM TU7HDN(P3)	;INDICATE UNKNOWN DENSITY
	RET			;NON-SKIP RETURN (TOSS THE INTERRUPT)
;HERE AFTER READING 1ST RECORD. GET DENSITY FROM THE HARDWARE

ANLYZ3:	CALL SETIRB		;POINT AT IORB
	MOVEI T2,.SJD16		;ASSUME 1600
	TRNN T1,DI.PE
	MOVEI T2,.SJD62		;NOPE, ITS 6250
	MOVEM T2,TU7HDN(P3)	;SAVE DENSITY IN UDB
	POP P,T1		;MAKE STACK RIGHT/RESTORE INTERRUPT CODE
	TXZ Q1,TB.DAT		;SET Q1 SO WE WON'T INCREMENT UDBPS2
				;FALL INTO ANLYZ4

;HERE ON REGULAR INTERRUPT OR SENSE AFTER READING 1ST RECORD

ANLYZ4:	MOVEM T1,SAVLSI(P2)	;SAVE LAST INTERRUPT CODE
	ANDI T1,DO.ICD		;6 BITS OF INTERRUPT CODE
	CAILE T1,MAXICD		;LEGAL?
	MOVEI T1,0		;NO
	SKIPN Q3,TU7RRO(P3)	;IN RETRY OPPOSITE?
	JRST ANLYZ5		;NO NEED TO DO ANYTHING NOW
	SETZM TU7RRO(P3)	;NOW NO LONGER IN OPPOSITE MODE
	HRRZ P4,UDBTWQ(P3)	;GET IORB ADDRESS
	JUMPE P4,ANLYZ5		;FORGET IT IF NO IORB (!)
	MOVE T2,IRBCNT(P4)	;GET WORDCOUNT OF RECORD
	SKIPN T3,UDBERR(P3)	;GET FUNCTION
	LOAD T3,ISFCN,(P4)
	SKIPL FNCTBL(T3)	;IS IT A DATA OPERATION?
	JRST ANLYZ5		;NO (!)
	PUSH P,T1		;SAVE INTERRUPT CODE
	CALL REVCCW		;YES, RE-REVERSE THE IO LIST
	HRRZ T1,Q3		;MASK OFF JUNK
	HLLM Q3,(T1)		;RESTORE LH OR CHANGED IOWD TO ITS ORIGINAL VALUE
	POP P,T1
ANLYZ5:	SKIPL Q3,ICDTBL(T1)	;GET ERROR BITS ASSOCIATED WITH THIS INTERRUPT
	JRST ANLYZ6		;NOT AN ERROR
	SKIPE UDBERR(P3)	;ERROR. FIRST TIME?
	TXNN Q3,IC.PAD		;NOT 1ST. DON'T SENSE IF TM78 WILL REPOSITON
	JRST TM8RDR		;ERROR - READ REGISTERS
ANLYZ6:	TXNN Q3,IC.RRG		;NON-ERROR INTERRUPT?
	SKIPN UDBERR(P3)	;YES, IN ERROR RECOVERY?
	CAIA			;ERROR OR NOT IN ERROR RECOVERY
	CALL RDREG4		;GOOD READ IN ERROR RECIVERY - READ FINAL REGS
	TXNN Q3,IC.ASY		;ASYNC?
	AOS (P)			;NO, SET FOR SKIP-RETURN
	TXNN Q3,IC.DSP		;DISPATCH ADDRESS?
	IFSKP.
	  HRRZ T4,Q3		;YES. SET UP LOCAL INDEX. (INTRRO NEEDS THIS).
	  JRST (T4)		;GO TO SUBROUTINE.
	ENDIF.
	SKIPGE UDBSTS(P3)	;OFF-LINE?
	JRST [CAME Q1,UNLFNC	;YES, IS IT AN UNLOAD?
		 RET		;NO, FORGET THE INTERRUPT
		 JRST .+1]	;YES, REPORT COMPLETION TO PHYSIO
				;FALL INTO HERE FROM PREVIOUS PAGE
ANLYZ7:	CAMN P3,KDBACT(P2)	;NO. HERE FOR THE "RIGHT" UNIT?
	SETZM KDBACT(P2)	;YES, CLEAR THE SAVED UDB
	MOVX T2,US.BOT		;CLEAR BOT, PICK UP DRIVE STATUS
	TXNE Q3,(IS.BOT)	;DID WE HIT BOT?
	IORB T2,UDBSTS(P3)	;YES, TELL THE WORLD
	TXNN Q3,(IS.BOT)	;IF NOT AT BOT
	ANDCAB T2,UDBSTS(P3)	;TELL THE WORLD WE AREN'T
	TXNE T2,US.REW		;WAS IT REWINDING?
	JRST ANLY10		;YES, TELL WORLD WE'RE DONE
	JUMPE Q1,ANLY11		;NO, GO AWAY IF WE DIDN'T TELL IT TO DO ANYTHING
	HRRZ T1,UDBTWQ(P3)	;GET TOP ENTRY IN TRANSFER QUEUE
	ADD T1,UDBPWQ(P3)	; + TOP ENTRY IN POSITION QUEUE
	TRNN T1,-1		;ANYTHING THERE?
	JRST ANLY11		;NO, FORGET THIS INTERRUPT
	TXNN Q3,IC.BST		;SET A BIT IN IORB?
	TDZA T1,T1		;NO
	HRLZ T1,Q3		;YES, GET THE BIT(S) TO SET
	CALL SETIRB		;POINT P4 AT IORB
	MOVX T2,IS.DVE!IS.DTE;CLEAR ERROR BITS
	ANDCAM T2,IRBSTS(P4)
	IORM T1,IRBSTS(P4)	;AND SET BIT(S) FROM THIS INTERRUPT
	TXNN Q1,TB.SPC		;SPACING OPERATION?
	JRST ANLYZ8		;NO, COUNT 1 RECORD
	SKIPE UDBERR(P3)	;IN ERROR RECOVERY?
	JRST [MOVEI T1,1	;YES, 1 RECORD
		 JRST ANLYZ9]
	HLLZ T2,UDBSLV(P3)	;NO, READ CURRENT RECORD COUNT
	CALL RDREG3
	LSH T1,-NDCSHF		;RIGHT-JUSTIFY IT
	EXCH T1,IRBCNT(P4)	;TELL WORLD HOW MANY WE DIDNT DO
	SUB T1,IRBCNT(P4)	;COMPUTE AMOUNT WE DID DO
	JRST ANLYZ9		;GO UPDATE POSITON
ANLYZ8:	TXNN Q3,IC.SNM!IC.PAD;ANY MOTION?
	TXNN Q1,TB.DAT		;YES, DATA OP?
	TDZA T1,T1		;NO MOTION, DONT UPDATE POSITION
	MOVEI T1,1		;WE MOVED 1 RECORD
	TXNE Q1,TB.WTM		;IS IT A TAPE MARK OPERATION?
	MOVEI T1,1		;YES. SET TO INCREMENT COUNT SO
				;THAT LABELLED TAPES WORK.
	SKIPE TU7RRO(P3)	;IN RETRY OPPOSITE?
	TXC Q1,TB.REV		;YES, GET ORIGINAL DIRECTION
ANLYZ9:	TXNE Q1,TB.REV		;REVERSE?
	MOVNS T1		;YES
	ADDM T1,UDBPS2(P3)	;UPDATE RECORD POSITION
	SETZM SAVFNC(P3)	;INDICATE WE AREN'T DOING ANYTHING
	TRNN Q3,(IS.TPM)	;TAPE MARK?
	RET			;NO, RETURN
	SETZM UDBPS2(P3)	;YES, AT 0TH RECORD
	TXNE Q1,TB.REV		;UPDATE FILE COUNTER
	SOSA UDBPS1(P3)
	AOS UDBPS1(P3)
	RET			;AND RETURN

;HERE ON AN INTERRUPT WHEN DRIVE IS MARKED AS REWINDING

ANLY10:	CALL PHYRWD		;TELL REST OF WORLD WE FINISHED THE REWIND
	SETOM TU7HDN(P3)	;INDICATE UNKNOWN DENSITY
ANLY11:	SOS (P)			;NON-SKIP RETURN (FORGET IT)
	SETZ P4,		;PHYRWD WIPES OUT P4
	RET			;GO AWAY
;HERE TO DO AN EXTENDED SENSE

ANLY12:	MOVEM Q1,TU7SNS(P3)	;SAVE UPDATED BITS
	MOVEI T2,TM8XCW(P2)	;SORRY ABOUT THAT, BUT I CAN'T CONVINCE
	MAP T2,(T2)		;PHYH2 TO DO THE RIGHT THING
	TLZ T2,777760		;MAKE ICWA=JUMP KDB
	TLO T2,200000
	HRRZ T1,CDBICP(P1)	;ICWA
	EXCH T2,(T1)		;STORE JUMP, PICK UP WHAT WAS THERE
	MOVEM T2,TM8SCW(P2)	;SAVE REAL ICWA
	MOVEI T2,TM8XSN(P2)	;POINT AT EXTENDED SENSE BLOCK
	MAP T2,(T2)		;GET THE REAL LOC
	TLZ T2,777760
	TLO T2,(6B2!17B13)	;MUNGE UP AN IOWD TO READ EXTENDED SENSE
	MOVEM T2,TM8XCW(P2)	;SAVE IN KDB
	MOVX T2,.DOFMT		;TELL THE HDWRE WHAT DRIVE
	HRR T2,UDBSLV(P3)
	TRO T2,DO.RC1		;ONLY 1 RECORD
	MOVEI Q1,DF.XSN!ERSTRY	;FUNCTION IS EXTENDED SENSE, CCW ALREADY SET
	SOS (P)			;GIVE NON-SKIP (ANOTHER INTERRUPT COMING)
	PUSH P,CDBICR(P1)	;SAVE INITIAL CONTROL REGISTER
	CALL TM8SI5		;CRANK UP THE EXTENDED SENSE
	  JFCL
	POP P,CDBICR(P1)	;RESTORE WHAT WE WERE DOING BEFORE THE SENSE
	RETSKP			;AND RETURN
	SUBTTL Interrupt Processing -- Action Routines

;HERE ON A REWIND STARTED INTERRUPT

INTRWP:	HRRZ T1,UDBPWQ(P3)	;GET PWQ ENTRY.
	CAIN T1,0		;IS THERE AN IORB ON THE PWQ?
	JRST INTRW1		;NO. THEN THIS IS A SPURIOUS INTERRUPT.
	MOVX T1,US.REW		;TELL THE WORLD
	IORM T1,UDBSTS(P3)	;THAT THE DRIVE IS REWINDING
	SETZB Q1,SAVFNC(P3)	;INDICATE WE AREN'T DOING ANYTHING TO DRIVE
	CALLRET SETIRB		;SET UP P4 AND RETURN

				;HERE IF THERE IS A REW INTERRUPT
				;BUT THERE IS NO IORB ON THE PWQ.
INTRW1:	SOS (P)			;ADJUST STACK POINTER.
	SETZ P4,		;SET TO DISMISS INTERRUPT
	MOVE T2,CDBADR(P1)	;GET CHANNEL NUMBER
	MOVE T3,TM8ADR(P2)	;GET CONTROLLER NUMBER
	HRRZ T4,UDBSLV(P3)	;[7.1116] Get unit number
	BUG.(INF,TM8REW,PHYM78,HARD,<PHYM78 - Spurious rewind started interrupt>,<<T2,CHAN>,<T3,CONT>,<T4,UNIT>>,<

Cause:	The TM78 gave a spurious rewind started interrupt.

Action:	The monitor has dismissed the interrupt.  There may be TM78 or other
	hardware problems.  If this BUGCHK is persistent, notify Field Service
	and have them check out the TM78 and drive.

Data:	CHAN - Channel number
	CONT - Controller number
	UNIT - Unit number
>,,<DB%NND>)			;[7.1210][7.1116] Let the world know
	RET			;GO DISMISS INTERRUPT


;HERE WHEN A DRIVE COMES ON-LINE

INTONL:	CALL PHYONL		;TELL THE WORLD THE DRIVE IS BACK
	CALL ATDONE		;CLEAR THE ATTENTION BIT
	MOVEI Q1,DF.SNS		;START A SENSE TO SEE IF WRITE-LOCKED
	SETZ P4,		;TELL PHYSIO TO FORGET THE INTERRUPT
	SOS (P)
	CALLRET SENSE		;START THE SENSE AND RETURN

;HERE WHEN A DRIVE IS (OR GOES) OFF-LINE

INTOFL:	CALL PHYOFL		;TELL THE WORLD
	HRRI Q3,(IS.ERR!IS.DVE)	;LIGHT SOME ERRORS
	JRST ANLYZ7		;AND RETURN
;HERE ON A TU FAULT/TM FAULT INTERRUPT

CLRTM:	CALL TM8ZAP		;RESET THE TM78
	MOVE T1,SAVLSI(P2)	;GET INTERRUPT CODE
	MOVE T2,CDBADR(P1)	;GET CHANNEL NUMBER
	MOVE T3,TM8ADR(P2)	;GET CONTROLLER NUMBER
	BUG.(INF,TM8AEI,PHYM78,HARD,<PHYM78 - Asynchronous error interrupt (TM78 hardware problem)>,<<T1,ICODE>,<T2,CHAN>,<T3,CONT>>,<

Cause:	The TM78 gave an asynchronous error interrupt.  This happens when the
	TM78 thinks it has detected a hardware fault in the TM78 or one of its
	drives.

Action:	The TM78 has been cleared and restarted.  The TM78 or one of its drives
	may be getting flakey.  Field Service must be called to check the TM78
	out.

Data:	ICODE - The interrupt code associated with this interrupt from
		MASSBUS register 13 of the TM78
	CHAN  - Channel number of the TM78
	CONT  - Controller number of the TM78
>,,<DB%NND>)			;[7.1210][7.1116] Let the world know
	SETZ P4,		;TELL PHYSIO THIS ISNT THE LAST INTERRUPT
	SKIPN P3,KDBACT(P2)	;WERE WE WORKING ON A DRIVE?
	JRST CLRTM1		;NO, NOTHING TO RESTART
	MOVE Q1,UDBSTS(P3)	;YES, GET STATUS
	TXNN Q1,US.ACT		;IS IT GOING?
	JRST CLRTM1		;NO, DON'T TRY TO RESTART
	CALL SETIRB		;YES, SET UP P4 POINTING AT IORB
	TXNN Q1,US.POS		;DOING A DATA OPERATION?
	JRST TM8SIO		;YES, GO RETRY THE OPERATION
	MOVE Q3,NRTERV		;POSITION - CALL IT A HARD DEVICE ERROR
	RETSKP

;HERE IF NOTHING IS HAPPENING

CLRTM1:	AOS T1,TM8ACT(P2)	;BUMP ASYNC INTERRUPT COUNT
	CAIG T1,TM8AMX		;TOO MANY?
	RET			;NO
	CALL SETHLD		;YES, SET HOLD (STOP MICROCODE) TO PREVENT
	 JFCL			; TM78 FROM CLOGGING ERROR FILE
	SETOM TM8ACT(P2)	;INDICATE THE TM IS STOPPED
	RET			;AND RETURN, IGNORING INTERRUPT
;HERE ON A REREAD OPPOSITE INTERRUPT

INTRRO:	CALL SETIRB		;POINT P4 AT IORB
	MOVX T2,.DOBC		;READ BYTE COUNT THE TM78 THINKS IS THE LENGTH
	CALL RDREG3		; (MIGHT HAVE CHANGED SINCE LAST RETRY)
	JUMPN T1,INTRR2		;DID THE TM78 RETURN A BYTE COUNT OF 0?
INTRR1:	MOVE Q3,NRTERD		;YES, HERE IS WHERE WE GIVE UP
	SOS  (P)		;ADJUST STACT POINTER FOR SKIP RETURN
	JRST TM8RDR		;READ REGISTERS AND CALL IT A DAY
INTRR2:	LOAD T3,IRBDM,(P4)	;NO, A REAL BYTE COUNT
	HLRZ T3,MODTBL(T3)	;CONVERT TO WORDS
	IDIVI T1,(T3)
	JUMPN T2,INTRR1		;CANT RETRY IF NON-INTEGRAL NO OF WORDS
	MOVEM T1,IRBCNT(P4)	;SAVE CORRECTED BYTE COUNT FOR RETRY
	MOVE T2,T1		;WORDCOUNT WHERE REVCCW WANTS IT
	CALL REVCCW		;SET UP TO READ REVERSE
	MOVEM T1,TU7RRO(P3)	;SAVE ORIGINAL IOWD WHICH REVCCW CHANGED
INTRR3:	HRRI Q3,(IS.ERR!IS.DTE)	;TELL ANLYZE THAT THERE IS AN ERROR
	JRST ANLYZ7		;AND CARRY ON
	SUBTTL Error Recovery

;ERROR RETRY ENTRY POINT
;P1=CDB  P2=KDB  P3=UDB  RETURNS Q1=ERROR BLOCK ADDRESS
;NON-SKIP RETURN - ERROR RETRY IN PROGRESS
;SKIP - WE'RE DONE WITH IT (FOR BETTER OR WORSE)

TM8ERR:	SKIPGE UDBSTS(P3)	;DRIVE NOW OFF-LINE?
	RETSKP			;YES, FORGET ERROR RECOVERY
	MOVE T1,TU7ECD(P3)	;EXTRA ERROR FLAGS
	TLNN T1,-1		;AFTER RH20 ERROR?
	JUMPN T1,R		;YES, RETURN (A SENSE IS CURRENTLY IN PROGRESS)
	SAVEQ
	CALL SETIRB		;GET OUR IORB
	HRRZ Q1,UDBERP(P3)	;GET ERROR BLOCK IF PRESENT
	HLLZ T1,IRBSTS(P4)	;GET IORB STATUS
	LOAD T2,ISFCN,(P4)	;GET ORIGINAL FUNCT FROM IORB
	MOVE T4,FNCTBL(T2)	;GET TABLE ENTRY
	TXNE T4,TB.DAT		;NON-DATA OPERATIONS ARE RECOVERED BY TM78
	TXNE T1,IS.NRT!IS.IER	;FATAL OR INHIBIT ERR RECOVERY?
	JRST TM8NRB		;GIVE-UP RETURN
	SKIPN T1,TU7ECD(P3)	;NO, RETRY THE ERROR. GET FAILURE BITS
	JRST TM8RCV		;RECOVERED THE ERROR!
	AOS T3,UDBERC(P3)	;COUNT A FAILED RETRY
	CAILE T3,RTYOP		;TRIED ENOUGH?
	JRST TM8NRC		;YES, NON-RECOVERABLE
	SOJN T3,TM8ER1		;GO IF NOT 1ST RETRY
	PUSH P,T1		;1ST - SET ERROR BLOCK
	CALL BEGLOD
	POP P,T1
	LOAD T2,ISFCN,(P4)	;GET ORIGINAL FUNCT FROM IORB
TM8ER1:	SKIPE TU7RRO(P3)	;REREADING IN OPPOSITE DIRECTION?
	TRC T2,IRFRED!IRFRDR	;YES, REVERSE SENSE OF ORIGINAL READ
	TXON T1,IC.SNM!IC.PAD	;NEED A REPOSITON?
	MOVEI T2,IRFBSB		;YES, BACK UP 1 BLOCK
	MOVEM T2,UDBERR(P3)	;SAVE ERROR FNCN
	MOVEM T1,TU7ECD(P3)
	CALL TM8SIO		;GO RETRY
	  JRST TM8NRC
	RET			;RETRY STARTED, WAIT FOR NEXT INTERRUPT
;HERE ON A RECOVERED ERROR

TM8RCV:	MOVX T1,IS.ERR		;CLEAR THE ERROR BIT FROM THE IORB
	ANDCAM T1,IRBSTS(P4)
	TXNE T4,TB.WRT
	AOSA UDBSWE(P3)		;COUNT A SOFT ERROR
	AOS UDBSRE(P3)
	JRST TM8NRD		;SET END OF ERROR BLOCK AND RETURN

;HERE WHEN THE RETRY FAILED

TM8NRB:	SKIPN UDBERC(P3)	;HAVE WE DONE ANY RETRIES?
	CALL BEGLOD		;NO, SET UP 1ST PART OF ERROR BLOCK

TM8NRC:	TXNE T4,TB.WRT
	AOSA UDBHWE(P3)		;COUNT A HARD ERROR
	AOS UDBHRE(P3)
TM8NRD:	CALL ENDLOD		;SET UP END OF ERROR BLOCK
	SETZM TU7RRO(P3)	;CLEAN UP FLAGS
	RETSKP			;AND TELL PHYSIO WE'RE DONE
;HERE AFTER AN RH20-DETECTED ERROR, THE TM78 THINKS EVERYTHING IS FINE

TM8RDH:	HRRZM P,TU7ECD(P3)	;SET LH(TU7ECD) NON-0
	MOVX T1,IS.ERR		;INDICATE AN ERROR
	IORM T1,IRBSTS(P4)
				;FALL INTO TM8RDR

;ROUTINE TO READ ALL TM78 REGISTERS INTO TM8REG IN THE KDB

TM8RDR:	CALL RDREGS		;READ DRIVE REGISTERS (EXCEPT 7-10)
	TXO Q1,TB.RRG		;INDICATE WHY WE'RE DOING THE SENSE
	MOVEM Q3,TU7ESD(P3)	;SAVE ERROR BITS FOR WHEN SENSE FINISHES
	SOS (P)			;SENSE GIVES A SKIP-RETURN
	CALLRET SENSE		;DO A SENSE SO WE CAN READ REGS 7 - 10

;ROUTINE TO READ REGISTERS ON ERROR

RDREGS:	CALL ERRCNI		;GET CONI AND DATAI
	MOVEM T1,TM8CNI(P2)	;SAVE IN KDB
	MOVEM T2,TM8CS1(P2)
	MOVEM T3,TM8DBF(P2)
	MOVEI T4,TM8REG(P2)	;WHERE TO READ
	HRLI T4,-22		;READ ALL REGISTERS
	SETZ T2,		; STARTING AT 0
RDREG1:	CALL RDREG3
	MOVEM T1,(T4)		;STORE DATA IN UDB
	ADD T2,[010000,,0]	;SET FOR NEXT REGISTER
	AOBJN T4,RDREG1
	RET

;HERE AFTER SENSE COMPLETES WHICH WAS DONE TO READ REGS 7-10

RDREG2:	MOVSI T1,TM8XSN(P2)	;ZERO THE EXTENDED SENSE AREA
	HRRI T1,TM8XSN+1(P2)	; IN CASE WE DON'T DO AN EXTENDED SENSE
	SETZM TM8XSN(P2)	; OR THERE IS AN ERROR IN THAT TRANSFER
	BLT T1,TM8XSN+16(P2)
	MOVEI T4,TM8REG+7(P2)
	HRLI T4,-3		;AOBJN WORD FOR REGS TO READ
	MOVSI T2,070000		;STARTING REGISTER TO READ
	CALLRET RDREG1		;GO READ 3 REGISTERS

;HERE TO READ REGISTERS AFTER A SUCCESSFUL RETRY

RDREG4:	PUSH P,TM8REG+7(P2)	;SINCE WE CAN'T READ 7-10 WITHOUT SOME HAIR,
	PUSH P,TM8REG+10(P2)	; AND THEY WON'T BE CHANGING
	PUSH P,TM8REG+11(P2)	; SAVE THEM
	CALL RDREGS		;READ ALL 22 REGISTERS
	POP P,TM8REG+11(P2)	;RESTORE THE SAVED ONES
	POP P,TM8REG+10(P2)
	POP P,TM8REG+7(P2)
	RET			; AND RETURN
;SUBROUTINE TO LOAD THE ERROR BLOCK AT START OF ERROR
;ENTER WITH Q1 POINTING AT ERROR BLOCK

BEGLOD:	JUMPE Q1,R		;IF NO ERROR BLOCK, PUNT
	PUSH P,T4		;SAVE, BECAUSE SEBCPY USES T4.
	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
	MOVSI T1,TM8REG(P2)	;WHERE TO GET REGS
	HRRI T1,SEBDAT+MB%REG(Q1) ;WHERE TO STORE THEM
	BLT T1,SEBDAT+MB%REG+TM8ELN-1(Q1) ;STUFF INTO ERROR BLOCK
	POP P,T4		;RESTORE T4
	RET

;SUBROUTINE TO LOAD ERROR BLOCK AT END OF ERROR

ENDLOD:	JUMPE Q1,R		;IF NO ERROR BLOCK, CANT SAVE DATA
	MOVE T3,[-22,,TM8REG]	;WHERE TO START
	ADDI T3,(P2)		;RELOCATE INTO THIS KDB
	MOVEI T2,SEBDAT+MB%REG(Q1) ;REGISTER DATA GOES HERE
ENDLO1:	MOVE T1,(T3)		;GET REGISTER
	HRLM T1,(T2)		;PUT IT
	ADDI T2,1
	AOBJN T3,ENDLO1		;DONE?
	MOVE T1,TM8CNI(P2)	;GET CONI
	MOVEM T1,SEBDAT+MB%CIF(Q1) ;SAVE
	MOVE T1,TM8CS1(P2)	;GET TCR
	MOVEM T1,SEBDAT+MB%D1F(Q1) ;SAVE
	MOVE T1,TM8DBF(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,TM8CNI(P2) ;CONI INITIAL
	SEBPTR MB%D1I,SBTWD,TM8CS1(P2) ;TCR
	SEBPTR MB%D2I,SBTWD,TM8DBF(P2) ;BAR/DBF

NITAB==.-ITAB
	SUBTTL TM78 Initializing Routine

;THIS ROUTINE IS CALLED ONCE PER TM78 DRIVE ON THE SYSTEM
;SET UP UDB'S - 1 PER DRIVE ON THE TM78
;INPUT  C(P1)=CDB  C(Q2)=UNIT NR; OUTPUT P2,P3

TM8INI:	SAVEQ			;SAVE REGISTERS
	CALL TM8ZAP		;RESET CONTROLLER
	JUMPL P5,UNINA		;[7457] Jump if doing all units on Kontroller
	MOVE P2,CDBIUN(P1)	;[7457] Get AOB pointer to KDB list in the CDB
	ADD P2,Q2		;[7457] Point to the correct unit (TM78 number)
	SKIPE P2,(P2)		;[7457] Get KDB out of CDBUDB or skip if none
	JRST INIL0		;[7457] There is a KDB, use it for this unit
UNINA:	MOVX T1,LK.TM8		;[7457] Here if we need a KDB, load KDB length
	CALL PHYALC		;RESERVE SPACE
	RET			;RETURN IF NO SPACE FOUND
	MOVEM T1,P2		;SAVE ADDRESS IN PROPER AC
	MOVE P3,T1		;COPY KDB
	MOVEI T1,.BTKDB		;MARK AS KDB
	DPB T1,USYBKT		; ...
	MOVX T1,.UTTM7		;YES - SET UP UNIT TYPE IN KDB
	STOR T1,USTYP,(P2)	;...
UNINI:	MOVSI Q1,-TM8SLC	;SET UP AOBJN INDEX LH
	HRRI Q1,KDBUDB(P2)	;MAKE RH POINT TO UDB ENTRIES IN KDB
	MOVEM Q1,KDBIUN(P2)	;INITIAL POINTER
	MOVEM Q1,KDBCUN(P2)	;CURRENT POINTER
	HRRZM Q2,TM8ADR(P2)	;SAVE KDB ADDRESS
	MOVEI T1,TM8DSP		;INSERT DISPATCH VECTOR
	MOVEM T1,KDBDSP(P2)	; ...
	CALL SETHLD		;SET HOLD IN TM78
	 JRST UNINF		;WOULDN'T SET
	MOVEI Q1,TM8REV(P2)	;POINT AT KDB
	HRLI Q1,441100		;MAKE A BYTE POINTER
	MOVE Q3,[.DOIA!3776]	;POINT AT LOC FOR 1ST ROM REV LEVEL
UNINE:	MOVE T2,Q3
	CALL WTREG3		;LOC WE WANT TO READ
	MOVSI T2,(.DOTMS)
	CALL RDREG3		;READ THE LOCATION
	ANDI T1,377		;ONLY 8 BITS ARE OF INTEREST
	IDPB T1,Q1		;SAVE IN ..U?0 UDB
	ADDI Q3,4000		;STEP TO NEXT REV LEVEL LOC
	TRNN Q3,40000
	JRST UNINE		;GO READ IT
				;START REVISION LEVEL CHECK.
	SETZM T4		;CLEAR T4 FOR USE AS A FLAG
	MOVEI Q1,TM8REV-1(P2)	;SET UP BYTE POINTER FOR ACTUAL LEVELS
	HRLI Q1,001100
	MOVEI Q3,MINREV-1	;SET UP BYTE POINTER FOR MINIMUM LEVELS NEEDED.
	HRLI Q3,001100
	MOVEI T3,10		;SET UP COUNTER TO CHECK 8. LEVELS.
REVCHK:	ILDB T1,Q1		;GET THE REVSION LEVEL NUMBERS.
	ILDB T2,Q3
	CAMGE T1,T2		;DO THE CHECK.
	AOS T4			;LEVEL DOES NOT MEET MINIMUM. SET FLAG.
	SOJG T3,REVCHK		;CHECK ALL LEVELS.
	JUMPE T4,REVCH1		;LEVELS MEET MINIMUM LEVELS REQUIRED.
	DMOVE T1,TM8REV(P2)	;SET UP FOR BUGCHK. GET ACTUAL LEVELS.
	DMOVE T3,MINREV		;GET MINIMUM LEVELS.
	BUG.(INF,REVLEV,PHYM78,SOFT,<TM78 Microcode is outdated>,<<T1,ACTUAL LEVELS>,<T2,ACTUAL LEVELS>,<T3,MINIMUM LEVELS>,<T4,MINIMUM LEVELS>>,<

Cause:	The TM78 does not have a microcode version that is needed by this
	monitor.

Action:	Field Service must install the new microcode.

Data:	ACTUAL LEVELS - The actual revision levels in the TM78
	MINIMUM LEVELS - The levels that are required by this monitor
>,,<DB%NND>)			;[7.1210] 

REVCH1:	CALL CLRHLD		;CLEAR HOLD IN TM
UNINF:	MOVSI Q3,1		;WAIT FOR TM READY TO GO BACK ON
UNING:	MOVX T2,.DOTMS
	CALL RDREG3		;BEFORE WE TRY TO TALK TO CONTROLLER AGAIN
	TRNN T1,DI.TMR
	SOJG Q3,UNING
INIL0:	SKIPGE Q1,P5		;[7457] Skip loading Q1 if doing a single unit
	MOVSI Q1,-TM8SLC	;[7457] Load AOB pointer for all units
INILP:	HRRZ T2,Q1		;DRIVE NUMBER
	ADDI T2,DR.ND0		;REGISTER TO TALK TO FOR THIS DRIVE
	ROT T2,-6		;WHERE IT WILL DO THE MOST GOOD
	HRRI T2,DF.SNS		;SET UP A SENSE FOR THIS DRIVE
	CALL WTREG3
	MOVSI Q3,1		;SET UP A COUNTER
INIL1:	HRLI T2,(.DOAS)		;READ ATTENTION SUMMARY
	CALL RDREG3		;AND LOOK FOR US
	MOVEI T2,1		;GET INTO RIGHT POSITION
	LSH T2,0(Q2)
	TRNN T1,0(T2)		;CHECK FOR THIS BIT
	JRST INIL3		;NO WAIT SOME MORE
	MOVX T2,.DOICN		;READ NON-DATA STATUS
	CALL RDREG3
	LDB T2,[POINT 3,T1,27]	;GET DRIVE NUMBER
	CAIN T2,0(Q1)		;CORRECT DRIVE?
	JRST INIU1		;YUP SEE WHAT WE GOT BACK
	CALL CLRATN
INIL3:	SOJG Q3,INIL1		;GO TRY AGAIN
	HRRZ T1,CDBADR(P1)	;[7.1116] Load channel
	HRRZ T2,TM8ADR(P2)	;[7.1116] Load controller
	HRRZ T3,Q1		;[7.1275] Load drive number
	BUG.(CHK,TM8SNS,PHYM78,HARD,<PHYM78 - Can't sense drive status>,<<T1,CHAN>,<T2,CONT>,<T3,UNIT>>,<

Cause:	Repeated attempts to sense a tape drive status have failed.

Action:	There is a TM78 or tape drive hardware problem.  Field Service should
	check out the TM78.  If one particular drive number is being called
	out, that drive is suspect too.

Data:	CHAN - Channel number
	CONT - Controller number
	UNIT - Unit number
>,,<DB%NND>)			;[7.1275][7.1210] 
	JRST NODRV		;FORGET THIS DRIVE

INIU1:	CALL INIUNI		;INITIALIZE A SINGLE UNIT
NODRV:	AOBJN Q1,INILP		;TRY NEXT SLAVE
TOORET:	CALL CLRATN
	MOVE T1,P2		;TELL RETURN TO PUT KDB INTO CDB
	RET
;SUBROUTINE TO SET HOLD IN TM78
;NON-SKIP RETURN IF HOLD WOULDN'T SET
;SKIP RETURN NORMALLY

SETHLD:	MOVE T2,[.DOIA!3776]	;POINT INTERNAL ADDR AT A READ-ONLY LOCATION
	CALL WTREG3		;IN CASE TM78 DECIDES TO WRITE WHEN HOLD SETS
	MOVE T2,[.DOTMS!DO.HLD]
	CALL WTREG3		;SET HOLD SO WE CAN READ REV LEVELS
	MOVEI Q3,40000		;HOW LONG TO WAIT
SETHL1:	MOVSI T2,(.DOTMS)	;READ STATUS
	CALL RDREG3
	TRNN T1,DO.HLA		;HOLD ACKNOWLEDGED?
	SOJG Q3,SETHL1
	JUMPE Q3,R		;LOSE IF IT STILL DIDNT SET
	RETSKP			;HOLD IS SET - SKIP RETURN

;SUBROUTINE TO CLEAR HOLD IN TM78
;ALWAYS RETURNS TO CALL+1

CLRHLD:	MOVSI T2,(.DOTMS)
	CALL WTREG3		;CLEAR HOLD
	MOVE T2,[.DOTMS!DO.TMC]
	CALLRET WTREG3		;CLEAR POSSIBLE ERROR AND RETURN
;THIS ROUTINE IS CALLED TO INITIALIZE A SPECIFIC SLAVE
;INPUT C(P1)=CDB  C(Q1)=UNIT C(P2)KDB  NR; OUTPUT P3

INIUNI:	SAVEQ
	STKVAR <MTINDX>		;INDEX INTO MTCUTB
	MOVX T2,.DOSR		;READ THE STATUS REGISTER
	CALL RDREG3
	TXNN T1,DI.AVL+DI.MNT	;AVAILABLE OR MAINTEANCE MODE?
	JRST CLRATN		;NO, DRIVE DOESN'T EXIST
	HRLOI T3,-MTAN-1	;YES. DRIVE IS THERE. FIND SLOT TO SAVE IT
INIUN1:	AOBJP T3, [BUG.(INF,TM8N2S,PHYM78,HARD,<PHYM78 - More drives than table space, excess ignored>,,<

Cause:	The number of tape drives available exceeds the constant value MTAN.
	Only MTAN drives are configured.

Action:	The monitor should be rebuilt with a value of MTAN large enough to
	accommodate all the tape drives available to the system.
>,,<DB%NND>)			;[7.1210] 
		JRST TOORET]	;DON'T INITIALIZE ANY MORE SLAVES
	SKIPE MTCUTB(T3)	;CHECK TO SEE IF UNIT FREE
	JRST INIUN1		;NOPE TRY NEXT ONE
	MOVEM T3,MTINDX		;SAVE CURRENT LOGICAL INDEX
	MOVE T3,[TM8DSP,,LU.TM8] ;YES, SET UP ADDRESS,,LENGTH
	ADDI P2,(Q1)		;POINT TO PROPER KDB ENTRY
	CALL PHYUDB		;AND ASK FOR UDB ALLOCATION
	  JRST CLRATN		;RETURN IF NO SPACE FOUND
	HRRZM P3,KDBUDB(P2)	;SAVE LINK
	SUBI P2,(Q1)		;FUDGE IT BACK
	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 T2,.DOSR		;GET DRIVE STATUS AGAIN
	CALL RDREG3
	MOVX T3,US.TAP		;INDICATE A TAPE TYPE DEVICE
	TXNN T1,DI.RDY		;ON LINE?
	TXO T3,US.OFS		;NO, SET OFF LINE BIT
	TXNE T1,DI.FPT		;WRITE LOCKED?
	TXO T3,US.WLK		;YES
	HLLM T3,UDBSTS(P3)	;SAVE UDB STATUS
	MOVX T3,.UTT78		;UNIT TYPE
	STOR T3,USTYP,(P3)	;SAVE IT
	MOVX T1,UC.160!UC.625!UC.CD!UC.IC!UC.HD ;SET CHARACTERISTICS
	MOVEM T1,UDBCHR(P3)
	MOVX T2,.DOSN		;NOW SERIAL NR
	CALL RDREG3
	CALL PHCVBO		;CONVERT TO OCTAL
	MOVEM T1,UDBDSN(P3)	;STORE IT
	MOVSI T1,DR.ND0(Q1)	;SET UP UDBSLV = REG TO WRITE,,NUMBER
	LSH T1,^D12		;PUT REGISTER WHERE IT WILL DO THE MOST GOOD
	HRRI T1,(Q1)
	MOVEM T1,UDBSLV(P3)	;SET UP SLAVE ADDRESS
	AOS JB0FLG		;THIS WILL REQUEST JOB0 INCASE CALLER SETS MTAJB0
CLRATN:	MOVEI T2,1		;CLEAR DRIVE ATTENTION
	LSH T2,0(Q2)
	HRLI T2,(.DOAS)		;ATTENTION SUMMARY
	CALLRET WTREG3
	SUBTTL Tables To Control I/O 

TB.DAT==1B0
TB.WRT==1B1
TB.REV==1B2
TB.SPC==1B3
TB.RD==1B4
TB.ERA==1B5
TB.WTM==1B6
TB.REW==1B7
TB.RRG==1B8	;NOT IN TABLE, LIGHTS ON SENSE FROM RDREG
TB.XSN==1B9	;NOT IN TABLE, LIGHTS AFTER SENSE IF WE DO EXTENDED SENSE

FNCTBL:	0			;0 - ILLEGAL
	TB.DAT!TB.RD!DF.RED!1B17 ;1 - READ FORWARD
	0			;2 - ILLEGAL (READ FMT)
	TB.WRT!TB.DAT!DF.WRT!3B17 ;3 - WRITE
	0			;4 -ILLEGAL (WRITE FMT)
	0			;5 - ILLEGAL (SEEK)
	TB.SPC!DF.SPF!6B17	;6 - SKIP RECORD
	TB.SPC!TB.REV!DF.SPR!7B17 ;7 - BACKSPACE RECORD
	TB.WRT!TB.WTM!DF.WTM!10B17 ;10 - WRITE TAPE MARK
	TB.WRT!TB.ERA!DF.ERG!11B17 ;11 - ERASE
REWFNC:	TB.REW!TB.REV!DF.REW!12B17 ;12 - REWIND
UNLFNC:	DF.UNL!13B17		;13 - REW, UNLOAD
	TB.DAT!TB.RD!TB.REV!DF.RRV!14B17 ;14 - READ REVERSE
	0			;15-ILLEGAL (RECOVERY READ)
	0			;16 - ILLEGAL
	0			;17 - ILLEGAL

	WT.GCR==2		;TURN WRITE PE INTO WRITE GCR

;FRAMES/WORD,,MODE BITS

MODTBL:	-1			;0 - ILLEGAL
	5,,30000		;1 - CORE DUMP
	-1			;2 - SIXBIT
	-1			;3 - 7 BIT (ASCII)
	1,,20000		;4 - INDUSTRY COMPAT
	11,,40000		;5 - HIGH DENSITY
MAXMOD==.-MODTBL-1

;DENSITY CODE TABLE

DENTBL:	-1			;0 - ILLEGAL
	-1			;1 - 200 BPI
	-1			;2 - 556 BPI
	-1			;3 - 800 BPI
	0			;4 - 1600 BPI
	WT.GCR			;5 - 6250 BPI
MAXDEN==.-DENTBL-1
IC.RRG==1B0			;READ REGISTERS
IC.BST==1B1			;SET A BIT IN TKBSTS
IC.DSP==1B2			;DISPATCH TO AN ADDRESS
IC.ASY==1B3			;ASYNCH EVENT (RETURN 0 TO TAPSER)
IC.XSN==1B4			;DO AN EXTENDED SENSE TO GET MORE INFO
IC.SNM==1B5			;NO TAPE MOTION
IC.PAD==1B6			;REPOSITION ALREADY DONE (SER=0)

MINREV:	6005,,6004		;MINIMUM TM78 REVISION LEVELS REQUIRED 
	2003,,10003

ICDTBL:	IC.BST!(IS.NRT!IS.ERR)	;0 - UNDEFINED
	0			;1 - DONE
	IC.BST!(IS.TPM)		;2 - UNEXPECTED TAPE MARK
	IC.BST!(IS.TPM!IS.BOT)	;3 - UNEXPECTED BOT
	IC.BST!(IS.EOT)		;4 - END OF TAPE
	IC.BST!(IS.TPM)		;5 - UNEXPECTED LOGICAL EOT
	IC.BST!(IS.NRT)		;6 - NO OP COMPLETED
	IC.DSP!INTRWP		;7 - REWIND IN PROGRESS
	IC.BST!IC.SNM!(IS.WLK!IS.ERR!IS.NRT) ;10 - WRITE TO A WRITE-LOCKED TAPE
	IC.DSP!INTOFL!IC.BST	;11 - NOT READY
	IC.DSP!INTOFL!IC.BST	;12 - DRIVE NOT AVAILABLE (ON OTHER PORT)
	IC.DSP!INTOFL!IC.BST	;13 - OFF LINE
	IC.DSP!INTOFL!IC.BST	;14 - NON-EXISTENT DRIVE
	IC.BST!IC.RRG!(IS.DVE!IS.ERR!IS.NRT) ;15 - NOT CAPABLE
	IC.BST!IC.RRG!(IS.ERR!IS.NRT) ;16 - UNDEFINED
	IC.ASY!IC.DSP!INTONL	;17 - DRIVE HAS COME ON LINE
	IC.BST!IC.RRG!(IS.ERR!IS.NRT!IS.RTL) ;20 - LONG RECORD
	0			;21 - SHORT RECORD
	IC.BST!IC.RRG!IC.XSN!IC.PAD!(IS.ERR!IS.DTE) ;22 - RETRY THE INITIAL OPERATION
	IC.DSP!INTRRO!IC.PAD!IC.BST ;23 - REREAD OPPOSITE
NRTERD:	IC.BST!IC.RRG!IC.XSN!(IS.NRT!IS.DTE) ;24 - UNREADABLE
	IC.BST!IC.RRG!IC.XSN!(IS.ERR!IS.NRT) ;25 - ERROR, SER IS SET
	IC.BST!IC.RRG!IC.XSN!(IS.ERR!IS.NRT) ;26 - ERROR AFTER EOT, SER IS SET
	IC.BST!IC.RRG!IC.XSN!(IS.ERR!IS.NRT!IS.DVE) ;27 - BAD TAPE
NRTERV:	IC.BST!IC.RRG!IC.XSN!(IS.ERR!IS.DVE) ;30 - TM FAULT A
	IC.BST!IC.RRG!IC.XSN!(IS.ERR!IS.NRT!IS.DVE) ;31 - TU FAULT A
	IC.ASY!IC.DSP!CLRTM	;32 - TM FAULT B
ICDND1==.-ICDTBL-1
	IC.ASY!IC.DSP!CLRTM!IC.RRG!IC.XSN ;33 - TU FAULT B
	IC.ASY!IC.DSP!CLRTM	;34 - MASSBUS FAULT
ICDND2==.-ICDTBL-1
MAXICD==.-ICDTBL-1
REVERR==23
	TNXEND
	END