Google
 

Trailing-Edge - PDP-10 Archives - BB-M081Z-SM - monitor-sources/phyh2.mac
There are 52 other files named phyh2.mac in the archive. Click here to see a list.
; Edit= 8908 to PHYH2.MAC on 16-Aug-88 by GSCOTT
;Update BUG. documentation. 
; Edit= 8855 to PHYH2.MAC on 30-Jun-88 by RASPUZZI, for SPR #21891
;Prevent ILLGO BUGHLTs by not trashing T3 when function 0 has been done.
; UPD ID= 8584, RIP:<7.MONITOR>PHYH2.MAC.5,  11-Feb-88 16:54:14 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 8431, RIP:<7.MONITOR>PHYH2.MAC.4,   4-Feb-88 14:12:52 by GSCOTT
;TCO 7.1210 - Set P2RAE1, P2RAE2, P2RAE3, PH2DNA, PH2IHM, and PH2PIM
; normally not dumpable.
; UPD ID= 8429, RIP:<7.MONITOR>PHYH2.MAC.3,   4-Feb-88 14:01:44 by GSCOTT
;TCO 7.1213 - Prevent Class A Massbus errors from causing an ILLGO because
; RH2HNG doesn't clear the stacked transfer before a retry is attempted.
; *** Edit 7463 to PHYH2.MAC by RASPUZZI on 28-Apr-87, for SPR #20634
; Catch ILLUUOs before they happen on a non-existant RH20 channel. Instead,
; let's crash with a RH2NXC.
; UPD ID= 2155, SNARK:<6.1.MONITOR>PHYH2.MAC.35,   5-Jun-85 10:39:02 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 1908, SNARK:<6.1.MONITOR>PHYH2.MAC.34,   4-May-85 22:08:26 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1844, SNARK:<6.1.MONITOR>PHYH2.MAC.33,  30-Apr-85 11:58:47 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1466, SNARK:<6.1.MONITOR>PHYH2.MAC.32,   3-Feb-85 15:18:12 by PAETZOLD
;TCO 6.1.1171 - Fix up ILLGO calculation for modulo 22 bit addressing
; UPD ID= 1462, SNARK:<6.1.MONITOR>PHYH2.MAC.31,   2-Feb-85 11:23:52 by GROSSMAN
;TCO 6.1.1169 - Move KLNI initialization to PHYSIO.
; UPD ID= 4617, SNARK:<6.MONITOR>PHYH2.MAC.30,  28-Jul-84 14:37:49 by GROSSMAN
;Remove references to KNIN.
; UPD ID= 4599, SNARK:<6.MONITOR>PHYH2.MAC.29,  27-Jul-84 00:06:59 by GROSSMAN
;TCO 6.2147 Simplify KLNI initialization.
; UPD ID= 4544, SNARK:<6.MONITOR>PHYH2.MAC.27,  15-Jul-84 21:25:44 by PURRETTA
;Update copyright notice
; UPD ID= 4173, SNARK:<6.MONITOR>PHYH2.MAC.26,   2-May-84 14:36:08 by MCLEAN
;MAKE PH2IUA A BUGHLT IT IS MUCH BETTER
; UPD ID= 3744, SNARK:<6.MONITOR>PHYH2.MAC.25,  23-Feb-84 18:54:25 by MCLEAN
;I WAS SOLD DOWN THE RIVER ON THE LAST EDIT BY MOSER... TRY AGAIN
; UPD ID= 3720, SNARK:<6.MONITOR>PHYH2.MAC.24,  21-Feb-84 13:54:56 by MCLEAN
;CHECK FOR LOSS OF PORT AT RH2UNS+ A FEW FOR DEVICE TYPE OF 0
; UPD ID= 3577, SNARK:<6.MONITOR>PHYH2.MAC.23,  28-Jan-84 08:24:25 by GRANT
;Remove "*** TEMPORARY ***" comment in RH2INI
; UPD ID= 2935, SNARK:<6.MONITOR>PHYH2.MAC.22,  27-Sep-83 09:44:11 by GRANT
;KLIPA initialization no longer done in RH2INI
; UPD ID= 2778, SNARK:<6.MONITOR>PHYH2.MAC.21,  28-Jul-83 14:05:14 by MCLEAN
;GET IT RIGHT.....
;MORE WRNGUN FIX
; UPD ID= 2762, SNARK:<6.MONITOR>PHYH2.MAC.19,  24-Jul-83 02:08:37 by TGRADY
; TCO 6.1750.  Change PH2PIM/PH2PIX back into a BUGCHK
; UPD ID= 2753, SNARK:<6.MONITOR>PHYH2.MAC.18,  23-Jul-83 02:11:14 by MCLEAN
;TCO 6.1749 FIX WRNGUN SO IF P3 IS 0 WE DON'T GET NOIORB BUGHLT'S
; UPD ID= 2427, SNARK:<6.MONITOR>PHYH2.MAC.17,   5-May-83 20:22:04 by PAETZOLD
;TCO 6.1648 - Temporary change to help chase down PH2PIMs
; UPD ID= 2067, SNARK:<6.MONITOR>PHYH2.MAC.16,  23-Mar-83 07:12:01 by LEAPLINE
;More CI/NI changes.
; UPD ID= 1984, SNARK:<6.MONITOR>PHYH2.MAC.15,  14-Mar-83 07:19:27 by LEAPLINE
;Fix checks for CI and NI so they work together.
; UPD ID= 1931, SNARK:<6.MONITOR>PHYH2.MAC.14,   7-Mar-83 21:20:48 by CDUNN
;Change default to include KLIPA code
; UPD ID= 1886, SNARK:<6.MONITOR>PHYH2.MAC.13,  28-Feb-83 19:40:18 by PAETZOLD
;TCO 6.1529 - Remove TCO 6.1515
; UPD ID= 1831, SNARK:<6.MONITOR>PHYH2.MAC.12,  18-Feb-83 16:54:12 by PAETZOLD
;TCO 6.1515 - Add PH2DSW switch
; UPD ID= 1788, SNARK:<6.MONITOR>PHYH2.MAC.11,  11-Feb-83 04:04:09 by WACHS
;TCO 6.1501 - Don't give a PIA to a KLIPA/KLNI
; UPD ID= 1774, SNARK:<6.MONITOR>PHYH2.MAC.10,   7-Feb-83 07:58:40 by PAETZOLD
;More TCO 6.1405 - ACs in the BUG. macro are messed up
; UPD ID= 1584, SNARK:<6.MONITOR>PHYH2.MAC.9,  27-Dec-82 17:49:57 by LEAPLINE
;Change FTKLNI to KNIN
; UPD ID= 1515, SNARK:<6.MONITOR>PHYH2.MAC.8,   7-Dec-82 14:30:51 by PAETZOLD
;TCO 6.1405 - Add more additional data to the PH2PIM BUGHLT
; UPD ID= 1503, SNARK:<6.MONITOR>PHYH2.MAC.7,   1-Dec-82 15:54:52 by LEAPLINE
;TCO 6.1.XXXX	Add KLNI support code under FTKLNI conditional
; UPD ID= 1411, SNARK:<6.MONITOR>PHYH2.MAC.6,   3-Nov-82 16:39:07 by MOSER
;TCO 6.1327 - CORRECTLY RESTORE PREP REGISTER AT DISMISS
; UPD ID= 1409, SNARK:<6.MONITOR>PHYH2.MAC.5,   3-Nov-82 16:36:32 by MOSER
;TCO 6.1325 - MAKE PH2PIM A BUGHLT
; UPD ID= 1015, SNARK:<6.MONITOR>PHYH2.MAC.4,  30-Jul-82 04:45:48 by WACHS
;TCO 6.1198  Changes for CI
; UPD ID= 902, SNARK:<6.MONITOR>PHYH2.MAC.3,   9-Jun-82 23:25:08 by MURPHY
;TCO 6.1147 - Move bugdefs from BUGS.MAC to here and put them in-line.
; UPD ID= 722, SNARK:<6.MONITOR>PHYH2.MAC.2,  11-May-82 04:20:09 by CDUNN
;TCO 6.1127 - Add KLIPA support, add FTKLIPA and FTCI, default to off...
; UPD ID= 502, SNARK:<5.MONITOR>PHYH2.MAC.13,   6-Mar-82 12:17:19 by PAETZOLD
;TCO 5.1748 - Make CLRCHL global
; UPD ID= 149, SNARK:<5.MONITOR>PHYH2.MAC.12,   3-Sep-81 16:48:22 by UHLER
;TCO 5.1487 - ADD EXTN FOR WREQ AND MEMSCN
; UPD ID= 148, SNARK:<5.MONITOR>PHYH2.MAC.11,   3-Sep-81 16:36:29 by UHLER
;TCO 5.1487 - ADD CODE TO DETECT CHANNEL WRITE PARITY ERRORS AND CALL MEMSCN
; UPD ID= 1621, SNARK:<5.MONITOR>PHYH2.MAC.10,   2-Mar-81 07:48:41 by WACHS
;TCO 5.1266 - ADD CODE TO REVCCW
; UPD ID= 1502, SNARK:<5.MONITOR>PHYH2.MAC.9,  27-Jan-81 10:24:54 by WACHS
; UPD ID= 1454, SNARK:<5.MONITOR>PHYH2.MAC.8,  20-Jan-81 05:51:46 by WACHS
; TCO 5.1234 - ADD ROUTINE TO REVERSE THE IOWDS FOR TAPE RETRY OPPOSITE
; UPD ID= 1363, SNARK:<5.MONITOR>PHYH2.MAC.7,  18-Dec-80 10:09:05 by WACHS
; TCO 5.1206 CHANGES FOR HANDLING TM78
; UPD ID= 953, SNARK:<5.MONITOR>PHYH2.MAC.6,  22-Aug-80 16:32:17 by LYONS
;MORE TCO 5.1062 - ALLOW A 0 PAGE ADDR IN THE RH LOGOUN AREA ONLY IF THE
;FUNCTION WAS A READ VALIDITY CHECK
; UPD ID= 574, SNARK:<5.MONITOR>PHYH2.MAC.5,  31-May-80 22:49:28 by DBELL
;MORE TCO 5.1048 - FIX BLKCNT TO HANDLE MULTIPLE CCWS
;TCO 5.1048 - ADD NEW ENTRY POINT TO RETURN ADDRESS FROM CCW WORD
; UPD ID= 483, SNARK:<4.1.MONITOR>PHYH2.MAC.92,  26-Apr-80 11:59:28 by DBELL
;TCO 4.1.1149 - CALL LOWER LEVEL ROUTINES ON HUNG DEVICE CALLS
; UPD ID= 362, SNARK:<4.1.MONITOR>PHYH2.MAC.91,  26-Mar-80 11:07:04 by DBELL
;TCO 4.1.1119 - ADD SUPPORT FOR RP20 DISKS

;	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		;PARAMETER FILE
	TTITLE (PHYH2,,< - Channel Dependent Code For RH20 Controller>)
	SUBTTL T. HESS, T. WACHS, L. BOSACK/LB 29-JUL-75

	SEARCH PHYPAR		;PHYSIO PARAMETERS
	EXTN <WREQ,MEMSCN>
	Subttl	Table of Contents

