Google
 

Trailing-Edge - PDP-10 Archives - BB-H311D-RM - monitor-sources/phyh2.mac
There are 52 other files named phyh2.mac in the archive. Click here to see a list.
; 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

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY  BE  USED
;OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT  (c)  DIGITAL  EQUIPMENT  CORPORATION  1976, 1984.
;ALL RIGHTS RESERVED.


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

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 INITIALIZATION

RH2INI:	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
	CAME T1,[KLPMSK]	;IS IT ONE OF THEM?
	IFSKP.
	  CAMN Q1,[RH2.5]	;YES, IS THIS THE KLNI CHANNEL?
	   CALL NIINI		; YES, INITIALIZE IT
	  JRST RH2NXT		;THEY MAKE THEIR OWN CDBS
	ENDIF.
	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, RESET AND CHECK ENTRIES
;HERE ON A HUNG TRANSFER
;CALLED WITH PI OFF

RH2HNG:	MOVEI T1,0		;CONTROLLER ONLY RESET
	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


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

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.

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.
>)
	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

;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 mass-buss register, but
	the read failed due to a register access error from the RH20.
	This is almost always due to a hardware malfunction.

Action:	Call field service.

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.
>)
	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
;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 ERR WRITING REG>,<<T1,DATAI>,<T2,DATA>,<T3,CONI>,<T4,CHAN>>,<

Cause:	The routine WTREG was called to write a mass-buss register,
	but the write failed due to a register access error from the
	RH20.  This is almost always due to a hardware malfunction.

Action:	Call field service.

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.
>)
	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

;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
;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,HARD,<PHYRH2 - INVALID CHANNEL FUNCTION>,,<

Cause:	The routine CHSTRT was called to start IO 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
;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,HARD,<PHYH2 - ILLEGAL HDW 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.
>)
		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
;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
	SUBI T3,1
	CAME T3,T4		;BETTER BE THE SAME
	JRST [	LDB T1,IRYFCN	;GET THE FUNCTION CODE
		CAIN T1,IRFRVC	;READ VALIDITY?
		AOSE T3		;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 IO operation.  The operation supposedly succeeded according
	to the IORB status bits.  But then, in verifying for a
	short style IORB that the IO 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 IO.
>)
		RETSKP]		;HERE IF READ VALIDITY, AND PAGE 0
	RETSKP			;NO
;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
;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
;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 ACC ERR 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.

Action:	Call field service.

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.
>)
	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 IO had finished for a controller but
	now we can't find that active controller.
>)
	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 IO had finished for a unit.  The operation was a write
	operation.  The CONI said that a particular unit completed the IO, but
	that was not the unit to which the IO was begun.  This BUGHLT occurs on
	the second such error for a particular IORB.
>)
	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 IO transfer was
	in progress.  If an OVRDTA had previously occured, and the
	device finally responds, this BUGINF can happen.  This usually
	indicates a hardware failure.

Action:	Call field service.

Data:	CHAN/	The channel number.
>)
	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
	TNXEND
	END