;		     Table of Contents for AM70-PHYH2
;
;				  Section		      Page
;
;
;    1. Parameters . . . . . . . . . . . . . . . . . . . . . .   3
;    2. Vectored interrupts on non-existant RH20 . . . . . . .   7
;    3. EPT Initialization . . . . . . . . . . . . . . . . . .   8
;    4. Initialization . . . . . . . . . . . . . . . . . . . .   9
;    5. Start I/O and Positioning  . . . . . . . . . . . . . .  14
;    6. Hung and Reset Entries . . . . . . . . . . . . . . . .  15
;    7. Check Routine  . . . . . . . . . . . . . . . . . . . .  16
;    8. Channel Utility Routines
;        8.1    Read Massbus Register  . . . . . . . . . . . .  18
;        8.2    Write Massbus Register . . . . . . . . . . . .  20
;        8.3    Clear RAE and Channel  . . . . . . . . . . . .  22
;        8.4    Start Channel  . . . . . . . . . . . . . . . .  23
;        8.5    Generate CCW . . . . . . . . . . . . . . . . .  25
;        8.6    Check For Errors . . . . . . . . . . . . . . .  26
;        8.7    Compute Number of Device Blocks  . . . . . . .  29
;        8.8    Reverse CCW List . . . . . . . . . . . . . . .  30
;    9. Interrupt Routine  . . . . . . . . . . . . . . . . . .  32
;   10. ECC Channel Logic  . . . . . . . . . . . . . . . . . .  38
;   11. End of PHYH2 . . . . . . . . . . . . . . . . . . . . .  39
	SUBTTL Parameters

;RH20 REGISTERS

DO.BA2==70B5			;SECONDARY BLOCK ADDRESS
DO.CT2==71B5			;SECONDARY TRANSFER CONTROL
DO.BA1==72B5			;PRIMARY BLOCK ADDRESS
DO.CT1==73B5			;PRIMARY TRANSFER CONTROL
DO.IVI==74B5			;INTERRUPT VECTOR INDEX
DO.RDR==75B5			;READ REGISTER
DO.WTR==76B5			;WRITE REGISTER
DO.DIA==77B5			;DIAGNOSTIC CONTROL REGISTER

;DEVICE INDEPENDENT REGISTERS

DO.SR==1B5			;STATUS REGISTER
  DS.PGM=1000			;PROGRAMMABLE PORT SWITCH ENABLED
DO.AS==4B5			;ATTENTION SUMMARY REGISTER
DO.DA==5B5			;DESIRED ADDRESS REGISTER
DO.DT==6B5			;DRIVE TYPE REGISTER

DO.LR==1B6			;LOAD REGISTER ENABLE
DO.DRE==1B9			;DISABLE RAE STOP

;BITS IN DATAO STCR

DO2RCP==1B7			;RESET CHANNEL PC
DO2SCS==1B10			;STORE CHANNEL STATUS
DO2NBC==MASKB(20,29)		;NEGATIVE BLOCK COUNT
DO2RGS==MASKB(0,5)		;REGISTER SELECT FIELD

;COMMON DATAI BITS

DI.CPE==1B8			;CONTROL BUS PARITY ERROR
DI.TRA==1B10			;TRA (MASSBUSS SIGNAL)
DI1UNS==MASKB(15,17)		;UNIT SELECT FIELD IN PTCR
DI1FNC==MASKB(30,35)		;FUNCTION CODE IN PTCR

;LOGOUT AREA FIELDS

LG2DBP==MASKB(14,26)		;LOGOUT WORD 2 DATA BUFFER PAGE NUMBER

;DEVICE DEPENDENT DEFINITIONS IN THE CDB

RH2CNI==CDBDDP+0		;CONI RH2,T1
RH2CNO==CDBDDP+1		;CONO RH2,T2
RH2DTI==CDBDDP+2		;DATAI RH2,T1
RH2DTO==CDBDDP+3		;DATAO RH2,T2

L.RH2==CDBDDP+4-CDBINT		;LENGTH OF RH20 CDB
RH2.0==540B11			;DEVICE CODE OF FIRST RH20
RH2.5==564B11			;DEVICE CODE OF KLNI (5TH SLOT)
RH2.7==574B11			;DEVICE CODE OF LAST RH20
RH2.I==0			;EPT ADDRESS OF FIRST RH20
RH2.L==7			;Last RH channel number

CHXFR==1B0			;INDICATE XFER WORD
CHJMP==2B2			;INDICATE CHANNEL JUMP
CHLST==1B1			;INDICATE LAST XFER
CHREV==1B2			;INDICATE REVERSE
CHCNT==MASKB(3,13)		;MASK FOR WORD COUNT IN CCW
CHADR==MASKB(14,35)		;MASK FOR PHYSICAL ADDRESS IN CCW

;CCYADR:	POINT 22,T1,35		;BYTE POINTER TO CCW ADDRESS FIELD
;CCYCNT:	POINT 11,T1,13		;BYTE POINTER TO CCW COUNT FIELD

;BITS IN CHANNEL LOGOUT AREA

CS1MPE==1B1			;MEMORY PARITY ERROR
CS1NSE==1B2			;NEGATION OF SBUS ERR
CS1NC0==1B3			;NEGATION OF WORDCOUNT = 0
CS1NXM==1B4			;NONEXISTANT MEMORY
CS1LTE==1B9			;LAST TRANSFER ERROR
CS1RHE==1B10			;RH20 ERROR
CS1LWC==1B11			;LONG WORD COUNT (RH20 FINISHED BEFORE CHANNEL)
CS1SWC==1B12			;SHORT WORD COUNT (CHANNEL FINISHED BEFORE RH20)
CS1OVR==1B13			;OVERRUN (MBOX BUFFER)

;SOFTWARE FLAGS IN FUNCTION (USED BY CHSTRT)
ERETRY==200
ERSTRY==400
;RH20 CONI/CONO BITS

;CONI (RH)

CI.BPE==1B18			;DATA BUS PARITY ERROR
CI.EXC==1B19			;EXCEPTION
CI.LWE==1B20			;LONG WORD COUNT ERROR
CI.SWE==1B21			;SHORT WORD COUNT ERROR
CI.MBE==1B22			;MBOX ERROR
CI.DRE==1B23			;DRIVE RESPONSE ERROR
CI.RAE==1B24			;REGISTER ACCESS ERROR
CI.MBH==1B25			;MBOX HALTED
CI.OVR==1B26			;DATA OVERRUN
CI.MEN==1B27			;MASSBUS ENABLE
CI.ATN==1B28			;DRIVE ATTENTION
CI.2RF==1B29			;SECONDARY COMMAND REGISTER FULL
CI.ATE==1B30			;ATTENTION ENABLE
CI.1RF==1B31			;PRIMARY COMMAND REGISTER FULL
CI.DON==1B32			;CHANNEL DONE
CI.PIA==7			;PRIORITY ASSIGNMENT
CI.ERR==555000			;BITS THAT CAUSE ERRORS

KLPMSK==400003,,0		;BITS WHICH DEFINE A KLIPA/KLNI

;CONO

CO.RAE==1B24			;CLEAR REGISTER ACCESS ERROR
CO.RST==1B25			;CONTROLLER RESET
CO.XFR==1B26			;CLEAR TRANSFER ERROR
CO.MEN==1B27			;MASSBUS ENABLE
CO.RCL==1B28			;RESET MBOX COMMAND LIST POINTER
CO.DEL==1B29			;DELETE SECONDARY COMMAND
CO.ATE==1B30			;ENABLE ATTENTION INTERRUPTS
CO.STP==1B31			;STOP CURRENT COMMAND
CO.DON==1B32			;CLEAR DONE
CO.CLR=005010			;CLEAR BITS THAT CAUSE INTERRUPTS
;CHANNEL DISPATCH TABLE FOR RH20

RH2DSP::JRST RH2INI		;0 - INITIATION
	JRST RH2STK		;1 - STACK SECOND CHANNEL COMMAND
	JRST RH2SIO		;2 - START I/O
	JRST RH2POS		;3 - POSITION REQUEST
	JRST RH2LTM		;4 - RETURN BEST XFER
	JRST RH2INT		;5 - INTERRUPT PROCESSING
	JRST RH2CCW		;6 - MAKE CHANNEL XFER WORD
	JRST RH2HNG		;7 - TRANSFER HUNG
	JRST RH2RST		;10 - RESET CHANNEL
	JRST RH2CHK		;11 - PERIODIC CHECK
	JRST EXTKDB		;12 - CHECK UNIT EXISTANCE
	JRST RH2CCA		;13 - EXTRACT ADDRESS FROM CCW WORD

;DUMMIES

RH2LTM:	RET
	SUBTTL Vectored interrupts on non-existant RH20
;RHxBAD - This routine has 8 entry points. Each entry point is
;for a different RH20 channel. We get here when the monitor gets
;an interrupt on an RH20 channel and that channel does not physically
;exist. [7463]
;
; Called by:
;	We come in here by a vectored interrupt from a non-existant RH20
;
; Returns:
;	Never - This routine will always BUGHLT.

RH0BAD::MOVEI T1,0		;Interrupt from channel 0
	JRST RHHALT		;Now crash
RH1BAD::MOVEI T1,1		;Interrupt from channel 1
	JRST RHHALT
RH2BAD::MOVEI T1,2		;Interrupt from channel 2
	JRST RHHALT
RH3BAD::MOVEI T1,3		;Interrupt from channel 3
	JRST RHHALT
RH4BAD::MOVEI T1,4		;Interrupt from channel 4
	JRST RHHALT
RH5BAD::MOVEI T1,5		;Interrupt from channel 5
	JRST RHHALT
RH6BAD::MOVEI T1,6		;Interrupt from channel 6
	JRST RHHALT
RH7BAD::MOVEI T1,7		;Interrupt from channel 7
RHHALT:	BUG.(HLT,RH2NXC,PHYH2,HARD,<Interrupt from non-existant RH20>,<<T1,RHCHAN>>,<

Cause:	The monitor received a vectored interrupt from an RH20 channel.  But
	during system startup this RH20 did not exist in the configuration.
	This is almost always caused by faulty hardware (ie - 2 RH20s may be
	interrupting the KL simultaneously).

Action:	Contact Field Service and have them find out which RH20 is faulty.

Data:	RHCHAN - RH20 that requested the interrupt that does not exist.
>) ;Crash!
	SUBTTL EPT Initialization
;EPTINI - This routine initializes the fourth word of each RH20
;channel. Each word is initialized to point to a routine to handle 
;an interrupt on this channel when that channel does not exist.
;The fourth word of each channel will be setup properly by RH2INI when
;we return from this routine. [7463]
;
; Call with:
;	no arguments
;	CALL EPTINI
;
; Returns:
;	+1 - Always, with each channel's vectored interrupt word setup
;	     to BUGHLT if the channel is not there (that is to be determined
;	     later in RH2INI)
;
;Clobbers no Acs!

EPTINI:	SAVET			;Don't bash these
	MOVE T1,[XPCW RH0ERR]	;Here's the first channel's interrupt word
	MOVEI T3,RH2.I		;Point to first RH20 channel
EPTIN1:	MOVE T2,T3		;Put current channel in T2
	IMULI T2,4		;There are 4 words per RH20 channel in the EPT
	ADDI T2,3		;The vectored interrupt word is the third one
	MOVEM T1,KIEPT(T2)	;Store instruction
	ADDI T1,4		;Get next address for XPCW
	AOS T3			;Do next channel
	CAIG T3,RH2.L		;All channel done?
	JRST EPTIN1		;No, do next channel
	RET			;Fini
	SUBTTL Initialization

RH2INI:	CALL EPTINI		;[7463] (/) Init the EPT with no RH20s
				;[7463] Now see what RH20s exist
	MOVSI Q1,(RH2.0)	;INITIAL CHANNEL DEVICE ADDRESS
	PUSH P,Q1		;SAVE ON PDL

RH2NCH:	CALL DEVXCT		;SET PIA
	 CONO 0,CO.MEN+7
	CALL DEVXCT		;READ DEVICE REGISTER
	 CONI 0,T1		;STATUS INTO T1
	TRNN T1,7		;EXISTS?
	JRST RH2NXT		;NO - TRY NEXT
	CALL DEVXCT		;YES - DO CONTROLLER RESET
	 CONO 0,CO.RST		;...
	AND T1,[KLPMSK]		;ONLY THOSE BITS WHICH DEFINE A KLIPA/KLNI
	CAMN T1,[KLPMSK]	;IS IT ONE OF THEM?
	 JRST RH2NXT		;THEY MAKE THEIR OWN CDBS
	CALL DEVXCT		;NOW SET MASSBUS ENABLE
	 CONO 0,CO.MEN
RH2NC2:	MOVEI T1,L.RH2		;GET LENGTH OF CDB
	CALL PHYALC		;ALLOCATE SOME STORAGE
	 JRST PA1		;FAILURE QUIT INITALIZATION
	MOVEI P1,-CDBINT(T1)	;CDB BASE ADDRESS TO P1
	HRRZ P4,(P)		;GET ACTUAL CHANNEL ADDRESS
	MOVEM P1,CHNTAB(P4)	;SAVE CDB IN CHANNEL TABLE
	HRRZM P4,CDBADR(P1)	;STORE CHNTAB INDEX
	EXCH P1,P3		;GET CDB IN P3
	MOVEI T1,.BTCDB		;MARK AS CDB
	DPB T1,USYBKT		; ...
	EXCH P1,P3		;RESTORE
	MOVEI T1,.CTRH2		;SET TYPE
	DPB T1,CSYTYP		;..
	MOVEI T1,PHYCHN		;GET PIA
	DPB T1,CSYPIA		;SET PIA IN CONFIGURATION INFORMATION
	MOVSI T1,(CS.STK)	;INDICATE CHANNEL CAN DO COMMAND
	IORM T1,CDBSTS(P1)	;STACKING
	MOVE T1,[CONO 0,CO.MEN(T2)] ;SET UP IOT'S
	IOR T1,Q1		;WITH CORRECT DEVICE CODES
	MOVEM T1,RH2CNO(P1)	;STASH IN CDB
	MOVE T1,[CONI 0,T1]	;CONI STATUS
	IOR T1,Q1		;SET DEVICE CODE
	MOVEM T1,RH2CNI(P1)	;STORE IN CDB
	MOVE T1,[DATAO 0,T2]	;DATAO INSTRUCTION
	IOR T1,Q1		;SET DEVICE CODE
	MOVEM T1,RH2DTO(P1)	;STASH IN CDB
	MOVE T1,[DATAI 0,T1]	;DATAI INSTRUCTION
	IOR T1,Q1		;SET DEVICE CODE
	MOVEM T1,RH2DTI(P1)	;INTO CDB
	HRRZ T1,(P)		;GET RH NUMBER
	LSH T1,2		;TIMES 4
	MOVEI T2,KIEPT+3(T1)	;IN UNUSED LOGOUT AREA
	HRLZM T2,CDBICP(P1)	;AND STORE AS INTERRUPT VECOTOR
	MOVEI T3,CDBINT(P1)	;ADDRESS FOR XPCW ON INTERRUPT
	HRLI T3,(<XPCW>)	;BUILD INSTRUCTION
	MOVEM T3,0(T2)		;STORE IN PAGE 0
	MOVEI T3,CDBINT+4(P1)	;SET JUMP ADDRESS
	MOVEM T3,CDBINT+3(P1)	;SET IN XFER VECTOR
	SETZM CDBINT+2(P1)	;SET FLAGS TO 0
	ADDI T1,RH2.I+KIEPT	;ADDRESS OF CHANNEL ICP AREA
	HRRM T1,CDBICP(P1)	;STASH IN CDB

	MOVE T1,[MOVEM P1,CDBSVQ]
	ADDI T1,0(P1)		;INSTRUCTION TO STORE P1 IN CDB
	MOVEM T1,CDBINT+4(P1)	;BUILD INTERRUPT CODE
	MOVE T1,[JSP P1,PHYINT]
	MOVEM T1,CDBINT+5(P1)	;DISPATCH TO PHYSIO
	MOVE T1,[BLT 17,17]	;INSTRUCTION TO RESTORE ACCUMULATORS
	MOVEM T1,CDBJEN(P1)	;PUT IN CDB
	MOVEI T1,CDBRST(P1)	;BUILD DATAO CDBRST, TO RESET THE
	HRLI T1,(DATAO 0,0)	; RH20 PREPARATION REGISTER
	IOR T1,Q1
	MOVEM T1,CDBJEN+1(P1)	;STORE IT IN THE EXIT SEQUENCE
	MOVEI T1,CDBINT(P1)	;ADDRESS OF INTERRUPT PC
	HRLI T1,(<XJEN 0>)	;BUILD XJEN INSTRUCTION
	MOVEM T1,CDBJEN+2(P1)	;STORE
	MOVEI T1,RH2DSP		;INSERT DISPATCH VECTOR
	MOVEM T1,CDBDSP(P1)	;SET UP DISPATCH
				;NOW FIND UNITS & TYPES
	MOVE Q3,[-MAXRH,,CDBUDB] ;AOBJN POINTER TO UDB TABLE
	ADDI Q3,0(P1)		;RELOCATE POINTER
	MOVEM Q3,CDBCUN(P1)	;STORE IN CDB
	MOVEM Q3,CDBIUN(P1)	;...
	SETOM CDBXFR(P1)	;INDICATE CHANNEL FREE
	MOVEI Q2,0		;FIRST UNIT #

RH2UNL:	MOVEI T2,CO.RAE		;RESET RAE (IN CASE)
	XCT RH2CNO(P1)
	SETZM P3		;IN CASE NOT WANTED
	SETOM P5		;INDICATE TO CREATE ALL UDBS AND KDBS
	CALL RH2UNS		;SEARCH UNIT TYPE
RH2NXU:	MOVEM P3,0(Q3)		;STORE IN CDB IF ANY (0 IF NONE)
	AOS Q2			;NEXT UNIT #
	AOBJN Q3,RH2UNL		;KEEP GOING

	MOVEI T2,CO.RAE		;CLEAR REGISTER ACCESS ERROR
	XCT RH2CNO(P1)		;...
	SETOM CDBCAD(P1)	;CLEAR THIS WORD SINCE RH2RST WON'T
	MOVEI T1,0		;CONTROLLER ONLY RESET
	CALL RH2RST		; ...
;	MOVE T1,CDBIUN(P1)	;CHECK IF ANY DEVICES FOUND.
;RH2CKU:	SKIPE (T1)		;UNIT PRESENT?
;	JRST RH2NXT		;YES, GO ON TO NEXT CHANNEL
;	AOBJN T1,RH2CKU		;NO, LOOP FOR MORE
;	MOVSI T1,(CS.OFL)	;NONE PRESENT, MARK OFFLINE.
;	IORM T1,CDBSTS(P1)	; ...
;	MOVE Q1,(P)		;RECOVER DEVXCT ARGUMENT
;	CALL DEVXCT		;COMPLETELY DISABLE RH
;	 CONO 0,0		; ...

RH2NXT:	AOS Q1,0(P)		;RESTORE DEVICE CODE
	ADD Q1,[4B11]		;ADVANCE TO NEXT CHANNEL
	MOVEM Q1,0(P)		;STASH NEW ADDRESS
	TRZ Q1,-1		;CLEAR CHANNEL #
	CAMLE Q1,[RH2.7]	;BEYOND LAST?
	AOJA P4,PA1		;INCR MAXCHN AND EXIT
	JRST RH2NCH		;TRY NEXT
;
; ROUTINE TO DETERMINE THE TYPE OF DISK/TAPE
;
;
RH2UNS::MOVSI T2,(DO.DT)	;DEVICE TYPE REGISTER
	TLO T2,(Q2)		;SET UNIT NUMBER
	XCT RH2DTO(P1)		;SEND OUT
	XCT RH2DTI(P1)		;AND READ BACK
	TLNN T1,(DI.TRA)	;NORMAL RESPONSE?
	JRST RH2US1		;NO - GO CLEAR RAE AND EXIT
	LDB T1,[POINT 9,T1,35]	;GET DEVICE TYPE CODE
	JUMPE T1,[ MOVSI T2,(DO.SR)	 ;TRY TO GET THE PORT AGAIN THIS TIME WE MISSED
		   TLO T2,(Q2)		;READ THE STATUS REGISTER
		   XCT RH2DTO(P1)	;SEND OUT REQUEST
		   XCT RH2DTI(P1)	;GET STATUS BACK
		   TLNN T1,(DI.TRA)	;CHECK FOR ERROR
		   JRST RH2US1		;CLEAR ERROR
		   TRNN T1,DS.PGM	;CHECK FOR PGM MODE
		   RET			;NOT IN PGM FORGET IT
		   JRST RH2UNS]		;WAIT TILL WE CAN READ DRIVE TYPE REGISTER
	CAIG T1,TY.RPH		;WITHING RP04,5,6 RANGE?
	CAIGE T1,TY.RPL		; ??
	SKIPA			;NO.
	JRST RH2IRP		;YES - INITIALIZE IT
	CAIN T1,TY.RS4		;RS04 TYPE?
	JRST RH2IRS		;YES - INITIALIZE IT
	CAIN T1,TY.DXA		;DX20A TYPE?
	JRST RH2IDA		;YES - INITIALIZE IT
	CAIN T1,TY.DXB		;DX20B TYPE?
	JRST RH2IDB		;YES - INITIALIZE IT
	CAIG T1,TY.T3H		;WITHIN TM03 RANGE
	CAIGE T1,TY.T3L		; ???
	SKIPA			;NO
	JRST RH2ITM		;YES
	CAIG T1,TY.T2H		;GREATER THAN HIGHEST TM02 TYPE
	CAIGE T1,TY.T2L		;OR LOWER THAN LOWEST?
	SKIPA			;YES - NOT TM02
	JRST RH2ITM		;IS TM02 - GO INITIALIZE
	CAIN T1,TY.T78		;TM78 TYPE?
	JRST RH2IT8		;YES, INITIALIZE IT
	RET			;NOT A KNOWN DEVICE

;HERE IF UNIT WAS NONEXISTANT

RH2US1:	MOVEI T2,CO.RAE		;CLEAR RAE
	XCT RH2CNO(P1)		; ...
	RET			;RETURN
;ROUTINE TO INVOKE RP04/RS04 INITIATION

RH2IRS:	SKIPA T1,[.UTRS4]	;RS04 TYPE
RH2IRP:	MOVEI T1,.UTRP4		;RP04 TYPE
	CALL FNDUTP		;FIND TABLE ENTRY
	 CALL UDSINI(T1)	;CALL INITIALIZE IF FOUND
	RET			;ADVANCE TO NEXT UNIT

;HERE TO INITIALIZE A DX20

RH2IDA:	SKIPA T1,[.UTDXA]	;SEARCH FOR DX20A (TAPE CONTROLLER)
RH2IDB:	MOVEI T1,.UTDXB		;OR FOR DX20B (DISK CONTROLLER)
	JRST RH2ITD		;GO SEARCH FOR DX20

;HERE TO INITIALIZE A TM02/3

RH2ITM:	MOVEI T1,.UTTM2		;SEARCH FOR TM02
RH2ITD:	MOVEI P2,0		;IN CASE NOT FOUND IN TABLES
	CALL FNDUTP		; ...
	 CALL UDSINI(T1)	;FOUND - CALL INITIALIZE, RETURN KDB IN P2
	MOVE P3,P2		;COPY KDB TO WHERE COMMON CODE WANTS IT
	RET			;LOOP FOR MORE

;HERE TO INITIALIZE A TM78
RH2IT8:	MOVEI T1,.UTTM7		;SEARCH FOR TM78
	JRST RH2ITD		;GO SEARCH

;ROUTINE USED TO EXECUTE IOT FOUND AT CALL+1
;NOTE - INSTRUCTION MUST NOT CAUSE SKIP!

DEVXCT:	MOVE T4,@(P)		;FETCH IOT
	IOR T4,Q1		;OR IN DEVICE CODE
	XCT T4			;EXECUTE IT
	RETSKP			;RETURN - SKIP OVER INSTRUCTION

;ROUTINE TO SCAN CHANNEL/UNIT TABLES FOR TYPE GIVEN IN T1
;RETURNS TABLE ENTRY IN T1 (SKIP RETURN ON NOT FOUND)

FNDUTP:	MOVE T2,[PHYUNL,,PHYUNT] ;ENTRY FOR UNIT TABLE
FNDTPL:	HLRZ T3,0(T2)		;GET LH = TYPE CODE
	CAME T1,T3		;TYPES MATCH?
	AOBJN T2,FNDTPL		;NO - TRY NEXT
	JUMPGE T2,RSKP		;SKIP RETURN IF NO MATCH
	HRRZ T1,0(T2)		;MATCH - GET DISPATCH ADDRESS
	RET			;RETURN
	SUBTTL Start I/O and Positioning

;HERE TO START POSITIONING (P3 := UDB)

RH2POS:	HRRZ T1,UDBDSP(P3)	;ADDRESS OF DEVICE ROUTINE
	CALLRET UDSPOS(T1)	;START IT

;HERE TO START ACTUAL OPERATION (P3 := UDB , P4 := IORB)

RH2SIO:	HRRZ T1,CDBICP(P1)	;GET STATUS AREA
	SETZM 1(T1)		;CLEAR CS1
	HRRZ T1,UDBDSP(P3)	;DISPATCH TO DEVICE CODE
	CALL UDSSIO(T1)		;ATTEMPT TO START IO
	 JRST CLRCHL		;LOSE
	RETSKP			;WIN

;HERE TO STACK A SECOND COMMAND TO THE RH20

RH2STK:	HRRZ T1,UDBDSP(P3)	;GET UNIT DISPATCH
	CALLRET UDSSTK(T1)
	SUBTTL Hung and Reset Entries

;HERE ON A HUNG TRANSFER
;CALLED WITH PI OFF

RH2HNG:	MOVEI T1,1		;[7.1213] Full reset to prevent ILLGOs
	CALL RH2RST		;RESET THE RH20
	HRRZ T1,UDBDSP(P3)	;GET DISPATCH ADDRESS
	CALLRET UDSHNG(T1)	;RESET CONTROLLER AND UNIT ALSO


;HERE TO RESET THE CHANNEL AND ALL UNITS
;T1/ 0 TO RESET JUST THE CHANNEL
;T1/ 1 FOR FULL RESET

RH2RST:	SKIPE T4,T1		;COPY ARG TO SAFE PLACE
	SETOM CDBCAD(P1)	;CLEAR PRIMARY CCW ADDRESS ONLY IF FULL RESET
	SETOM CDBCAD+1(P1)	;ALWAYS CLEAR SECONDARY ADDRESS
	MOVEI T1,CO.DEL!CO.DON	;DELETE ANY SECONDARY COMMAND
	CALL CHNCNO		;DO CONO
	MOVEI T1,CO.STP		;STOP ANY TRANSFER
	CALL CHNCNO		;DO CONO
	MOVEI T2,CO.RST		;CONO RESET
	SKIPE T4		;IF GENTLE RESET, SKIP MBINIT
	XCT RH2CNO(P1)		;DO CONO DIRECTLY
	HLRZ T2,CDBICP(P1)	;SETUP INTERRUPT VECTOR ADDRESS
	HRLI T2,(DO.IVI)
	CALL WTREGX		;WRITE IN CONTROLLER
	CALLRET CLRCHL		;AND REINIT CHANNEL
	SUBTTL Check Routine

;HERE EVERY NOW AND THEN (ABOUT 1 SEC) TO CHECK PIA.

RH2CHK:	MOVE T1,CDBSTS(P1)	;GET STATUS BITS
	TXNE T1,CS.OFL		;IS RH20 MARKED OFFLINE?
	RET			;YES, DON'T CHECK ANYTHING
	XCT RH2CNI(P1)		;GET CONI
	MOVE T3,T1		;SAVE THE CONI WORD IN A SAFE PLACE
	ANDI T1,7		;MASK PIA
	LDB T2,CSYPIA		;GET WHAT IT SHOULD BE
	CAMN T1,T2		;ARE THEY THE SAME?
	RET			;YES

; Temporary
; In the never ending search for the PH2PIMs another wonderful diagnostic
; routine.

	MOVE T4,T3		;SAVE THE FIRST CONI
	XCT RH2CNI(P1)		;GET THE CONI AGAIN
	MOVE T3,T1		;SAVE THE CONI WORD
	ANDI T1,7		;GET THE PI BITS
	LDB T2,CSYPIA		;GET WHAT IT SHOULD BE
	CAME T1,T2		;ARE THEY THE SAME
	 JRST RH2CH1		;NO SO IT IS SOLID
	HRRZ T1,CDBADR(P1)	;GET CHANNEL NUMBER
	BUG.(CHK,PH2PIX,PHYH2,HARD,<PHYH2 - RH20 returned from the twilight zone>,<<T1,CHAN>,<T3,CONI>,<T4,OLD>,<T2,PIA>>,<

Cause:	The routine RH2CHK was called for a periodic check on the status of the
	channel, and found that the PI assignment for the channel was not what
	was expected.  A second check of the channel status found the correct
	PI assignment.

Action:	Call Field Service and have them check the channel listed as the first
	item of additional data.

Data:	CHAN - The channel number
	CONI - The results of the final CONI on the RH
	OLD - The results of the first CONI on the RH
	PIA - The PI assignment we expected to see
>)
	RET			;IT GOT BETTER, SOMEHOW.
RH2CH1:
	HRRZ T1,CDBADR(P1)	;GET CHANNEL #
	BUG.(CHK,PH2PIM,PHYH2,HARD,<PHYH2 - RH20 lost PI assignment>,<<T1,CHAN>,<T3,CONI>,<T2,PIA>>,<

Cause:	The routine RH2CHK was called for a periodic check on the status of the
	RH20, and it discovered that the channel assignment of the RH20 changed
	from what it should be.  This usually indicates a hardware malfunction.
	This situation is serious as it could cause file structure damage.

Action:	Call Field Service and have them check out the channel listed in the
	additional data.

Data:	CHAN - The channel number
	CONI - The results of the CONI on the RH
	PIA - The PI assignment we expected to see but did not see
>,,<DB%NND>)			;[7.1210] 
	LDB T2,CSYPIA		;GET CORRECT PIA
	MOVSI T1,(CS.ACT)	;IS CHANNEL ACTIVE?
	TDNN T1,CDBSTS(P1)	; ??
	TRO T2,CO.ATE		;NO, SET ATTENTION EN
	XCT RH2CNO(P1)		;SEND TO CHANNEL
	RET
	SUBTTL Channel Utility Routines -- Read Massbus Register

;ROUTINE TO READ A MASS-BUSS REGISTER
;CALL - C(T2) := REGISTER TO BE READ
;	C(P3) := UDB POINTER
;	C(P1) := CDB POINTER
;RETURNS VALUE IN T1 , PRESERVES T4

RDREG::	HRRZ T3,UDBAKA(P3)	;GET UNIT #
	SKIPL T2		;INTERNAL REGISTER?
	TLO T2,(DO.DRE)		;NO - TRY FIRST WITH DRAES ON
	TLOA T2,(T3)		;SET UNIT NUMBER
RDREG3::TLO T2,<(DO.DRE)>(Q2)	;UNIT # IN Q2
RDREGX:	MOVEI T3,^D10		;INITIALIZE RETRY COUNTER
RDREGL:	XCT RH2DTO(P1)		;DATAO RH2,T2
	XCT RH2DTI(P1)		;NOW READ REGISTER (DATAI RH2,T1)
	PUSH P,T1		;SAVE RESULT
	XCT RH2CNI(P1)		;GET CONI
	TRNE T1,CI.RAE		;REGISTER ACC ERR?
	JRST RDRAE		;YES - BAD NEWS
RDRAE1:	POP P,T1		;NO - RESTORE RESULT
	SKIPGE T2		;READING AN INTERNAL RH REGISTER?
	RET			;YES - DONE
	TLNN T1,(DI.CPE)	;CONTROL BUS PAR ERR?
	TLNN T1,(DI.TRA)	;OR NOT TRA
	JRST RDREGE		;YES - ERROR
RDEXIT:	ANDI T1,177777		; CLEAR OUT GARBAGE
	RET			;EXIT

;HERE WHEN CBPE OR MISSING TRA

RDREGE:	SOJG T3,RDREGL		;LOOP IF RETRY STILL POSITIVE
	TLZ T2,(DO.DRE)		;TRY ONE MORE TIME - IF RAE, BOMB WORLD
	JUMPL T3,RDEXIT		;IF NOW NEGATIVE, DEPART, TRAGIC ERROR
	JRST RDREGL		;TRY AGAIN
;HERE WHEN A REGISTER ACCESS ERROR IS DETECTED

RDRAE:	PUSH P,T2		;SAVE ANOTHER REGISTER
	TLNE T2,(DO.DRE)	;DRAES?
	JRST RDRAE2		;YES - JUST CLEAR RAE
	MOVE T2,T1		;COPY CONI
	XCT RH2DTI(P1)		;GET DATAI
	PUSH P,T3
	HRRZ T3,CDBADR(P1)
	BUG.(CHK,P2RAE1,PHYH2,HARD,<PHYH2 - RH20 register access error reading register>,<<T1,DATAI>,<T2,CONI>,<T3,CHAN>>,<

Cause:	The routine RDREG was called to read a MASSBUS register, but the read
	failed due to a register access error from the RH20.  This is almost
	always due to a hardware malfunction.  It can also happen when a RP06
	LAP (Logical Address Plug) is removed or inserted.

Action:	Call Field Service if this is seen unless RP06 LAPs are being removed
	or inserted.

Data:	DATAI - The result of a DATAI done after the error was detected
	CONI - The CONI which showed the register access error
	CHAN - The channel number
>,,<DB%NND>)			;[7.1210] 
	POP P,T3
	CALL CLRRAE		;RESET RAE
	POP P,T2		;RESTORE REGISTERS
	POP P,T1		; ...
	JRST RDEXIT		;ALL WE COULD DO...

RDRAE2:	CALL CLRRAE		;CLEAR ERROR
	POP P,T2
	JRST RDRAE1		;CONTINUE ATTEMPT
	SUBTTL Channel Utility Routines -- Write Massbus Register

;ROUTINE TO WRITE A MASS-BUSS REGISTER
;CALL - C(T2) := REGISTER TO BE WRITTEN & DATA
;	C(P1) := CDB , C(P3) := UDB
;PRESERVES T1,T4

WTREG::	HRRZ T3,UDBAKA(P3)	;GET UNIT #
	TLOA T2,<(DO.LR)>(T3)	;SET IN LHS AND LR ENABLE
WTREG3::TLO T2,<(DO.LR)>(Q2)	;SET LR AND UNIT NUMBER FROM Q2
WTREGX:	TLO T2,(DO.LR)		;WRITE A REGISTER WHEN THE DRIVE NUMBER DOESNT MATTER
	XCT RH2DTO(P1)		;ZAP
	PUSH P,T1		;SAVE REGISTER
	XCT RH2CNI(P1)		;GET CONI
	TRNE T1,CI.RAE		;REGISTER ACC ERR?
	JRST WTRAE		;YES - BAD NEWS
	POP P,T1		;NO - RESTORE REGISTER
	RET			;RETURN
;HERE WHEN RAE ON WRITE

WTRAE:	PUSH P,T3		;SAVE REGISTER
	MOVE T3,T1		;COPY CONI
	XCT RH2DTI(P1)		;GET DATAI
	PUSH P,T4
	HRRZ T4,CDBADR(P1)	;GET CHANNEL NUMBER
	BUG.(CHK,P2RAE2,PHYH2,HARD,<PHYH2 - Register access error writing register>,<<T1,DATAI>,<T2,DATA>,<T3,CONI>,<T4,CHAN>>,<

Cause:	The routine WTREG was called to write a MASSBUS register, but the write
	failed due to a register access error from the RH20.  This is almost
	always due to a hardware malfunction.  It can also happen when a RP06
	LAP (Logical Address Plug) is removed or inserted.

Action:	Call Field Service if this is seen unless RP06 LAPs are being removed
	or inserted.

Data:	DATAI - The result of a DATAI done after the error was detected
	DATA - The register and data that was attempted to be written
	CONI - The CONI which showed the register access error
	CHAN - The channel number
>,,<DB%NND>)			;[7.1210] 
	POP P,T4		;RESTORE REG
	MOVE T3,T2		;SAVE ATTEMPTED REGISTER
	CALL CLRRAE		;CLEAR RAE
	MOVE T2,T3		;RESTORE
	POP P,T3		;RESTORE
	POP P,T1
	RET
	SUBTTL Channel Utility Routines -- Clear RAE and Channel

;HERE TO CLEAR RAE
;USES ONLY T2.

CLRRAE:	LDB T2,CSYPIA		;GET PIA
	TRO T2,CO.RAE		;CLEAR RAE
	XCT RH2CNO(P1)		;DO CLEAR
	RET

;ROUTINE TO CLEAR RH20 CONTROLLER OR DO A CONO
;PRESERVES T4

CLRCHL:: MOVEI T1,CO.CLR!CO.ATE	;ENABLE FOR ALL INTERRUPTS
CHNCNO:	LDB T2,CSYPIA		;GET PI ASSIGNMENT
	IOR T2,T1		;BUILD CONO
	XCT RH2CNO(P1)		;...
	RET			;RETURN
	SUBTTL Channel Utility Routines -- Start Channel

;ROUTINE TO START CHANNEL I/O
;CALLED WITH PI OFF
;C(T2) := DATAO , C(Q1) := FUNCTION , C(P3) := UDB POINTER
;C(Q1) = -1 IMPLIES ONLY DATAO FROM T2
;GIVES SKIP RETURN TO SHOW ALL OK

CHSTRT::SKIPE T2		;CHECK FOR VALID OPS
	SKIPN Q1		; ...
	BUG.(HLT,RH2ICF,PHYH2,SOFT,<PHYRH2 - Invalid channel function>,,<

Cause:	The routine CHSTRT was called to start I/O on the channel, but the
	supplied arguments were illegal.  Either no DATAO word was specified,
	or the function code was zero.
>)
	HRRZ T1,UDBAKA(P3)	;GET UNIT NUMBER
	SKIPL CDBXFR(P1)	;IF NON DATA TRANSFER
	CAMN T1,CDBXFR(P1)	;OR SAME AS UNIT HOLDING CHANNEL
	SKIPA Q2,[CO.ATE]	;CONSIDER ATTENTION ENABLE
	MOVEI Q2,0		;ELSE DISABLE ATTENTION INTERRUPTS
	CAMN Q1,[EXP -1]	;NON CHANNEL FUNCTION?
	JRST [	MOVEI Q1,0	;YES
		JRST CHST1]	;DO JUST ONE DATAO
	CAIGE Q1,50		;DATA TRANSFER OPERATION?
	JRST CHST1		;NO
	MOVEI Q2,0		;OPERATION USES CHANNEL, DISABLE ATTENTION
	PUSH P,T2		;SAVE DATAO
	MOVX T2,CS.CWP		;GET CHANNEL WRITE PARITY ERROR BIT
	ANDCAM T2,CDBSTS(P1)	;CLEAR IT IN THE CDB
	TRZE Q1,ERSTRY		;CHAN LIST ALREADY SET UP?
	JRST CHST0		;YES, SKIP SETUP
	MOVSI T2,(CS.ACL)	;TOGGLE CCW LIST
	XORM T2,CDBSTS(P1)	; ..
	MOVEI T1,CDBCCL(P1)	;DO SETUP
	MOVEI T2,CDBCCL+1(P1)
	TRZN Q1,ERETRY		;ECC RETRY?
	CALL PHYXFL		;NO - GET HEAD OF TRANSFER LIST
	MOVE T4,T1		;REMEMBER BEGINNING OF LIST
	HRL T4,T2		;AND END OF LIST
	MOVEI T3,CDBCAD(P1)	;GET ADDRESS OF PRIMARY CCW ADDRESS WORD
	SKIPL 0(T3)		;IS IT IN USE?
	AOS T3			;YES, STEP ADDRESS TO SECONDARY CCW ADDRESS WRD
	HRRZM T1,0(T3)		;STORE CCW ADDRESS IN APPROPRIATE WORD
	SETMM (T1)		;INSURE REFERENCE
	MAP T1,(T1)		;GET PHYSICAL ADDRESS
	TLZ T1,777760		;FLUSH ACCESS BITS ETC
	TLO T1,(CHJMP)		;BUILD CHANNEL JUMP
	HRRZ T3,CDBICP(P1)	;AND STORE IN
	MOVEM T1,(T3)		;CHANNEL ICPC
	MOVSI T3,(CHLST)	;SET LAST TRANSFER
	IORM T3,-1(T2)		;IN CCW LIST
	MOVE T1,T4		;RESTORE TRANSFER LIST POINTER
CHST0:	CALL BLKCNT		;GET BLOCK COUNT FROM TRANSFER LIST
	MOVNS T1		;AS NEGATIVE NUMBER
	STOR T1,DO2NBC,Q1	;STORE IN DATAO STCR
	TXO Q1,DO.CT2!DO2RCP!DO2SCS ;FINISH STCR DATAO
	POP P,T2		;RECOVER DATAO
	LOAD T1,DO2RGS,T2	;GET REGISTER
	CAIN T1,<(DO.DA)>_-^D12	;DESIRED ADDRESS?
	TLC T2,(75B5)		;YES XOR TO PRODUCE SBAR

CHST1:	HRRZ T3,UDBAKA(P3)	;GET UNIT ADDRESS
	TLO T2,<(DO.LR)>(T3)	;SET UNIT AND LOAD
	XCT RH2DTO(P1)		;WRITE REG
	JUMPE Q1,CHST2		;SECOND DATAO TO DO?
	MOVE T2,Q1		;YES - GET CONTROL REGISTER
	TLO T2,<(DO.LR)>(T3)	;SET UNIT AND LOAD
	MOVEM T2,CDBICR(P1)	;SAVE INITIAL TCR FOR LOGGER
	XCT RH2DTO(P1)		;WRITE REG
	MOVEI T1,4		;DELAY **TEMP**
	SOJG T1,.		; **TEMP**
CHST2:	LDB T2,CSYPIA		;GET PI ASSIGNMENT
	IOR T2,Q2		;SET ATTENTION ENABLE IF DECIDED ABOVE
	XCT RH2CNO(P1)		;DO CONO
	RETSKP			;INDICATE SUCCESS
	SUBTTL Channel Utility Routines -- Generate CCW

;ROUTINE TO GENERATE A CHANNEL XFER WORD FOR THE RH20
;CALL - C(T1) := MODE,,+COUNT(1B0 IF BACKWARDS) , C(T2) := PHYSICAL-ADDRESS
;RETURNS+1(ALWAYS):
;T1/ CCW FOR THIS TRANSFER
;NOTE: THE MAXIMUM TRANSFER WHICH WILL ALWAYS WORK IS 1 PAGE.
;	THE CALLER IS EXPECTED TO WORRY ABOUT PAGE CROSSING PROBLEMS

RH2CCW:	PUSH P,T1		;SAVE ARGUMENT
	HRRZ T3,T1		;GET WORD COUNT
	HLRZS T1		;GET MODE IN CORRECT PLACE
	TRZ T1,(1B0)		;CLEAR BACKWARDS BIT FROM MODE
	CAIN T1,IRMWRD		;SPECIAL CASE CHECK FOR COMMON CASE
	JRST RH2CW1		;IS WORD MODE, DO IT FAST
	SKIPLE T1		;CHECK MODE FOR LEGALITY
	CAILE T1,IRMMAX		; ...
	JRST [	BUG.(CHK,PH2IHM,PHYH2,SOFT,<PHYH2 - Illegal hardware mode - word mode assumed>,,<

Cause:	The routine RH2CCW was called to generate a channel transfer word, and
	one of it's arguments is the data mode to use.  But the data mode
	supplied was illegal.
>,,<DB%NND>)			;[7.1210] 
		MOVEI T1,IRMWRD	;ASSUME WORD MODE
		JRST .+1]
	IDIV T3,MODTAB(T1)	;CONVERT TO WORDS
	SKIPE T4		;ROUND?
	AOS T3			;YES
RH2CW1:	POP P,T4		;GET ARGUMENT BACK
	MOVSI T1,(CHXFR)	;BUILD CCW
	STOR T3,CHCNT,T1	;STORE COUNT IN T1
	STOR T2,CHADR,T1	;STORE ADDRESS IN T1
	SKIPGE T4		;BACKWARDS?
	TLO T1,(CHREV)		;YES
	RET			;RETURN

;RH2CCA - EXTRACT THE PHYSICAL MEMORY ADDRESS FROM A CCW TRANSFER WORD.
;ARGUMENT:
;  T1/	CCW WORD
;RETURNS:
;  T1/	ADDRESS, OR ZERO IF NONE


RH2CCA:	LOAD T1,CHADR,T1	;GET PHYSICAL ADDRESS FROM CCW
	RET			;DONE
	SUBTTL Channel Utility Routines -- Check For Errors

;ROUTINE TO DETERMINE IF ANY CHANNEL DEPENDENT ERROR OCCURED.
;NOTICE:  CONI OVERRUNS (LONG WORD COUNTS) ARE IGNORED IF THE TRANSFER WAS
;TO A DISK AND THE LENGTH OF THE TRANSFER WAS NOT AN EXACT MULTIPLE OF
;THE SECTOR SIZE.  (IN THIS CASE, WE EXPECT THE LONG WORD COUNT).
;RETURN +1 IF ERROR , +2 IF NONE


CKERR::	MOVE T2,CDBCNI(P1)	;GET CONI AT INTERRUPT
	ANDI T2,CI.ERR		;ANY ERRORS?
	HRRZ T1,CDBICP(P1)	;CHECK CHANNEL
	SKIPN T1,1(T1)		;GET STATUS WORD 1
	JUMPE T2,RSKP		;IF NO LOGOUT AND  NO  CONI ERRS, GOOD XFR
	JUMPN T2,[CAIN T2,CI.OVR ;CONI ERRORS, ONLY OVERRUN?
		TXNN T1,CS1SWC	;AND WORD LENGTH ERROR FROM LOGOUT?
		CALL CKERR1	;NO, FLAG AN ERROR
		JRST .+1]	;PROCEED
	TXNE T1,CS1NSE		;SBUS ERROR?
	TXNE T1,CS1MPE!CS1NXM!CS1RHE!CS1OVR ;OR OTHER DEFINITE ERRORS?
	JRST [	TXNE T1,CS1MPE	;YES, A PARITY ERROR?
		AOS CDBPAR(P1)	;YES - NOTE
		TXNE T1,CS1NXM	;NONEXISTANT MEMORY?
		AOS CDBNXM(P1)	;YES - NOTE
		TXNE T1,CS1OVR	;AN OVERRUN?
		AOS CDBOVR(P1)	;YES - NOTE
		CALL CKERR1	;INDICATE SOME ERROR HAPPENED
		JRST .+1]	;AND CONTINUE WITH LENGTH ANALYSIS
	MOVX T2,CS1LWC!CS1SWC	;WORD COUNT ERROR BITS
	MOVE T3,UDBSTS(P3)	;GET STATUS BITS
	TXNE T3,US.TAP		;MAGTAPE?
	TXZ T2,CS1LWC		;YES - IGNORE RECORD SHORTER THAN BUFFER
	TDNN T1,T2		;LENGTH ERROR?
	JRST CKERR2		;NO - CHECK COUNT FROM LOGOUT AREA
	TXNN T1,CS1LWC		;RECORD TOO SHORT?
	TXNN T3,US.DSK		;OR NOT A DISK?
	JRST CKERR3		;YES, THEN MARK THE ERROR
	CALL PHYCNT		;GET LENGTH OF TRANSFER WE TRIED
	MOVEI T2,PGSIZ		;AND SIZE OF A PAGE
	MOVE T3,UDBSIZ(P3)	;GET POINTER TO SIZE TABLE
	IDIV T2,SECPAG(T3)	;COMPUTE LENGTH OF DISK SECTOR
	TRNE T1,-1(T2)		;IS THE LENGTH ERROR TO BE EXPECTED?
	JRST CKERR2		;YES, THAT'S OK THEN
CKERR3:	MOVX T1,IS.RTL		;FLAG LENGTH ERROR IN IORB
	IORM T1,IRBSTS(P4)	; ...
CKERR1:	MOVX T2,IS.DVE		;DECLARE A DEVICE ERROR
	IORM T2,IRBSTS(P4)	; ...
	RET
CKERR2:	MOVX T1,IS.DVE		;WERE ANY ERRORS DETECTED ALREADY?
	TDNE T1,IRBSTS(P4)	; ???
	RET			;YES - ERROR
	SKIPL 0(P4)		;CHECK FOR SHORT IORB
	RETSKP			;RETURN OK FOR LONG ONES
	HRRZ T1,CDBICP(P1)	;GET ADDRESS OF LOGOUT
	MOVE T1,2(T1)		;GET ADDRESS OF LOGOUT DONE
	MOVEI T4,-CST5(P4)	;GET ADDRESS TO FINISH AT
	LOAD T3,LG2DBP,T1	;PAGE NUMBER FROM LOGOUT
	SOSL T3			;[8855] Get page (off by one)
	ANDX T3,<PHCPNO_<-PGSFT>> ;[8855] Retain modulo 22 bits (but not if page 0)
	CAMN T3,T4		;[8855] Better be the same
	IFSKP.			;[8855] If not,
	  LDB T1,IRYFCN		;[8855] Get the function code
	  CAIN T1,IRFRVC	;[8855] Read validity?
	  AOSE T3		;[8855] Was it for page 0 (skip function)?
	  BUG.(HLT,ILLGO,PHYH2,HARD,<Invalid channel logout>,,<

Cause:	The routine CKERR was called to check for channel errors after an I/O
	operation.  The operation supposedly succeeded according to the IORB
	status bits.  But in verifying for a short style IORB that the I/O was
	done correctly, the page number contained in the channel logout area
	did not match the number of the page on which the IORB wanted to
	perform I/O.

Action:	This is usually caused by a RH20 or drive problem.  Have Field Service 
	check the hardware, particularly the RH20 and RP0x DCL.
>)				;[8855]
	ENDIF.			;[8855]
	RETSKP			;[8855] Page matches or page 0
;ROUTINE TO GET CONI AND DATAI'S ON ERROR
;RETURNS T1=CONI, T2=PTCR, T3=PBAR
ERRCNI::HRRZ T1,CDBICP(P1)	;GET CHANNEL LOGOUT AREA
	DMOVE T2,(T1)		; CS0,1
	DMOVEM T2,CDBCS0(P1)	;SAVE
	TXNE T3,CS1NSE		;A NON-SPECIFIC MEMORY ERROR?
	TXNE T3,CS1MPE!CS1NXM	;ANY MEMORY ERRORS?
	CALL [	JUMPGE T3,R	;IF NO STATUS, NO REPORT
		SAVET		;YES. SAVE TEMPS
		MOVE T2,T3	;COPY STATUS 1
		MOVE T3,2(T1)	;GET UPDATED CCW
		CAMN T3,CDBCS2(P1) ;PREVIOUS ERROR ON SAME PAGE?
		CAME T2,CDBCS0(P1) ;AND A MEM ERROR ALSO?
		SKIPA		;NO. REPORT THIS ONE THEM
		RET		;YES. NO REPOORTING RETRIES
		HRRZ T1,CDBADR(P1) ;GET CHANNEL #
		LSH T1,2	;*4
		ADDI T1,<RH2.0>_<11-35>
		CALLRET APRRPT]	;AND DO REPORT
	MOVE T2,2(T1)		;GET CS2
	MOVEM T2,CDBCS2(P1)	;SAVE
	MOVE T1,(T1)		;GET ICCW
	TLNN T1,(CHXFR)		;IF NOT A JUMP,
	JRST ERCNI1		;DONT TRY FOR CCWS
	LOAD T1,CHADR,T1	;GET ADDRESS PART OF JUMP
	LSH T1,-PGSFT		;AS A PAGE
	PIOFF			;INTERLOCK WINDOW
	CALL MAPRCA		;MAP THIS PAGE
	HRRZ T2,CDBICP(P1)	;GET CHAN BLOCK AGAIN
	MOVE T3,(T2)		;GET JUMP CCW BACK
	ANDI T3,777		;GET ADDRESS WITHIN PAGE
	ADD T3,T1		;GET INDEX INTO WINDOW PAGE
	MOVE T4,(T3)		;GET FIRST POSSIBLE CCW
	MOVEM T4,CDBCC1(P1)	;SAVE IN CDB
	ADDI T3,1		;INCREMENT POINTER
	MOVEI T4,0		;DONT STORE GARBAGE IF OVERFLOW
	TRNE T3,777		;STILL WITHIN WINDOW BOUND?
	MOVE T4,(T3)		;YES - FETCH SECOND POSSIBLE CCW
	MOVEM T4,CDBCC1+1(P1)	;SAVE IN CDB
	CALL UNMRCA		;FREE WINDOW
	PION			;ALLOW INTERRUPTS AGAIN
ERCNI1:	MOVSI T2,(DO.BA1)	;READ PRIMARY BLOCK ADDRESS REGISTER
	CALL RDREGX
	MOVE T4,T1		;SAVE BAR IN T4
	MOVSI T2,(DO.CT1)	;READ PRIMARY TRANSFER CONTROL REGISTER
	CALL RDREGX
	MOVE T2,T1		;INTO T2
	MOVE T3,T4		;GET BAR INTO T3
	MOVE T1,CDBCNI(P1)	;GET CONI
	RET
	SUBTTL Channel Utility Routines -- Compute Number of Device Blocks

;BLKCNT - ROUTINE TO COMPUTE NUMBER OF DEVICE BLOCKS NEEDED TO DO I/O
;  T1/	END OF TRANSFER LIST,,BEGINNING OF TRANSFER LIST
;  P3/	UDB
;  P4/	IORB
;RETURNS+1(ALWAYS):
;  T1/	NUMBER OF DEVICE BLOCKS NEEDED FOR THIS TRANSFER LIST


BLKCNT:	MOVX T2,US.TAP		;TAPE?
	TDNE T2,UDBSTS(P3)	; ???
	JRST BLKCT1		;YES
	HLRZ T2,T1		;GET TAIL OF CCW LIST
	SUBM T1,T2		;SUBTRACT TO GET NEGATIVE LENGTH OF LIST
	HRLZ T2,T2		;START BUILDING AOBJN POINTER
	HRR T2,T1		;INSERT HEAD ADDRESS TO FINISH IT
	SETZ T3,		;INITIALIZE TOTAL
BLKCNL:	MOVE T1,(T2)		;GET NEXT CCW WORD
	LOAD T1,CHCNT,T1	;EXTRACT WORD COUNT
	ADDB T1,T3		;ADD INTO TOTAL
	AOBJN T2,BLKCNL		;LOOP OVER ALL CCW WORDS
	MOVE T2,UDBSIZ(P3)	;GET POINTER TO DISK SIZE TABLE
	IMUL T1,SECPAG(T2)	;MULTIPLY BY NUMBER OF SECTORS IN A PAGE
	ADDI T1,PGSIZ-1		;ROUND UP IF DOING PARTIAL SECTORS
	LSH T1,-PGSFT		;DIVIDE BY PAGE SIZE TO GET SECTORS NEEDED
	RET			;DONE

BLKCT1:	MOVEI T1,1		;MAGTAPE IS ALWAYS 1
	RET
	SUBTTL Channel Utility Routines -- Reverse CCW List

;REVCCW - ROUTINE TO REVERSE THE CHANNEL IOWD LISTS FOR REREAD IN OPPOSITE DIRECTION
;  T2/	WORDCOUNT OF RECORD
;  P4/	IORB
;RETURNS+1(ALWAYS):
;T1/ORIG LH OF CHANGED IOWD,,ITS ADDRESS IF IT GOT CHANGED (CHLST LIT, WDCNT CHANGED)
;  AND IOWD LIST SET UP TO READ IN THE OPPOSITE DIRECTION

REVCCW::JUMPE T2,[SETZ T1,
		  RET]		;WORDCOUNT OF 0 IS HIGHLY ILLEGAL
	SAVEQ			;NEED SOME ACS
	SETZ Q2,		;Q2 WILL POINT AT CHANGED IOWD
	HRRZ T3,IRBXFL(P4)	;GET START OF LIST
REVCC1:	SKIPN T1,(T3)		;GET AN IOWD
	SOJA T3,REVCC4		;UNTERMINATED LIST, ENDS AT PREVIOUS IOWD
	LOAD T4,CHCNT,T1	;GET WORDCOUNT OF IOWD
	CAMLE T4,T2		;LAST IOWD?
	JRST REVCC2		;YES, IO LIST IS TOO LONG. FIX IT
	SUB T2,T4		;ACCOUNT FOR THE WORDS IN THIS IOWD
	JUMPE T2,REVCC3		;LIGHT CHLST IF IOWD FINISHES THE RECORD
	TLNE T1,(CHLST)		;NO. END OF LIST (RECORD TOO LONG)?
	JRST REVCC4		;YES, WE'RE AT END. REVERSE THEM
	AOJA T3,REVCC1		;NOT AT END. TRY NEXT IOWD
REVCC2:	STOR T2,CHCNT,T1	;FIX IOLIST - SET CORRECT LENGTH
REVCC3:	TLO T1,(CHLST)		;INDICATE IT IS THE LAST IOWD
REVCC4:	MOVE Q2,(T3)		;SAVE ORIGINAL IOWD (LH)
	HRR Q2,T3		;SAVE ITS ADDRESS
	MOVEM T1,(T3)		;SAVE MODIFIED IOWD WHERE THE RH20 WILL SEE IT
	HRRZ T2,IRBXFL(P4)	;POINT T2 AT START OF LIST
REVCC5:	CAML T2,T3		;HAVE A PAIR OF IOWDS TO EXCHANGE?
	JRST REVCC6		;NO, AT A SINGLE IOWD (MIDDLE), OR DONE
	MOVE Q1,(T3)		;GET LAST IOWD
	MOVE T1,(T2)		;GET 1ST IOWD
	TLZE Q1,(CHLST)		;LAST IOWD?
	TLO T1,(CHLST)		;YES, LIGHT BIT IN CORRESPONDING NEW IOWD
	CALL REVIOW		;SET IT FOR READ OPPOSITE
	MOVEM T1,(T3)		;AND SAVE AWAY
	MOVE T1,Q1		;GET LAST IOWD
	CALL REVIOW		;REVERSE IT
	MOVEM T1,(T2)		;AND SAVE
	SUBI T3,1		;POINT AT NEXT TO LAST
	AOJA T2,REVCC5		;POINT AT 2ND, AND REVERSE NEXT PAIR
REVCC6:	CAME T2,T3		;EVEN NO OF IOWDS?
	JRST REVCC7		;YES, DONE
	MOVE T1,(T2)		;NO, GET MIDDLE IOWD (OR ONLY ONE)
	CALL REVIOW		;REVERSE IT
	MOVEM T1,(T2)		;SAVE UPDATED IOWD
REVCC7:	MOVE T1,Q2		;RETURN VALUE IN T1
	RET			;AND WE'RE DONE
;REVERSE 1 IOWD
REVIOW:	LOAD T4,CHCNT,T1	;GET COUNT OF IOWD
	TLCE T1,(CHREV)		;REVERSE DIRECTION
	JRST [SUBI T1,-1(T4)	;WAS REVERSE, SET FOR FORWARD
	      RET]
	ADDI T1,-1(T4)		;WAS FORWARD, POINT AT END
	RET
	SUBTTL Interrupt Routine

;ENTER FROM PHYSIO W/ C(P1) := CDB CAUSING INTERRUPT.

RH2INT:	XCT RH2DTI(P1)		;GET REGISTER RH WAS CONNECTED TO
	TLZ T1,007770		; CLEAR UNNEEDED BITS
	MOVEM T1,CDBRST(P1)	;SAVE FOR EXIT SEQUENCE TO RESTORE (DATA0 RH,CDBRST)
	XCT RH2CNI(P1)		;GET CONI
	MOVEM T1,CDBCNI(P1)	;AND SAVE FOR ERROR LOGGING, ETC.
	TRNN T1,CI.RAE		;IS RAE SET?
	JRST RH2IN1		;NO - GO ON
	MOVE T2,T1		;COPY CONI
	XCT RH2DTI(P1)		;GET DATAI
	HRRZ T3,CDBADR(P1)	;GET CHANNEL ADDR
	BUG.(CHK,P2RAE3,PHYH2,HARD,<PHYH2 - Register access error on done or ATN interrupt>,<<T1,DATAI>,<T2,CONI>,<T3,CHAN>>,<

Cause:	The routine PHYINT was called to process an interrupt for the RH20, and
	a check was made to see if a register access error occured, and it did.
	This is almost always due to a hardware malfunction.  It can also
	happen when a RP06 LAP (Logical Address Plug) is removed or inserted.

Action:	Call Field Service if this is seen unless RP06 LAPs are being removed
	or inserted.

Data:	DATAI - The result of a DATAI done after the error was detected
	CONI - The CONI which showed the register access error
	CHAN - The channel number
>,,<DB%NND>)			;[7.1210] 
	CALL CLRRAE		;CLEAR RAE
	MOVE T1,CDBCNI(P1)	;RECOVER CONI
RH2IN1:	MOVEI Q1,0		;INITIAL UNIT #
	TRNN T1,CI.ATN		;ANY ATTENTIONS?
	JRST NOATTN		;NO
	MOVSI T2,(DO.AS)	;SET TO READ ATTENTION SUMMARY REGISTER
	CALL RDREGX		; READ (ANY UNIT WILL DO)
	ANDI T1,377		;MASK OUT IMPOSSIBLE BITS
	TRNN T1,377		;ANY ATTENTION ON?
	JRST NOATTN		;NO - CHECK DATA TRANSFER
ATCHKN:	LSHC T1,-1		;SHIFT 1 BIT OVER
	JUMPGE T2,ATCHK2	;JUMP IF NOT THIS UNIT
	PUSH P,T1		;SAVE REMAINDER
	HRRZ T1,Q1		;GET UNIT #
	CALL SETUDB		;SET UP P3 := UDB ADDRESS, T2 := DISPATCH
	JUMPE P3,ATNXU		;SPURIOUS INTERRUPT IF NO UNIT THERE
	SETZ P4,		;P4=0 IF NO ERRORS
	CALL UDSATN(T2)		;INFORM LOWER LEVEL
				;SETS LH(Q1) TO -1 IF POS DONE INTERRUPT
	 JRST ATCHK0		;NORMAL RETURN
	POP P,T1		;"REALLY-A-TRANSFER-DONE-INTERRUPT" RETURN
	JRST XFR3		; (TM78 SENSE AFTER IO). CLEAN UP XFER
ATCHK0:	JUMPN P4,ATNIRB		;JUMP IF IORB DONE OR ERROR
ATCHK1:	POP P,T1		;RESTORE ATTENTION REGISTER
ATCHK2:	SKIPE T1		;DONE IF ZERO
	AOJA Q1,ATCHKN		;INCR UNIT # AND TRY NEXT

NOATTN:	MOVE T1,CDBCNI(P1)	;GET CONI AT INTERRUPT
	SKIPL T4,CDBXFR(P1)	;TRANSFER IN PROGRESS?
	JRST XFR		;YES - ANALYZE
	TRNE T1,CI.DON		;IS DONE UP NOW?
	JRST BADDON		;EVIL EVENT
NOATT1:	HLLE P4,Q1		;NO TRANSFER, SET P4=-1 OR 0
	RETSKP			;AND LET PHYSIO DO ITS THING
XFR:	TRNN T1,CI.DON		;IS CONTROLLER BUSY?
	JRST [	SETZ P4,	;YES, MUST BE FROM ERRPSI (PHYRP4)
		RETSKP]		; SO JUST DISMISS THE INTERRUPT
	SKIPLE WREQ		;NEED TO CHECK FOR CHANNEL WRITE PARITY ERRORS?
	CALL CKCWP		;YES, DO SO
	MOVSI T2,(DO.CT1)	;READ RH20 CONTROL REGISTER
	CALL RDREGX
	LOAD T1,DI1UNS,T1	;GET UNIT RH20 IS TALKING TO
	CAME T1,T4		;RIGHT UNIT?
	JRST WRNGUN		;NO, TRY AGAIN
	CALL SETUDB		;YES, SET UP P3, T2
XFR1:	CALL UDSINT(T2)		;CALL INTERRUPT SERVICE
	 JRST XFR2		;INDICATE ERRORS
	JUMPLE P4,XFR3		;DON'T SET BITS IF NO IORB
	MOVX T1,CS.CWP		;GET CHANNEL WRITE PARITY BIT
	TDNE T1,CDBSTS(P1)	;CHANNEL WRITE PARITY ERROR DETECTED ON THIS CHANNEL?
	JRST XFR4		;YES, FLAG THEM AS SUCH
XFR3:	SETOM T1		;T1:=-1
	EXCH T1,CDBCAD+1(P1)	;GET OLD CONTENTS, CLEAR SECONDARY CCW ADDR WORD
	MOVEM T1,CDBCAD(P1)	; AND MOVE IT INTO THE PRIMARY WORD
	MOVSI T1,(CS.AC2)	;STACKED COMMANDS?
	TDNN T1,CDBSTS(P1)	; ??
	JRST [	CALL CLRCHL	;NO - RESET CHANNEL
		RETSKP]		;INDICATE NO ERRORS
	MOVEI T1,CO.DON		;YES - JUST CLEAR DONE
	CALL CHNCNO		; ...
	RETSKP
;HERE WHEN THERE WAS A CHANNEL WRITE PARITY ERROR DETECTED BY THE APR THAT
;WAS CAUSED BY THIS CHANNEL.  P4/IORB

XFR4:	MOVX T1,IS.DVE		; AND DEVICE ERROR BIT FOR IORB
	IORM T1,IRBSTS(P4)	;YES, SET DEVICE ERROR BIT

;HERE WHEN THERE HAS BEEN AN ERROR DETECTED AT A LOWER LEVEL

XFR2:	SETOM CDBCAD(P1)	;CLEAR PRIMARY CCW ADDRESS WORD
	SETOM CDBCAD+1(P1)	; AND SECONDARY
	MOVEI T1,CO.DEL		;DELETE STACKED COMMAND
	CALL CHNCNO		; ...
	MOVEI T1,CO.DON		;EXPLICITLY CLEAR DONE FIRST
	CALL CHNCNO		; ...
	CALLRET CLRCHL		;AND RESET ERRORS
;HERE IF AN IORB FINISHES DURING ATTENTION PROCESSING OR
;IF THERE WAS A SEEK ERROR

ATNIRB:	HRRZS P4		;CLEAR ERROR FLAG
	POP P,(P)		;SCRAP STACK
	RETSKP			;RETURN TO PHYSIO, NEVER SET CHAN ERR

;HERE IF WE GOT AN INTERRUPT FROM THE WRONG DRIVE
WRNGUN:	MOVE T1,T4		;DRIVE PHYSIO IS TALKING TO
	CALL SETUDB		;SET UP P3
	SKIPG P3		;CHECK TO SEE IF WE GOT A UDB (TAPES)
	BUG.(HLT,PH2IUA,PHYH2,HARD,<Wrong and inactive unit interrupted>,,<

Cause:	The routine RH2INT was called to handle an interrupt, and it determined
	that I/O had finished for a controller but that active controller can't
	be found.  This bug may also be seen in combination with PH2WUI
	BUGHLTs.

Action:	Have Field Service verify proper operation of the RH20s and other
	MASSBUS device hardware.
>)
	PUSH P,T2		;SAVE DISPATCH ADDRESS
	CALL SETIRB		;SET UP P4
	MOVE T2,IRBSTS(P4)	;DRIVE STATUS
	TLOE T2,(IS.WGU!IS.ERR)	;HAVE WE SEEN THIS ERROR BEFORE?
	JRST WRNGU1		;YES, BADNESS
	MOVEM T2,IRBSTS(P4)	;NO, SAVE ERROR BITS
	POP P,T2		;RETRIEVE DISPATCH ADDRESS
	JRST XFR1		;AND RETRY THE OPERATION

WRNGU1:	MOVEM T2,IRBSTS(P4)	;SAVE ERROR BITS
	LDB T2,IRYFCN		;IF THIS IS A WRITE WE'D BETTER HALT
	CAIE T2,IRFWRT		;BEFORE WE WIPE OUT SOME DISK
	CAIN T2,IRFWTF
	BUG.(HLT,PH2WUI,PHYH2,HARD,<Wrong unit interrupted>,,<

Cause:	The routine RH2INT was called to handle an interrupt, and it determined
	that I/O had finished for a unit.  The operation was a write operation.
	The CONI said that a particular unit completed the I/O, but that was
	not the unit to which the I/O was begun.  This BUGHLT occurs on the
	second such error for a particular IORB.  This bug may also be seen in
	combination with PH2IUA BUGHLTs.

Action:	Have Field Service verify proper operation of the RH20s and other
	MASSBUS device hardware.
>)
	JRST PA1		;RETURN AN ERROR
;HERE ON AN INTERRUPT FROM A NONEXISTANT UNIT.

ATNXU:	PUSH P,Q1		;SAVE REGISTER
	HRRZ Q2,Q1		;GET UNIT NUMBER
	CALL RH2UNS		;SELECT UNIT
	HRRZ Q2,Q1		;GET UNIT NUMBER
	ADD Q2,P1		;POINT TO CDB+UNIT
	MOVEM P3,CDBUDB(Q2)	;STORE NEW ENTRY
	POP P,Q1		;RESTORE REGISTER
	MOVEI T2,1		;CLEAR ATTENTION DIRECTLY
	LSH T2,(Q1)		;POSITION BIT
	HRLI T2,(DO.AS)		;IN ATTENTION SUMMARY REGISTER
	CALL WTREGX		;SPECIAL REGISTER, NEEDS NO UNIT
	JRST ATCHK1		;AND CONTINUE LOOKING


;HERE WHEN DONE IS UP AND THE CHANNEL IS NOT OCCUPIED.

BADDON:	HRRZ T2,CDBADR(P1)	;GET CHANNEL #
	BUG.(INF,PH2DNA,PHYH2,HARD,<PHYH2 - Done interrupt and channel not active>,<<T2,CHAN>>,<

Cause:	The routine RH2INT was called to handle an interrupt on the RH20 and
	the CONI said done was up, but no I/O transfer was in progress.  If an
	OVRDTA had previously occured, and the device finally responds, this
	BUGINF will happen.  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 - The channel number
>,,<DB%NND>)			;[7.1210] 
	LDB T2,CSYPIA		;GET PI ASSIGNMENT
	TRO T2,CO.RAE!CO.XFR!CO.ATE!CO.DON ;CLEAR RAE,XFRERR,DON.
	XCT RH2CNO(P1)		;SEND TO CHANNEL
	SKIPLE WREQ		;NEED TO CHECK FOR CHANNEL WRITE PARITY ERRORS?
	CALL CKCWP		;YES, DO SO
	SETOM CDBCAD(P1)	;CLEAR PRIMARY AND SECONDARY CCW
	SETOM CDBCAD+1(P1)	; ADDRESS WORDS
	JRST NOATT1
;ROUTINE TO CALL MEMSCN FOR EACH TRANSFER WORD IN THE CHANNEL COMMAND LIST
;IF A CHANNEL WRITE PARITY ERROR WAS DETECTED BY THE APR WHILE THIS
;TRANSFER WAS GOING.  FIRST CHECK TO SEE IF THE FUNCTION CODE FROM THE PTCR
;WAS FOR A WRITE TO MEMORY (READ FROM DEVICE) AND THEN FOLLOW THE CHANNEL
;COMMAND LIST CALLING MEMSCN FOR EACH TRANSFER WORD.
;CALL:
;    P1/CDB
;RETURN +1 ALWAYS WITH CS.CWP SET IN CDB+CDBSTS AND CDB+CDBPAR
;	   INCREMENTED IF A MEMORY ERROR WAS DETECTED BY MEMSCN
;PRESERVES THE T AND Q AC'S

CKCWP:	SAVET			;SAVE THE T AC'S
	MOVX T2,DO.CT1		;REGISTER SELECT FOR PTCR
	CALL RDREGX		;READ IT
	LOAD T1,DI1FNC,T1	;GET THE FUNCTION CODE
	CAIGE T1,70		;WAS THE FUNCTION A MEMORY WRITE (DEVICE READ)?
	RET			;NO, JUST RETURN
	SAVEQ			;SAVE THE Q AC'S
	SKIPG Q1,CDBCAD(P1)	;GET THE ADDRESS OF THE CHANNEL COMMAND LIST
	RET			;CONFUSION?
CKCWP1:	MOVE Q2,(Q1)		;GET THE NEXT WORD IN THE LIST
	TXNN Q2,CHXFR		;WAS THE OPCODE A TRANSFER?
	RET			;NO, DONE WITH THE LIST
	LOAD T1,CHADR,Q2	;GET THE ADDRESS FROM THE CCW
	JUMPE T1,CKCWP3		;NO ADDRESSES TO SCAN IF CHANNEL SKIP
	LOAD T2,CHCNT,Q2	;GET THE WORD COUNT TO SCAN
	TXNE Q2,CHREV		;WAS IT A REVERSE TRANSFER?
	SUBI T1,-1(T2)		;YES, SET THE ADDRESS TO THE BEGINNING
CKCWP2:	CALL MEMSCN		;SCAN THE WORDS DESCRIBED BY THIS POINTER
	 JRST [	MOVX T1,CS.CWP	;GET CHANNEL WRITE PARITY ERROR BIT
		IORM T1,CDBSTS(P1) ;SET IT IN THE CDB
		AOS CDBPAR(P1)	;INCREMENT THE PARITY ERROR COUNT IN THE CDB
		JRST CKCWP3]	;CONTINUE
CKCWP3:	TXNN Q2,CHLST		;TRANSFER AND HALT?
	AOJA Q1,CKCWP1		;NO, INCREMENT THE ADDRESS AND TRY NEXT ONE
	RET			;YES, DONE WITH THE LIST
	SUBTTL ECC Channel Logic


;THE FOLLOWING ROUTINES, AS IN SEVERAL OTHER PLACES, ASSUME THE
;CCW LIST IS EXACTLY ONE WORD LONG.

;HERE TO RETURN THE PHYSICAL ADDRESS OF THE START OF THE LAST BLOCK
;TRANSFERRED.  CALL:
;  P1/  CDB
;  P3/  UDB
;RETURNS:  +1: ALWAYS
;		T1/  PHYSICAL ADDRESS OF START OF LAST SECTOR TRANSFERRED


ECCADR::MOVEI T1,PGSIZ		;GET SIZE OF A PAGE
	HRRZ T2,UDBSIZ(P3)	;AND POINTER TO DISK SIZE TABLE
	IDIV T1,SECPAG(T2)	;COMPUTE SIZE OF A SECTOR
	MOVEI T2,-1(T1)		;CREATE MASK
	HRRZ T1,CDBICP(P1)	;GET STATUS AREA
	MOVE T1,2(T1)		;GET CS2, THE UPDATED CCW
	LOAD T1,CHADR,T1	;GET ADDRESS PART
	SUBI T1,1		;BACK UP INTO LAST SECTOR TRANSFERRED
	TRZ T1,(T2)		;MASK TO START OF SECTOR
	RET			;DONE



;HERE TO UPDATE THE CCW LIST TO TRANSFER ANY DATA AFTER THE SECTOR
;WHICH WAS ECC CORRECTED.
;
;	CALL ECCUCL
;RETURNS+1:
;	NO MORE DATA TO TRANSFER
;RETURNS+2:
;	UPDATED CCW AT CDBCCL(P1)
;T1/ NUMBER OF WORDS TRANSFERED INCLUDING SECTOR ECC CORRECTED


ECCUCL::HRRZ T4,CDBICP(P1)	;GET STATUS AREA
	MOVE T1,2(T4)		;GET UPDATED CCW
	LOAD T3,CHCNT,T1	;GET WORD COUNT
	JUMPE T3,R		;IF 0, ALL DONE.
	TLO T1,(CHXFR!CHLST)	;FORCE LAST TRANSFER
	MOVEM T1,CDBCCL(P1)	;STORE IN CDB
	SETZM CDBCCL+1(P1)	;CLEAR TAIL
	CALL PHYCNT		;GET IORB COUNT
	SUB T1,T3		;LESS WORDS TRANSFERRED
	RETSKP
	SUBTTL End of PHYH2
	TNXEND
	END