Google
 

Trailing-Edge - PDP-10 Archives - BB-JR93N-BB_1990 - 10,7/mon/t78kon.mac
There are 10 other files named t78kon.mac in the archive. Click here to see a list.
TITLE	T78KON - RH20/TM78/TU78/TX79 DRIVER FOR TAPSER   V133
SUBTTL	T WACHS/TW/DPM/RJF	17-APRIL-90

	SEARCH	F,S,DEVPRM
	$RELOC
	$HIGH

;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 1980,1981,1982,1984,1986,1988,1990.
;ALL RIGHTS RESERVED.

.CPYRT<1980,1990>


XP VT78KN,133

	SALL

T78KON::ENTRY	T78KON
	;OFFSETS INTO TKBCCL
	TKBSCW==TKBCCL+1		;SAVED CHANNEL WORD
	TKBFLG==TKBCCL+2		;FLAGS FROM FNCTBL
	TKBCHR==TKBCCL+3		;CHARACTER (FRAME) COUNT
	TKBSCH==TKBCCL+4		;-1 IF A SCHEDULE CYCLE

	T78DMX==4			;MAXIMUM DRIVES PER KONTROLLER
	T78HDN==T78DMX-1		;HIGHEST DRIVE NUMBER ON KONTROLLER
	T78AMX==^D10			;MAX ASYNCH INTERRUPTS BEFORE
					; SHUTTING DOWN THE TM78
	T78IRE==INSVL.(.CCFTH,CC.OPC)!INSVL.(17,CC.WDC)!INSVL.(T78REG+30,CC.ADR)
					;IOWD TO READ ERROR LOG INFO

;DRIVER CHARARCTERISTICS
;	T78	= T78CNF
;	MTA	= MAGTAPE
;	0	= MAXIMUM DEVICES IN SYSTEM (NO LIMIT)
;	K.T78	= KONTROLLER TYPE
;	T78DMX	= MAXIMUM DRIVES PER KONTROLLER
;	T78HDN	= HIGHEST DRIVE NUMBER ON KONTROLLER
;	MDSEC0	= SECTION FOR KDB/UDB
;	MDSEC0	= SECTION FOR DDB
DRVCHR	(T78,MTA,0,K.T78,T78DMX,T78HDN,MDSEC0,MDSEC0,<DR.XAD!DR.MCD!DR.DPU!DR.GCC!DR.DDN>)

	.ORG	TKBUDB		;START OF TM78 SPECIFIC DATA
T78UTB:! BLOCK	T78DMX		;TABLE OF POINTERS TO UDBS
T78UVA:! BLOCK	1		;USER IOWD
T78RRO:! BLOCK	1		;IOWD FOR RETRY OPPOSITE OR ZERO
T78ACT:! BLOCK	1		;COUNT OF CONTINUOUS ASYNC INTERRUPTS
T78XIW:! BLOCK	1		;IOWD TO READ ERROR LOG INFO
T78ROM:! BLOCK	2		;ROM REV LEVELS
T78IUM:! BLOCK	T78DMW		;IGNORE DRIVE MASK
T78NUM:! BLOCK	T78DMW		;NEW DRIVE MASK
T78KLN:!			;LENGTH OF KDB
	.ORG

	 .ORG	TUBLEN
T78ICS:! BLOCK	47
T78ISE:! BLOCK	1		;LAST WORD IN INITIAL STATISTICS
T78REG:! BLOCK	50
T78ESD:! BLOCK	1		;TEMP USED DURING ERROR SENSE
T78SNS:! BLOCK	1		;INDICATES A SENSE IS IN PROGRESS
T78ULN:!			;LENGTH OF UDB
	 .ORG


T78KDB:	KDBBEG	(T78,T78KLN)
	SETWRD	(KDBNAM,<SIXBIT/MT/>)	;KONTROLLER NAME
	SETWRD	(KDBIUN,<TKBUDB>)	;INITIAL POINTER TO UNITS
	SETWRD	(KDBCUN,<TKBUDB>)	;CURRENT POINTER TO UNITS
	SETWRD	(KDBPCC,<TKWCCL,,TKBCCL>) ;PHYSICALLY CONTIGUOUS CORE
	SETWRD	(KDBIUM,<T78IUM>)	;OFFSET TO IGNORE UNIT MASK
	SETWRD	(KDBNUM,<T78NUM>)	;OFFSET TO NEW UNIT MASK
	SETWRD	(KDBSTS,<INSVL.(1,KD.MPT)>) ;INITIALLY ONE PATH
IFN FTMP,<SETWRD (TKBFCT,<TKBICT##>)>	;FAIRNESS COUNTER FOR QUEUED I/O
	SETWRD	(T78XIW,<T78IRE>)	;IOWD TO READ ERROR LOG INFO
	KDBEND


T78UDB:	UDBBEG	(T78,T78ULN)
	SETWRD	(UDBNAM,<SIXBIT/MT/>)	;DRIVE NAME
	SETWRD	(UDBPCC,<20,,T78REG+30>);PHYSICALLY CONTIGUOUS CORE
	SETWRD	(TUBIEP,<-50,,T78ICS>)	;INITIAL ERROR POINTER
	SETWRD	(TUBFEP,<-50,,T78REG>)	;FINAL ERROR POINTER
	UDBEND

EQUATE	(LOCAL,0,<T78ULP,T78ULB>)
EQUATE	(LOCAL,CPOPJ##,<T78CMD,T78EDL,T78IDL,T78LOD>)

T78ICD==TAPICD##		;PROTOTYPE INTERRUPT CODE ADDRESS
T78ICL==TAPICL##		;PROTOTYPE INTERRUPT CODE LENGTH
T78INT==TAPINT##		;INTERRUPT SERVICE
T78ELG==TPELGX##		;MAKE AN ERROR LOG ENTRY

T78DSP:	DRVDSP	(T78,TAPCHN##,TDVDDB##,TDVLEN##,TPMDIA##)
	TPK	(T78,NO,16K)	;SERVICE DEPENDENT DISPATCH

T78CKT:	EXP	K.T78,0		;COMPATIBLE KONTROLLER TABLE

T78NBF:	TPNBF	(<SR,BR,SF,BF,RW,RU>) ;NON-BLOCKING FUNCTION MASK
	SUBTTL	PARAMETERS

	;DRIVE REGISTERS USED IN DATAO'S

	.DOCR==0B5		;DRIVE CONTROL REGISTER
	.DOICD==1B5		;INTERRUPT CODE (DATA XFER)
	   DO.ICD==77		;INTERRUPT CODE
	   DI.FCD==176000	;FAILURE CODE
	.DOFMT==2B5		;RECORD COUNT/FORMAT
	   DO.SER==100000	;SUPRESS ERROR RETRY
	   DO.RC1==4		;RECORD COUNT RIGHTMOST BIT
	.DOER==3B5		;ERROR REGISTER
	.DOAS==4B5		;ATTENTION SUMMARY
	.DOBC==5B5		;BYTE COUNT
	.DODT==6B5		;DRIVE TYPE
	.DOSR==7B5		;STATUS REGISTER
	   DI.RDY==100000	;READY
	   DI.PRS==40000	;PRESENT
	   DI.PE==4000		;PHASE ENCODED
	   DI.BOT==2000		;BOT
	   DI.FPT==400		;FILE PROTECTED
	   DI.AVL==200		;AVAILABLE
	   DI.MNT==40		;IN MAINTENANCE MODE
	.DOSN==10B5		;SERIAL NUMBER
	.DODG==11B5		;DIAGNOSTIC
	.DODG2==12B5		;DIAGNOSTIC
	 ICNREG==13
	.DOICN==13B5		;INTERRUPT CODE (NON DATA-XFER)
	   DI.DRV==1400		;DRIVE NUMBER
	.DOND0==14B5		;NON DATA-XFER COMMAND, UNIT 0
	   DO.NDC==177400	;COUNT FIELD
	   DO.NDF==77		;FUNCTION CODE
	   NDCSHF==^D8		;SHIFT VALUE FOR COUNT
	.DOND1==15B5		;COMMAND, UNIT 1
	.DOND2==16B5		;COMMAND, UNIT 2
	.DOND3==17B5		;COMMAND, UNIT 3
	.DOIA==20B5		;INTERNAL ADDRESS
	.DOTMS==21B5		;TM STATUS
	   DI.TMR==1B20		;TM READY
	   DO.TMC==1B21		;TM CLEAR
	   DO.HLA==1B26		;HOLD ACKNOWLEDGED
	   DO.HLD==1B27		;HOLD
	;DRIVE FUNCTIONS
	DF.NOP==3		;NO-OP
	DF.UNL==5		;UNLOAD
	DF.REW==7		;REWIND
	DF.SNS==11		;SENSE
	DF.DSE==13		;DATA SECURITY ERASE
	DF.WTM==15		;WRITE TAPE MARK (PE)
	DF.SPF==21		;SPACE FORWARD RECORD
	DF.SPR==23		;SPACE REVERSE RECORD
	DF.SFF==25		;SPACE FORWARD FILE
	DF.SRF==27		;SPACE REVERSE FILE
	DF.SFE==31		;SPACE FORWARD RECORD OR FILE
	DF.SRE==33		;SPACE REVERSE RECORD OR FILE
	DF.ERG==35		;ERASE 3 INCHES OF TAPE (PE)
	DF.CLF==41		;CLOSE FILE (PE) - 2 EOFS, BACKSP 1
	DF.LET==45		;SKIP TO LOGICAL EOT

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

;BYTE POINTER TO FAILURE CODE IN EXTENDED SENSE DATA
TUYECD:	POINT	8,T78REG+30(U),35
	SUBTTL	START IO
;HERE TO START IO
T78SIO:	PUSHJ	P,CHKIRB##	;GET IORB FOR THIS OP
	  JRST	TAPDIS##	;NONE, GO AWAY
	PUSHJ	P,SAVE1##	;SAVE P1
	LDB	T4,PRBFCN##	;FUNCTION
	SKIPN	T78RRO(W)	;ARE WE IN RETRY OPPOSITE?
	JRST	T78SI1		;NO
	CAIN	T4,RB.FRB	;YES, TRYING TO DO A REVERSE READ?
	MOVEI	T4,RB.FRD	;YES, RETRY FORWARD
	CAIN	T4,RB.FCR	;DOING A CORRECTIVE READ?
	MOVEI	T4,RB.FRB	;YES, READ BACKWARDS
T78SI1:	SKIPN	P1,FNCTBL(T4)	;LEGAL?
	JRST	ILLFNC		;NO
	SKIPGE	T2,TRBRCT(T1)	;IF POSITIVE IN ERROR RECOVERY
	MOVEM	T2,T78UVA(W)	;REAL IOWD - SAVE IT
	SKIPGE	T78ACT(W)	;DID WE SHUT OFF TM TO PREVENT EXCESSIVE INTERRUPTS?
	PUSHJ	P,CLRHLD	;YES, CLEAR HOLD SO WE CAN TALK TO IT AGAIN
	SETZM	T78ACT(W)	;CLEAR ASYNC INTERRUPT COUNT
	LDB	T4,PRBDEN##	;GET DENSITY
	CAIGE	T4,RB.D16	;TOO LOW?
	MOVEI	T4,RB.D16
	CAILE	T4,RB.D62	;TOO HIGH?
	MOVEI	T4,RB.D62
	DPB	T4,PRBDEN##	;TELL THE REST OF THE WORLD
	CAIN	T4,RB.D62	;6250?
	TLNN	P1,(TB.WRT)	;YES, WRITE?
	JRST	T78SI2		;NO
	TROA	P1,WT.GCR	;YES, SET 6250 IN FUNCTION
ILLFNC:	MOVE	P1,FNCNOP	;ILLEGAL FNCN - JUST GET AN INTERRUPT
	JRST	T78SI2		;GO START THE OPERATOIN
SENSE:	MOVEM	P1,T78SNS(U)	;TELL INTERRUPT SERVICE WE ARE DOING A SENSE
T78SI2:	PUSH	P,T1		;SAVE T1
	MOVEI	T1,CO.MBE	;ENABLE THE MASSBUS, DISABLE INTERRUPTS
	XCT	KDBCNO(W)
	POP	P,T1		;RESTORE T1
	MOVE	T3,UDBPDN(U)	;PHYSICAL DRIVE NUMBER
	SKIPE	T78SNS(U)	;SENSE?
	JRST	[MOVEI	T2,DF.SNS ;YES, DO IT
		 JRST	T78SI3]
	JUMPL	P1,T78SI4	;NO, GO IF A DATA OP
	MOVE	T2,@IRBACC(T1)	;SENSE OR NON-DATA. GET COUNT
	LSH	T2,NDCSHF	;POSITION IT
	ANDI	T2,DO.NDC	;MASK OUT GARBAGE
	TRO	T2,(P1)		;SET FUNCTION FROM TABLE
T78SI3:	ADDI	T3,<(.DOND0)>_-14 ;GET RIGHT REGISTER (14=DRIVE 0, 15=DRIVE 1,...)
	DPB	T3,[POINT 4,T2,5] ;SAVE REGISTER IN FUNCTION
	JRST	T78SI6		;GO START UP THE WORLD
;HERE TO START A DATA OPERATION
T78SI4:	LDB	T4,PRBMOD##	;GET MODE
	SKIPGE	T4,MODTBL(T4)	;LEGAL?
	JRST	ILLFNC		;NO
	MOVEI	T2,(T4)		;YES. SET MODE IN COMMAND
	TRO	T2,DO.RC1(T3)	;RECORD COUNT=1, SET UNIT
	TLNE	S,IOSRTY##	;IF NOT DOING RETRIES
	TRO	T2,DO.SER	;INFORM THE HARDWARE
	HRLI	T2,(.DOFMT)	;TELL MODE, COUNT, UNIT
	PUSHJ	P,WTMBR##
	MOVS	T2,T78UVA(W)	;GET WORD COUNT
	HLRZS	T4		;NO OF FRAMES PER WORD
	TLOE	T2,-1		;DO WE ALREADY HAVE FRAME COUNT ?
	IMULI	T2,(T4)		;COMPUTE FRAME COUNT
	MOVNM	T2,TKBCHR(W)	;SAVE IN KDB
	MOVNS	T2		;+FRAME COUNT
	ANDI	T2,DO.ERD	;ONLY 16 BITS WORTH
	HRLI	T2,(.DOBC)
	PUSHJ	P,WTMBR##	;TELL BYTE COUNT REGISTER
	MOVE	T2,KDBICP(W)	;INITIAL CNTRL WORD ADDRESS
	HRRZ	T3,@IRBACC(T1)	;LOC OF FIRST IOWD
	TLO	T3,(INSVL.(.CCJMP,CC.OPC)) ;MAKE A JUMP TO IT
	MOVEM	T3,(T2)		;STORE IN ICWA
	HRRZ	T2,P1		;FUNCTION (READ/WRITE, PE/GCR)
T78SI5:	TDO	T2,[.DOSTC!DO.RCP!DO.SCS!DO.CNT]
T78SI6:	SKIPN	T78SNS(U)	;IF NOT DOING A SENSE
	MOVEM	T2,T78REG+5(U)	;SAVE FUNCTION IN UDB FOR SYSERR
	MOVE	T3,T2		;COPY FUNCTION WORD
	ANDI	T3,77		;MASK TO FUNCTION BYTE
	CAIE	T3,DF.SNS	;IF NOT DOING A SENSE,
	MOVEM	P1,TKBFLG(W)	;SAVE WHAT THE KONTROLLER IS DOING
	PUSHJ	P,WTMBR##	;START UP THE WORLD
	SKIPGE	P1		;DATA OP?
	PUSHJ	P,SETIVI	;YES, RESET INTERRUPT VECTOR ADDR
	PUSH	P,T1		;SAVE T1
	XCT	KDBCNI(W)	;CONI
	MOVE	T2,T1		;COPY RESULTS
	MOVEI	T1,TAPCHN##+CO.AIE+CO.MBE
	TRNE	T2,CI.RAE	;REGISTER ACCESS ERROR?
	MOVEI	T1,TAPCHN##+CO.MBE+CO.STP ;YES, GET TO INTERRUPT LEVEL NOW
	XCT	KDBCNO(W)	;NO, ENABLE FOR INTERRUPTS
	POP	P,T1		;RESTORE
	SKIPE	T78SNS(U)	;SENSE?
RTZER:	SETZ	T1,		;YES, ANOTHER INTERRUPT COMING
	POPJ	P,		;RETURN TO TAPSER
SUBTTL	CHECK FOR KONTROLLER BUSY


;CHECK FOR KONTROLLER BUSY
;CALL:	MOVE	W, KDB ADDRESS
;	MOVE	U, UDB FOR DRIVE TRYING TO SCHEDULE
;	PUSHJ	P,T78BSY
;	  <RETURN 1>		;BUSY
;	  <RETURN 2>		;NOT-BUSY
;	<RETURN 3>		;DON'T KNOW
;
;USES T1 AND T2

T78BSY:	MOVE	T1,KDBCHN(W)	;LOOK AT THE CHANNEL DATA BLOCK
	MOVE	T1,CHNTBP##(T1)	;SEE IF MORE THAN ONE KONT ON THE RH20
	AOBJN	T1,CPOPJ2##	;IF SO, THEN AVOID OVERHEAD & SAY "DON'T KNOW"
	PUSHJ	P,SAVE1##	;SAVE P1
	PUSH	P,U		;SAVE U
	MOVE	P1,KDBIUN(W)	;POINT TO START OF DRIVE TABLE

T78BS1:	SKIPE	U,(P1)		;GET A TUB ADDRESS
	PUSHJ	P,CHKIRB##	;SEE IF IT HAS A VALID IORB
	  JRST	T78BS2		;TRY ANOTHER DRIVE
	LDB	T2,PRBFCN##	;GET FUNCTION CODE
	MOVE	T2,BITTBL##	;NOT PICK UP THE ASSOCIATED BIT
	TDNN	T2,T78NBF	;NON-BLOCKING FUNCTION?
	POPJ	P,		;NO--KONT IS BUSY

T78BS2:	CAMGE	P1,KDBFUN(W)	;CHECKED ALL DRIVES?
	AOJA	P1,T78BS1	;LOOP BACK FOR ANOTHER
	JRST	UPOPJ1##	;RESTORE U AND RETURN KONT NOT BUSY
	SUBTTL	INTERRUPT PROCESSING

T78ISR:	PUSHJ	P,SAVE4##	;SAVE SOME ACS
	PUSHJ	P,SVMBR##	;SAVE CURRENT MBR FOR UUO LEVEL
	SETZ	P4,		;CLEAR TO GET TRBSTS FLAGS
	MOVE	P1,TKBFLG(W)	;GET COMMUNICATION/FLAGS WORD
	MOVE	P2,KDBCSO(W)	;GET TAPICD BLOCK ADDRESS
	MOVE	P2,TAPCII##(P2)	;GET CONI BITS AT INTERRUPT
	TRNE	P2,CI.RAE	;REGISTER ACCESS ERROR?
	JRST	NOATT1		;YES, HANDLE IT
	MOVSI	T2,(.DOAS)	;NO, READ ATTEN SUMMARY
	PUSHJ	P,RDMBR##
	ANDI	T2,377		;JUST REAL ATTENTIONS
	TDNN	T2,KDBUNI(W)	;ATTENTION FOR THIS KDB?
	JRST	NOATTN		;NO
	PUSHJ	P,ATTEN		;GO HANDLE IT
	  POPJ	P,		;ASYNC EVENT - RETURN 0 OR -1 TO TAPSER
	JUMPE	T1,INTREW	;REW COMPLETE IF T1=0
	SKIPN	T78SNS(U)	;COMPLETE A SENSE?
	TLNN	P1,(TB.DAT)	;NO, DATA OPERATION IN PROGRESS?
	JRST	CHEKIT		;SENSE OR NON-DATA
	TLO	P4,RB.SDE	;DATA OPERATION + ATTENTION - CANT HAPPEN
	JRST	DONE		;SO LIGHT AN ERROR AND RETURN
;HERE IF NO ATTENTIONS
NOATTN:	TRNN	P2,CI.DON	;DONE?
	JRST	RTZER		;NO, ERROR (NO ATTEN, NOT DONE = RH20 GOOFED)
NOATT1:	SKIPE	T1,TKBSCH(W)	;SCHEDULE CYCLE?
	JRST	SCHDON		;YES, TELL TAPSER ABOUT IT
	PUSH	P,T1		;SAVE T1
	MOVEI	T1,CO.CCD!CO.MBE;NO, CLEAR DONE
	XCT	KDBCNO(W)
	MOVEI	T1,CI.DON	;CLEAR IN INTERRUPT CONI WORD ALSO
	MOVE	T2,KDBCSO(W)
	ANDCAM	T1,TAPCII##(T2)
	POP	P,T1		;RESTORE T1
	MOVE	U,@KDBCUN(W)	;UNIT WE ARE TALKING TO
	SKIPE	T78SNS(U)	;DOING A SENSE?
	TLNN	P1,(TB.XSN)	;YES, AN EXTENDED SENSE?
	JRST	NOATT2		;NO
	MOVE	T2,TKBSCW(W)	;YES, RESTORE REAL CHAN GOTO WORD
	MOVEM	T2,@KDBICP(W)
	SETZM	TKBSCW(W)	;INDICATE WE DON'T HAVE A REAL IOWD ANY MORE
	PUSHJ	P,ATTEN3	;FINISH UP INTERRUPT PROCESSING
	  JRST	CLRCTL		;ASYNC
	JRST	CHEKIT		;KEEP ON TRUCKIN
NOATT2:	MOVSI	T2,(.DOICD)	;GET INTERRUPT CODE
	PUSHJ	P,RDMBR##
	MOVE	P3,T2		;WHERE ATTEN6 WANT IT
	PUSHJ	P,ATTEN6	;CHECK IT FOR GOODNESS
	  PJRST	CLRCTL		;ASYNC EVENT (!)
	TLNE	T4,RB.SER!RB.SED ;IF AN ERROR,
	JRST	CHEKIT		; DON'T BOTHER CHECKING CHANNEL FOR ERRORS
	MOVE	T3,KDBICP(W)	;GET LOC OF LOGOUT AREA
	HLL	P2,1(T3)	;GET RH20 LH FLAGS
	TLC	P2,(CS.NAE)
	TLNE	P2,(CS.SWC)	;IF SHORT WORDCOUNT (RECORD TOO LONG)
	TRZ	P2,CI.OVR	;THEN OVERRUN CAME UP ERRONEOUSLY
	TDNE	P2,[CS.ERR!CI.ERR] ;CHANNEL ERROR?
	JRST	CHNERR		;TOO BAD

CHEKIT:	LDB	T4,[POINT 4,P1,17] ;GET INDEX INTO FUNCTION TABLE
	HLLZ	P4,TRBSTS(T1)	;GET ERROR BITS
	TLNN	P1,(TB.ERA!TB.REW) ;ERASE OR REWIND?
	TLNE	P4,RB.SNM!RB.SAP ;NO, ANY TAPE MOTION
	JRST	NOTM		;DON'T UPDATE TUBREC/FIL
	MOVEI	T2,1		;ASSUME FORWARD
	TLNE	P1,(TB.REV)	;IS IT?
	MOVNI	T2,1		;NO
	ADDM	T2,TUBREC(U)	;UPDATE TUBREC
	LDB	T3,PRBFCN##	;GET IORB FUNCTION
	CAIE	T3,RB.FSF	;SKIP FILE?
	CAIN	T3,RB.FBF	;BACKSPACE FILE?
	TLO	P4,RB.STM	;SUCCESSFUL COMPLETION HERE NOT AN EXCEPTION
	HLLM	P4,TRBSTS(T1)	;POSSIBLY UPDATE IORB STATUS
	TLNN	P1,(TB.WTM)	;JUST WRITE AN EOF?
	TLNE	P4,RB.STM	; OR JUST SEE AN EOF?
	CAIA			;YES
	JRST	NOTM		;NO
	ADDM	T2,TUBFIL(U)	;UPDATE TUBFIL
	SETZM	TUBREC(U)	;AT 0TH RECORD
NOTM:	MOVSI	T2,TUSBOT	;ASSUME NOT AT BOT
	ANDCAM	T2,TUBSTS(U)
	TLNE	P4,RB.SBT	;ARE WE?
	IORM	T2,TUBSTS(U)	;YES, TELL THE REST OF THE WORLD
	PJRST	@INTABL(T4)	;THE LEAP OF FAITH
;SUBROUTINE TO HANDLE ATTENTION INTERRUPTS
;EXIT T1=IORB  OR T1=0 IF REWIND JUST FINISHED
;NON-SKIP IF ASYNCHRONOUS EVENT, SKIP-RETURN NORMALLY
ATTEN:	MOVSI	T2,(.DOICN)	;READ THE INTERRUPT CODE
	PUSHJ	P,RDMBR##
	MOVE	P3,T2		;SAVE IT (DISAPPEARS AFTER CLEARING ATTENTION)
	HRRZ	T2,KDBUNI(W)	;GET BIT FOR ATTENTIONS ON THIS UNIT
	HRLI	T2,(.DOAS)
	PUSHJ	P,WTMBR##	;CLEAR THIS ATTENTION, LEAVE ANY OTHERS ALONE
	LDB	T1,[POINT 2,P3,27] ;GET UNIT
	ADD	T1,KDBIUN(W)	;POINT AT RIGHT UDB
	SKIPE	U,(T1)		;SET UP U TO UDB
	JRST	ATTEN2		;INTERRUPT FROM UNKNOWN DRIVE

;HERE IF NO UDB IS FOUND FOR THE INTERRUPT ADDRESS
	LDB	T1,[POINT 5,P3,35] ;GET INTERRUPT CODE
	CAIE	T1,ICDND1	;IS IT ONE FOR WHICH THE ADDRESS ISNT VALID?
	CAIN	T1,ICDND2
	SKIPA	T1,KDBCUN(W)	;YES, BLAME IT ON THE CURRENT UNIT
	JRST	ATTE15		;NO,NEW UNIT
	SKIPN	U,(T1)		;SET U TO CURRENT UDB
	JRST	CLRINT
ATTEN2:	SKIPN	T78SNS(U)	;DOING A SENSE?
	JRST	ATTEN6		;NO
	MOVE	P1,T78SNS(U)	;SET P1 FOR THIS FUNCTION
	TLZN	P1,(TB.RRG)	;SENSE WHILE READING REGISTERS?
	JRST	ATTEN4		;NO, CARRY ON
	PUSHJ	P,RDREG2	;YES, READ REGS 7, 10, 11
	SKIPGE	T78ESD(U)	;SENSE AFTER AN RH20 ERROR?
	JRST	ATTEN3		;NO
	MOVE	T4,[IC.BST!RB.SED] ;YES, CAUSE AN ERROR BIT TO GET LIT IN IORB
	JRST	ATTEN9
ATTEN3:	MOVE	T4,T78ESD(U)	;RESTORE ERROR BITS
	TLNE	T4,(IC.XSN)	;NEED EXTENDED SENSE INFO?
	TLOE	P1,(TB.XSN)	;YES, HAVE WE DONE IT ALREADY?
	JRST	ATTEN9		;FINISH UP INTERRUPT
	JRST	ATTE14		;GO CRANK UP EXTENDED SENSE
ATTEN4:	MOVSI	T2,(.DOSR)	;READ THE STATUS REGISTER
	PUSHJ	P,RDMBR##
	JUMPL	P1,ATTEN6	;GO IF A DATA OP
	MOVSI	T4,TUSWTL##!TUSBOT## ;NON-DATA, CLEAR WRITE-LOCK BIT, BOT
	ANDCAM	T4,TUBSTS(U)
	TRNN	T2,DI.FPT	;SET IT AGAIN IF TAPE REALLY IS WRITE LOCKED
	TLZ	T4,TUSWTL##	;NOT WRITE-LOCKED
	TRNN	T2,DI.BOT
	TLZ	T4,TUSBOT##	;NOT AT LOAD-POINT
	IORM	T4,TUBSTS(U)
;	JRST	ATTEN6		;PUSH ON
;HERE ON NORMAL ATTENTION INTERRUPT
ATTEN6:	LDB	T2,[POINT 5,P3,35] ;GET INTERRUPT CODE
	CAIE	T2,ICDND1	;ASYNC INTERRUPT WHERE REGS NOT READ?
	CAIN	T2,ICDND2
	JRST	[MOVEI	T1,T78REG+7(U) ;YES. CLEAR OUT OLD INFO
		 SETZM	-1(T1)	   ; SO AS NOT TO CONFUSE FIELD-SERVICE
		 HRLI	T1,-1(T1)  ; SINCE WE CAN'T GET ANY OTHER INFORMATION
		 BLT	T1,T78REG+47(U)
		 MOVEM	P3,T78REG+6+ICNREG(U) ;SAVE INTERRUPT CODE
		 JRST .+1]
	CAILE	T2,MAXICD	;LEGAL?
	MOVEI	T2,0		;NO
	SKIPN	P3,T78RRO(W)	;DOING RETRY OPPOSITE?
	JRST	ATTEN8		;NO
	TLC	P1,(TB.REV)	;YES, THE OPERATION IS REALLY IN THE OTHER DIRECTION
	SETZM	T78RRO(W)	;EITHER WIN OR RETRY IN ORIGINAL DIRECTION - CLEAN UP
	PUSH	P,T2
	PUSHJ	P,CHKIRB##	;GET IORB
	  JRST	ATTEN7		;NONE (!)
	LDB	T3,PRBFCN##	;GET FUNCTION
	HLRZ	T2,TUBCHR(U)	;GET WORDCOUNT OF RECORD
	SKIPL	FNCTBL(T3)	;IF A DATA OPERATION
	JRST	ATTEN7		;NOT A DATA OP!
	HRRZ	T3,@IRBACC(T1)	;GET CHANNEL COMMAND
	PUSHJ	P,REVCCW##	;RE-REVERSE THE IO LIST
	HLLM	P3,(P3)		;RESTORE ORIGINAL LH OF CHANGED IOWD
ATTEN7:	POP	P,T2
ATTEN8:	SKIPL	T4,ICDTBL(T2)	;GET BITS/DISPATCH ADDRESS
	JRST	ATTEN9		;NO ERROR, KEEP ON
	SKIPE	TUBERR(U)	;ERROR. FIRST TIME WE'VE SEEN IT?
	TRNN	T4,RB.SAP	;YES. DOES TM REPOSITION ON THIS ERROR?
	JRST	ATTE13		;1ST TIME OR NO REPOS, READ REGISTERS
ATTEN9:	TLNN	T4,(IC.RRG)	;WIN WITH NO ERRORS?
	SKIPN	TUBERR(U)	;YES, IN ERROR RETRY?
	CAIA
	PUSHJ	P,RDREG3	;GOOD RETRY - READ WINNING REGISTERS
	TLNN	T4,(IC.ASY)	;ASYNC INTERRUPT?
	AOS	(P)		;NON ASYNC - SKIP RETURN
	TLNE	T4,(IC.DSP)	;DISPATCH ON THIS CONDITION?
	PJRST	(T4)		;YES, GO TO SUBROUTINE
ATTE10:	TLNN	T4,(IC.BST)	;NO, SET A BIT?
	TDZA	T4,T4		;NO
	HRLZS	T4		;YES
	PUSHJ	P,CHKIRB##	;NO, POINT T1 AT IORB
	  SETZ	T1,		;NO IORB
	MOVE	T2,TUBSTS(U)	;GET STATUS
	TLNE	T2,TUSREW##	;WAS IT REWINDING?
	JRST	ATTE11		;YES, PROBABLY ASYNC INTERRUPT AT BOT
	JUMPE	T1,ATTE12	;GO IF NO IORB
	IORM	T4,TRBSTS(T1)	;LIGHT BIT IN IORB
	POPJ	P,		;AND RETURN
;HERE IF TUSREW IS ON IN TUB
ATTE11:	JUMPE	T1,CPOPJ##	;AT BOT IF NO IORB
	LDB	T2,PRBFCN##	;IORB - IS IT THE REWIND?
	CAIE	T2,RB.FRU
	CAIN	T2,RB.FRW
	POPJ	P,		;YES. REW WHEN WE'RE AT BOT (IMMEDIATE DONE INTERRUPT)
	JRST	RTZER		;NO, ANOTHER IORB HAS BEEN QUEUED. WE'RE AT BOT

;HERE WITH NO IORB, TAPE WAS NOT REWINDING
ATTE12:	SOS	(P)		;NON-SKIP RETURN
	SETZB	T1,T78SNS(U)	;PROBABLY SENSE AFTER ON-LINE
	POPJ	P,		;RETURN WITH T1=0

;HERE ON AN ERROR WHICH REQUIRES READING THE DRIVE REGISTERS
ATTE13:	SETZM	T78RRO(W)	;CLEAN UP FLAGS
	PUSHJ	P,RDREGS	;READ REGS (7-10 AREN'T CORRECT)
	TLO	P1,(TB.RRG)	;INDICATE WHY WE'RE DOING THE SENSE
	MOVEM	T4,T78ESD(U)	;SAVE ERROR BITS FOR WHEN SENSE FINISHES
	PJRST	SENSE		;DO A SENSE SO WE CAN READ REGS 7-10

;HERE WHEN WE NEED TO START AN EXTENDED SENSE OPERATION TO READ ERROR INFO
ATTE14:	MOVEM	P1,T78SNS(U)	;UPDATED FLAGS WORD
	XMOVEI	T2,TKBCCL(W)	;WHERE TO DO THE SENSE
	MAP	T2,(T2)		;CONVERT TO PHYSICAL ADDRESS
	TLZ	T2,(MP.NAD)
	TLO	T2,(INSVL.(.CCJMP,CC.OPC)) ;MAKE AN RH20 JUMP WORD
	EXCH	T2,@KDBICP(W)	;SAVE CURRENT ICWA, SET UP JUMP TO TEMP
	MOVEM	T2,TKBSCW(W)
	MOVE	T2,T78XIW(W)	;IOWD TO READ SENSE BYTES INTO TUB
	ADDI	T2,(U)		;POINT AT RIGHT TUB
	HLLZM	T2,TKBCCL(W)	;SAVE WHERE ICWA POINTS
	MAP	T2,(T2)		;COMPUTE PHYSICAL ADDRESS
	TLZ	T2,(MP.NAD)	;CLEAR EXTRANEOUS BITS
	IORM	T2,TKBCCL(W)	;COMPLETE THE IOWD
	MOVE	T2,UDBPDN(U)	;PHYSICAL DRIVE NUMBER
	TRO	T2,DO.RC1	;SET UP FORMAT REGISTER
	HRLI	T2,(.DOFMT)	; ONLY NEEDS UNIT NUMBER
	PUSHJ	P,WTMBR##
	MOVEI	T2,DF.XSN	;FUNCTION IS EXTENDED SENSE
	PJRST	T78SI5		;GO CRANK IT UP AND RETURN 0 TO TAPSER

;HERE ON AN INTERRUPT OF A NEW (UNKNOWN) UNIT
ATTE15:	LDB	T1,[POINT 2,P3,27] ;DRIVE NUMBER
	MOVE	T1,BITTBL##(T1)	;TRANSLATE TO BIT REPRESENTATION
	IORM	T1,T78NUM(W)	;REMEMBER TO CONFIGURE LATER
	HRROS	KDBNUM(W)	;FLAG IT FOR THE REST OF THE WORLD TO SEE
	JRST	RTZER		;AND CHUCK THE INTERRUPT
;HERE ON READ INTERRUPT
INTRD:	MOVE	T2,TUBREC(U)	;SET MODE/DENSITY IF FILE 0, RECORD 1
	SKIPE	TUBFIL(U)       ;IN THE FIRST FILE?
	JRST	INTRD2		;NO, DON'T WORRY ABOUT MODE/DENSITY
	SOJG	T2,INTRD2	;YES, JUMP IF PAST 1ST RECORD
	SKIPN	T78SNS(U)	;SENSE DONE ALREADY?
	SKIPE	P4
	JRST	INTRD1		;YES, GO READ STATUS REGISTER
	TLO	P4,RB.SNM	;NO, LITE "NO MOTION" BIT SO CHEKIT
	IORM	P4,TRBSTS(T1)	; WON'T INCREMENT TUBREC AGAIN
	PJRST	SENSE		;GO DO THE SENSE
INTRD1:	TLZ	P4,RB.SNM	;CLEAR "NO MOTION" SO STATS ARE CORRECT
	MOVSI	T2,(.DOSR)	;SENSE ALREADY DONE, READ STATUS REGISTER
	PUSHJ	P,RDMBR##
	MOVEI	T3,RB.D16	;SET TAPE'S DENSITY IN IORB
	TRNN	T2,DI.PE
	MOVEI	T3,RB.D62
	DPB	T3,PRBDEN##
INTRD2:	MOVSI	T2,(.DOBC)	;READ BYTE COUNT
	PUSHJ	P,RDMBR##
	MOVEM	T2,TRBRCT(T1)	;SAVE BYTE COUNT IN IORB
	MOVEM	T2,TUBCCR(U)	; AND IN TUB
	TLZ	T2,-1		;CLEAR POSSIBLE FLAG
	SKIPN	P4		;IF NO ERROR
	ADDM	T2,TUBCRD(U)	; UPDATE TOTAL STATS
	ADDM	T2,TKBCRD(W)
	ADDM	T2,.CPTFI##
	CAMLE	T2,TKBCHR(W)	;TOO LARGE A RECORD?
	TLO	P4,RB.STL!RB.SER ;YES, TELL TAPUUO
	LDB	T3,PRBMOD##	;MODE
	IDIV	T2,TMODTB##(T3)	;COMPUTE NUMBER OF WORDS XFERRED
	HRLM	T2,TUBCHR(U)	;SAVE WORDS
	DPB	T3,PMTNCR##	;SAVE RESIDUE
	JRST	DONE


;HERE ON WRITE INTERRUPT
INTWRT:	MOVE	T2,TKBCHR(W)	;NO OF FRAMES WE WROTE
	ADDM	T2,TUBCWR(U)	;UPDATE STATS
	ADDM	T2,TKBCWR(W)
	ADDM	T2,.CPTFO##
	JRST	DONE		;AND FINISH UP

;HERE ON A REREAD OPPOSITE INTERRUPT
INTRRO:	PUSHJ	P,CHKIRB##	;SET T1 TO IORB
	  JRST	INTRR1		;NONE(!)  CALL IT A HARD ERROR
	MOVSI	T2,(.DOBC)	;READ THE BYTE COUNT REGISTER
	PUSHJ	P,RDMBR##
	JUMPE	T2,INTRR1	;THE TM78 BLEW IT IF BYTE COUNT IS 0
	MOVN	T3,T2		;-VE BYTE COUNT
	HRLZM	T3,T78UVA(W)	;TO TELL THE TM78 THE RIGHT BYTE COUNT
	LDB	T3,PRBMOD##	;MODE
	IDIV	T2,TMODTB##(T3)	;CONVERT BYTES TO WORDS
	JUMPN	T3,INTRR1	;LOSE IF A NON-INTEGRAL NUMBER OF WORDS
	HRRZ	T3,@IRBACC(T1)	;POINT TO CHANNEL COMMAND
	PUSHJ	P,REVCCW##	;GOODNESS. REVERSE THE IO LIST
	MOVEM	T2,T78RRO(W)	;SAVE ORIGINAL IOWD ADDR AND LH
	MOVE	T4,[IC.BST!RB.SED!RB.SDE!RB.SAP] ;SOME ERROR BITS TO SET
	JRST	ATTE10		;AND KEEP GOING WITH ANALYSIS (WILL EVENTUALLY RETRY)
INTRR1:	MOVE	T4,NRTERD	;CANT RETRY OPPOSITE
	JRST	ATTEN9		;READ REGISTERS AND GIVE NON-RECOVERABLE ERROR
INTRWP:	MOVSI	T2,TUSREW##	;SAY WE'RE REWINDING
	IORM	T2,TUBSTS(U)
	HRRZ	T1,TUBQUE(U)	;SET T1 TO IORB (OR 0)
	TLZ	P1,17		;SO WE DON'T GO TO INTREW NOW
	JRST	CPOPJ1##	;SKIP RETURN TO T78INT

INTUNL:	MOVSI	T2,TKSOFL##	;LET REST OF WORLD KNOW
	IORM	T2,TUBSTS(U)	; THAT THE DRIVE IS OFF-LINE
	TLO	P4,RB.SOL	;SAY DRIVE IS OFF-LINE

INTREW:	PUSHJ	P,REWDON##	;TELL WORLD WE'RE THROUGH REWINDING
	SETZM	TUBREC(U)	;CLEAR STATS
	SETZM	TUBFIL(U)
	JUMPE	T1,CLRCTY	;JUST RETURN TO TAPSER IF WE WEREN'T AT BOT ALREADY
	JRST	DONE		;AND FINISH UP

;HERE ON ANY FLAVOR OF OFF-LINE/NOT AVAILABLE TO THIS MASSBUS INTERRUPT
INTOFL:	PUSHJ	P,CHKIRB##	;DOING AN OPERATION?
	  JRST	OFLUNI		;NO, ASYNC. RETURN 0 TO TAPSER
	MOVSI	T2,RB.SOL!RB.SER!RB.SNM ;YES, TELL WORLD NOTHING HAPPENED
	IORM	T2,TRBSTS(T1)

OFLUNI:	MOVSI	T2,TKSOFL##	;LET REST OF WORLD KNOW
	IORM	T2,TUBSTS(U)	; THAT THE DRIVE IS OFF-LINE
	POPJ	P,

;HERE ON BAD TAPE INTERRUPT
BADTAP:	LDB	T1,TUYECD	;PICK UP FAILURE CODE
	MOVE	T4,NRTERD	;LOAD BAD DATA ERROR
	CAIN	T1,14		;BAD TAPE AT OR BEYOND EOT?
	 TRO	T4,RB.SET	;YES, NOTE NEED TO SET EOT AS WELL
	PJRST	ATTE10		;AND GO HANDLE SETTING THE BITS

;HERE ON TU FAULT A INTERRUPT
TUFLTA:	MOVE	T4,NRTERV	;GET BAD DRIVE ERROR BITS
	LDB	T1,TUYECD	;GET ERROR CODE
	CAIE	T1,44		;31/44 (PREVIOUS RECORD DESTROYED)?
	JRST	ATTEN9		;NO, JUST SET BITS AS REQUESTED
	MOVSI	T1,TUSFLT##	;YES, LOAD NEW ERROR BIT
	IORM	T1,TUBSTS(U)	;TELL WORLD THAT TU IS BAD
	PJRST	RTZER		;AND PITCH THE INTERRUPT (USER GETS HUNG DEV)

;HERE ON ON-LINE INTERRUPT
INTONL:	MOVSI	T2,TKSOFL##	;CLEAR OFF-LINE BIT
	ANDCAM	T2,TUBSTS(U)
	PUSHJ	P,TPMONL##	;TELL MDA A DRIVE JUST CAME UP
	MOVEI	P1,DF.SNS	;NON-DATA TYPE SENSE
	SETZ	T1,		;TELL TAPSER THIS IS ASYNC
	PJRST	SENSE		;GO START A SENSE AND RETURN
SCHDON:	SETZM	TKBSCH(W)
	JRST	CLRCTL


;HERE AFTER AN OPERATION IS THROUGH
DONE:	IORB	P4,TRBSTS(T1)	;FLAGS BEFORE AND AFTER ATTEN6
	MOVSI	T2,RB.EXC
	SKIPE	P4		;ANY FUNNY THINGS?
	IORM	T2,TRBFNC(T1)	;YES, AN EXCEPTION HAS OCCURRED
	SETZM	T78SNS(U)
CLRCTL:	PUSH	P,T1		;SAVE IORB
	MOVEI	T1,CO.CLR
	MOVE	T2,KDBCSO(W)	;GET CONI BITS AT INTERRUPT
	MOVE	T3,TAPCII##(T2)
	TRZE	T3,CI.DON	;DONE LIT?
	TRO	T1,CO.CCD	;YES, CLEAR IT ALSO
	MOVEM	T3,TAPCII##(T2)
	XCT	KDBCNO(W)
	XCT	KDBCNI(W)	;SOMETIMES RAE WON'T CLEAR
	MOVE	T3,T1		;COPY RESULTS
	MOVEI	T1,CO.MBI	;MASSBUS INIT
	TRNE	T3,CI.RAE	;IS IT STILL UP?
	XCT	KDBCNO(W)	;YES - ZAP IT
	SETZM	TKBFLG(W)	;NOTHING HAPPENING NOW
	SKIPA			;ONWARD
CLRCTY:	PUSH	P,T1		;SAVE T1
	MOVEI	T1,TAPCHN##+CO.AIE+CO.MBE ;ENABLE FOR INTERRUPTS
	XCT	KDBCNO(W)
	POP	P,T1		;RESTORE T1
	POPJ	P,		;AND RETURN

;HERE TO CLEAR THE TM78
CLRTMI:	PUSH	P,T1		;SAVE T1
	MOVEI	T1,CO.CLR!CO.MBE;CLEAR THE RH20 OF ALL ERRORS
	XCT	KDBCNO(W)
	POP	P,T1		;RESTORE T1
	CAIA

CLRTMO:	TAPON
CLRTM:	MOVE	T2,[.DOTMS!DO.TMC] ;DO AN INIT OF THE TM78
	PUSHJ	P,WTMBR##
	MOVEI	T4,40000	;HOW LONG TO WAIT
CLRTM1:	MOVSI	T2,(.DOTMS)	;READ TM78 STATUS
	PUSHJ	P,RDMBR##
	TRNN	T2,DI.TMR	;TM READY?
	SOJG	T4,CLRTM1	;NO, TRY AGAIN
	PJRST	RTZER		;YES (OR TIMEOUT) RETURN
;HERE ON CONI ERROR BIT
CHNERR:	TRNN	P2,CI.RAE	;REGISTER ACCESS ERROR?
	JRST	NORAE		;NO
	TLO	P4,RB.SNM!RB.SED ;YES, NO TAPE MOTION+ERROR
	JRST	DONE
NORAE:	TLNN	P2,(CS.MPE!CS.NXM)
	JRST	CHNRTY		;NO, JUST RETRY
	MOVEI	T3,CHENXM##	;SET TO CALL RIGHT ROUTINE
	MOVSI	T4,IOCHNX	;ASSUMING NXM
	TLNN	P2,(CS.NXM)	;NXM?
	PUSHJ	P,[MOVEI T3,CHEMPE## ;NO--SET FOR MEMORY PARITY
		   MOVSI T4,IOCHMP ; ...
		   POPJ  P,]
	MOVE	F,TUBCUR(U)	;POINT TO CURRENT DDB
	MOVE	T1,KDBICP(W)	;T1=ICWA
	MOVE	P1,KDBCHN(W)	;P1=CDB
	IORM	T4,CHNNUM(P1)	;MARK MEMORY ERROR FOR LATER SWEEP
	SKIPN	TUBERR(U)	;CALL ERRCON ON FIRST ERROR ONLY
	PUSHJ	P,(T3)		;GO CALL ERRCON
CHNRTY:	MOVEI	T4,-1		;SET T78ESD=0,,-1 AS A FLAG
	JRST	ATTE13		;AND GO CRANK UP A SENSE
;SUBROUTINE TO SET HOLD IN THE TM78
;RETURNS CPOPJ IF HOLD DIDN'T SET, CPOPJ1 NORMALLY
SETHLD:	PUSH	P,T1		;SAVE T1
	MOVE	T2,[.DOIA!3776]	;POINT INTERNAL ADDR AT A READ-ONLY LOCATION
	PUSHJ	P,WTMBR##	;IN CASE TM78 DECIDES TO WRITE WHEN HOLD SETS
	MOVE	T2,[.DOTMS!DO.HLD]
	PUSHJ	P,WTMBR##	;SET HOLD
	MOVEI	T1,40000	;HOW LONG TO WAIT
SETHL1:	MOVSI	T2,(.DOTMS)	;READ STATUS
	PUSHJ	P,RDMBR##
	TRNN	T2,DO.HLA	;HOLD ACKNOWLEDGED?
	SOJG	T1,SETHL1	;NO, WAIT SOME MORE
	JUMPN	T1,TPOPJ1##	;SKIP-RETURN IF HOLD ACKNOWLEDGED
	JRST	TPOPJ##		;COULDN'T SET HOLD

;SUBROUTINE TO CLEAR HOLD
CLRHLD:	MOVSI	T2,(.DOTMS)
	PUSHJ	P,WTMBR##	;CLEAR HOLD
	MOVE	T2,[.DOTMS!DO.TMC]
	PUSHJ	P,WTMBR##	;CLEAR POSSIBLE ERROR
	POPJ	P,		;AND RETURN
;ROUTINE TO DO A SENSE TO SEE IF A SLAVE IS PRESENT
;ENTER WITH T2 = DRIVE NUMBER
;RETURNS CPOPJ IF NOT THERE, CPOPJ1 IF IT IS
INISNS:	ADDI	T2,<(.DOND0)>_-14 ;SET RIGHT DRIVE
	ROT	T2,-6
	HRRI	T2,DF.SNS	;DO A SENSE ON THAT DRIVE
	PUSHJ	P,WTMBR##
	MOVEI	T1,40000	;HOW LONG TO WAIT
INISN1:	MOVSI	T2,(.DOAS)
	PUSHJ	P,RDMBR##	;READ ATTEN SUMMARY
	TRNN	T2,377		;SENSE OP COMPLETE?
	SOJG	T1,INISN1	;NO, WAIT SOME MORE
	JUMPE	T1,CPOPJ##	;GO IF WE TIMED OUT
	MOVSI	T2,(.DOSR)	;READ STATUS REGISTER
	PUSHJ	P,RDMBR##
	TRNE	T2,DI.AVL+DI.MNT ;IS IT THERE?
	AOS	(P)		;YES
	POPJ	P,		;RETURN


;ROUTINE TO DETERMINE WHAT SLAVES ARE PRESENT
T78CFG:	CAIL	T1,FSTICD/4	;AN RH20?
	CAILE	T1,LSTICD/4	;...
	JRST	CPOPJ1##	;WRONG DRIVER
	TLNE	T2,(CI.PPT)	;IPA CHANNEL?
	JRST	CPOPJ1##	;YES
	MOVSI	T1,CP.RH2	;RH20 CHANNEL
	PUSHJ	P,AUTCHN##	;BUILD A CHANNEL DATA BLOCK
	  POPJ	P,		;NO CORE
	PUSHJ	P,SAVE1##	;SAVE P1
	SETZ	P1,		;MASSBUS UNIT NUMBER 0, DRIVE 0

T78CF1:	PUSHJ	P,T78UNI	;AUTOCONFIGURE A SINGLE MASSBUS UNIT
	HLLOS	P1		;RESET DRIVE NUMBER
	AOBJN	P1,.+1		;ADVANCE TO NEXT MASSBUS UNIT
	TLNN	P1,10		;CHECKED ALL UNITS?
	JRST	T78CF1		;LOOP BACK FOR ANOTHER
	JRST	CPOPJ1##	;TRY ANOTHER DEVICE ON SAME CHANNEL
;AUTOCONFIGURE A SINGLE MASSBUS UNIT
T78UNI:	PUSHJ	P,RDDTR##	;READ DRIVE TYPE REGISTER
	CAIE	T2,TY.T78	;TU78?
	POPJ	P,		;NOT ON THIS MASSBUS UNIT
	HLRZ	T1,P1		;GET MASSBUS UNIT NUMBER
	PUSHJ	P,AUTKDB##	;BUILD A KDB
	  POPJ	P,		;GIVE UP IF NO CORE
	PUSHJ	P,TAPCSA##	;SET UP CSO CONI ADDRESS
	SETZB	T1,T2		;NO KONTROLLER SERIAL NUMBER
	PUSHJ	P,AUTKSN##	;DUMMY ONE UP AND STORE IT
	PUSHJ	P,CLRTMI	;RESET THE TM78
	PUSHJ	P,T78ONL	;IS THE TM78 ALIVE?
	  POPJ	P,		;DO NO MORE
	PUSHJ	P,T78UN3	;PUT THE CONTROLLER IN A KNOWN STATE
	PUSHJ	P,T78MRL	;CHECK MICROCODE ROM LEVELS
	  POPJ	P,		;OLD ROMS
	HRRZ	T2,KDBUNI(W)	;GET BIT FOR ATTENTIONS ON THIS UNIT
	HRLI	T2,(.DIDTR)	;REGISTER TO READ
	PUSHJ	P,WTMBR##	;GET DRIVE TYPE REGISTER
	TRNN	T2,TR.DRQ	;DRIVE REQUEST REQUIRED (DUAL PORTED)?
	JRST	T78UN1		;NO
	MOVEI	T2,2		;THERE CAN BE TWO PATHS
	DPB	T2,[POINTR (KDBSTS(W),KD.MPT)] ;STORE COUNT
	MOVSI	T2,(KD.MPD)	;GET MULTI-PORTED BIT
	IORM	T2,KDBSTS(W)	;LITE FOR FUTURE REFERENCE

T78UN1:	MOVNI	P3,1		;INIT DRIVE NUMBER

T78UN2:	PUSHJ	P,T78DRV	;AUTOCONFIGURE A SINGLE DRIVE
	  JFCL			;IGNORE ERRORS
	HRRZ	T1,P1		;GET DRIVE NUMBER
	CAIGE	T1,T78DMX-1	;DONE ALL DRIVES?
	AOJA	P1,T78UN2	;LOOP BACK FOR MORE
	PJRST	CLRCTY		;YES, ENABLE FOR INTERRUPTS AND RETURN

T78UN3:	MOVE	T2,[.DOAS!377]	;CLEAR GARBAGE FROM ATTEN SUMMARY REG
	PUSHJ	P,WTMBR##	;DATAO
	MOVEI	T1,CO.MBI	;MASSBUS INIT
	XCT	KDBCNO(W)	;...
	MOVEI	T1,CO.MBE	;MASSSBUS ENABLE
	XCT	KDBCNO(W)	;...
	POPJ	P,		;RETURN
;AUTOCONFIGURE A SINGLE DRIVE
T78DRV:	PUSHJ	P,CLRTMI	;CLEAR ERRORS, ETC.
	HRRZ	T1,P1		;GET UNIT
	MOVE	T1,BITTBL##(T1)	;AND IT'S BIT
	TDNE	T1,T78IUM(W)	;WANT TO IGNORE THIS DRIVE?
	POPJ	P,		;SAY IT DOESN'T EXIST
	HRRZ	T2,P1		;DRIVE NUMBER
	PUSHJ	P,INISNS	;SEE IF THE NEXT SLAVE IS THERE
	  PJRST	CLRTMI		;NO THERE SO RESET THINGS AND RETURN
	HRRZ	T1,P1		;DRIVE NUMBER
	SETCM	T1,BITTBL##(T1)	;GET MASK OF ALL BUT THIS DRIVE
	SETZ	T2,		;ASSUME NO OTHER NEW DRIVES
	SYSPIF			;AVOID RACE WITH INTERRUPT LEVEL
	ANDB	T1,T78NUM(W)	;CLEAR SINCE DRIVE IS NO LONGER "NEW"
	SKIPE	T1		;WORK PENDING FOR OTHER DRIVES?
	MOVNI	T2,1		;YES
	HLLM	T2,KDBNUM(W)	;UPDATE FLAG
	SYSPIN			;RELEASE INTERLOCK
	MOVE	T2,[.DOAS!377]	;CLEAR THE ATTENTION
	PUSHJ	P,WTMBR##	;...
	MOVSI	T2,(.DOSN)	;MASSBUS REGISTER
	PUSHJ	P,RDMBR##	;READ DRIVE SERIAL NUMBER
	SETZ	T1,		;REALLY A ONE WORD QUANTITY
	HRRZ	T3,P1		;GET PHYSICAL DRIVE NUMBER
	PUSHJ	P,AUTDSN##	;FAKE UP IF A ZERO & SAVE TEMPORARILY
	HRRZ	T3,P1		;GET PHYSICAL DRIVE NUMBER
	PUSHJ	P,AUTDPU##	;LINK UP DUAL PORTED DRIVES
	  JFCL			;MUST PROCEED EVEN IF DUAL PORTED
	HRLZ	T1,P1		;PHYSICAL DRIVE NUMBER
	HRR	T1,P1		;UDB TABLE INDEX
	MOVEI	T2,TUCIRD##+TUCD62##+TUCD16##+K.T78
	XMOVEI	T3,HNGTBL	;POINT TO HUNG TIMER TABLE
	MOVE	T4,['TU78/9']	;DRIVE MODEL
	PUSHJ	P,TAPDRV##	;BUILD AND LINK UP UDB AND DDB
	  JFCL			;FAILED
	DMOVE	T1,.CPTSN##	;RETRIEVE DRIVE SERIAL NUMBER
	DMOVEM	T1,UDBDSN(U)	;SAVE IN UDB
	MOVEM	T2,T78REG+14(U)	;SAVE FOR DIAGNOSTICS
	DMOVE	T1,T78ROM(W)	;GET ROM LEVELS
	DMOVEM	T1,T78REG(U)	;SAVE FOR ERROR LOGGING
	MOVSI	T2,(.DOSR)	;READ STATUS REG
	PUSHJ	P,RDMBR##	;DATAO
	MOVSI	T3,TKSOFL##	;BIT TO SET
	TRNN	T2,DI.RDY	;IF NOT READY
	IORM	T3,TUBSTS(U)	; THE DRIVE IS OFF-LINE
	MOVSI	T3,TUSWTL##	;BIT TO CLEAR
	ANDCAM	T3,TUBSTS(U)	;ASSUME TAPE IS NOT WRITE-LOCKED
	TRNE	T2,DI.FPT	;CHECK WRITE ENABLED STATE
	IORM	T3,TUBSTS(U)	;WRONG - IT IS WRITE LOCKED
	MOVE	T2,[.DOAS!377]	;CLEAR THE ATTEN BIT WE JUST LIT
	PUSHJ	P,WTMBR##	;DATAO
	JRST	CPOPJ1##	;RETURN
;CHECK MICROCODE ROM LEVELS
T78MRL:	PUSHJ	P,SETHLD	;SET HOLD IN TM SO WE CAN READ REV LEVELS
	  JRST	T78MR4		;LOSE IF IT DIDNT SET
	XMOVEI	T3,T78ROM(W)	;POINT TO STORAGE
	HRLI	T3,(POINT 9,)	;MAKE A BYTE POINTER
	MOVE	T4,[.DOIA!3776]	;POINT AT LOC FOR 1ST ROM REV LEVEL

T78MR1:	MOVE	T2,T4
	PUSHJ	P,WTMBR##	;LOC WE WANT TO READ
	MOVSI	T2,(.DOTMS)
	PUSHJ	P,RDMBR##	;READ THE LOCATION
	ANDI	T2,377		;ONLY 8 BITS ARE OF INTEREST
	IDPB	T2,T3		;SAVE IN KDB
	ADDI	T4,4000		;STEP TO NEXT REV LEVEL LOC
	TRNN	T4,40000
	JRST	T78MR1		;GO READ IT
	DMOVE	T3,[POINT 9,T78ROM(W)	;POINT TO WHAT WE GOT
		    POINT 9,T78REV]	;AND WHAT WE EXPECT FOR EACH ROM
	PUSH	P,P1		;SAVE P1
	MOVSI	P1,-^D8		;NUMBER OF ROMS TO CHECK
T78MR2:	ILDB	T1,T3		;GET NEXT ROM WE GOT
	ILDB	T2,T4		;AND WHAT WE EXPECT
	CAML	T1,T2		;SEE IF AT LEAST WHAT WE EXPECT
	AOBJN	P1,T78MR2	;OK, CONTINUE
	JUMPGE	P1,T78MR3	;JUMP IF ALL OK
	HRROI	T1,[ASCIZ /Ask field service to install the new TM78 microcode ROMs/]
	PUSHJ	P,TAPREV##	;LET TAPSER TYPE A MESSAGE
	SKIPA			;TAKE FAILING RETURN

T78MR3:	AOS	-1(P)		;SKIP
	POP	P,P1		;RESTORE P1
	PUSHJ	P,CLRHLD	;CLEAR HOLD

T78MR4:	MOVEI	T1,CO.MBE!CO.RAE ;CLEAR POSSIBLE REG ACCESS ERROR
	XCT	KDBCNO(W)	; (ON IF NON-EX DRIVE)
	PUSHJ	P,SETIVI	;SET UP INTERRUPT VECTOR
	JRST	CLRCTL		;CLEAR RH20 AND RETURN

;TWO WORDS FOR PATCHING IN NEW TM78 ROM REV LEVELS
T78REV:	BYTE (9) 6,5,6,4
	BYTE (9) 2,3,8,3
;HERE TO CHECK IF ON-LINE
T78ONL:	MOVSI	T2,(<DO.DRE>!.DOTMS)
	TAPOFF			;PREVENT INTERRUPT CODE FROM CHANGING
				; PREPERATION REGISTER
	PUSHJ	P,RDMBR##	;IS THE TM78 ALIVE?
	TRNE	T2,DO.HLA	;DID WE STOP IT?
	JRST	T78ON2		;YES, OFF-LINE
	TRNE	T2,DI.TMR
	JRST	T78ON1		;YES
	XCT	KDBCNI(W)	;NO, IS THE UNIT THERE AT ALL?
	TRNN	T1,CI.RAE
	PJRST	CLRTMO		;YES, TRY TO GET IT GOING AGAIN
	MOVEI	T1,CO.RAE+CO.MBE+CO.AIE+TAPCHN## ;NO, CLEAR THE RAE
	XCT	KDBCNO(W)	; (NON-EX UNIT)
	MOVSI	T1,TKSOFL##	;BIT TO SET
	IORM	T1,TKBSTS(W)	; MARK CONTROLLER OFFLINE
	CAIA
T78ON1:	AOS	(P)
T78ON2:	TAPON
	SKIPE	T1,T78NUM(W)	;GET BIT MASK
	JFFO	T1,T78ON3	;FIND FIRST UNIT NUMBER
	HRRZS	KDBNUM(W)	;INDICATE NO DRIVES TO CONFIGURE
	PJRST	CLRCTY		;RETURN ENABLING INTERRUPTS
T78ON3:	PUSHJ	P,AUTLOK##	;GET AUTCON INTERLOCK
	  POPJ	P,		;TRY AGAIN NEXT TIME
	MOVEI	P1,(T2)		;GET PHYSICAL DRIVE NUMBER
	HLL	P1,KDBUNI(W)	;INCLUDE MASSBUS UNIT
	MOVE	T1,KDBDVC(W)	;DEVICE CODE
	XMOVEI	T2,T78DSP	;DISPATCH
	MOVE	T3,KDBCHN(W)	;CHANNEL DATA BLOCK
	PUSHJ	P,AUTSET##	;SET UP CPU VARIABLES
	PUSHJ	P,T78DRV	;TRY TO CONFIGRE A DRIVE
	  JFCL			;IGNORE ERRORS
	PUSHJ	P,AUTULK##	;RELEASE AUTCON INTERLOCK
	POPJ	P,		;TELL TAPSER CONTROLLER IS ALIVE

;HERE TO CAUSE A SCHEDULE CYCLE
T78SCH:	SETOM	TKBSCH(W)	;SET FLAG

;HERE TO RESET AN ACTIVE DRIVE (HUNG)
T78RES:	SKIPE	T2,TKBSCW(W)	;LOSE DURING AN EXTENDED SENSE?
	MOVEM	T2,@KDBICP(W)	;YES, RESET ICWA TO WHAT IT SHOULD BE
	SETZM	TKBSCW(W)
	SETZM	T78RRO(W)	;NO LONGER IN READ-OPPOSITE
	PUSH	P,T1		;SAVE T1
	MOVEI	T1,CO.MBE	;MAKE SURE THE
	XCT	KDBCNO(W)	; RH IS LISTENING
	PUSHJ	P,SETIVI	;SET UP INTERRUPT VECTOR
	MOVEI	T1,CO.STP!CO.MBE ;CLEAR BUSY, SET DONE
	XCT	KDBCNO(W)	;DO IT
	POP	P,T1		;RESTORE T1
	SKIPE	TKBSCH(W)	;SCHEDULING?
	JRST	CLRCTY		;YES, JUST ENABLE INTERRUPTS
	MOVE	T1,KDBCSO(W)	;NO, CLEAR CONI BITS SO AS NOT
	SETZM	TAPCII##(T1)	; TO CONFUSE CLRCTL
	JRST	CLRCTL		;CLEAR RH20 AND RETURN
;HERE ON AN INTERRUPT WHICH REQUIRES RESETING THE TM78
CLRINT:	PUSHJ	P,CLRTM		;RESET THE CONTROLLER
	JUMPE	U,CLRIN1
	MOVSI	T1,(1B1)	;MARK AS A HARD ERROR FOR DAEMON
	IORM	T1,TUBTRY(U)
	MOVSI	T1,T78REG(U)	;COPY FROM "AT END"
	HRRI	T1,T78ICS(U)	; TO "AT ERROR"
	BLT	T1,T78ISE(U)	; FOR SYSERR
	PUSHJ	P,TPELOG##	;LOG THE ERROR
CLRIN1:	SKIPN	P1,TKBFLG(W)	;WAS ANYTHING HAPPENING?
	JRST	CLRIN2		;NO, RETURN A ZERO
	HRRZ	T1,TUBQUE(U)	;POINT T1 AT IORB
	JUMPE	T1,CLRIN2	;NONE????
	JUMPL	P1,T78SI1	;RETRY THE COMMAND IF IT WAS A DATA OPERATION
	MOVE	T4,NRTERV	;POSITIONING OP - CALL IT A HARD DEVICE ERROR
	JRST	ATTEN9		;FINISH UP PROCESSING

;HERE IF NOTHING WAS HAPPENING
CLRIN2:	AOS	T1,T78ACT(W)	;BUMP ASYNC INTERRUPT COUNT
	CAIG	T1,T78AMX	;GONE OVER THE THRESHOLD?
	JRST	RTZER		;NO, RETURN A ZERO
	PUSHJ	P,SETHLD	;YES. SET HOLD IN THE TM (STOP THE MICROCODE)
	  JFCL			; TO STOP THESE INTERRUPTS FROM CLOGGING THE SYSTEM
	SETOM	T78ACT(W)	;INDICATE HOLD IS SET
	JRST	RTZER		;AND KEEP ON GOING (RETURN 0 TO TAPSER)
;ROUTINE TO READ REGISTERS ON ERROR
RDREGS:	MOVEM	P2,T78REG+2(U)	;SAVE CONI
	MOVSI	T2,(.DOPTC)
	PUSHJ	P,RDMBR##
	MOVEM	T2,T78REG+3(U)	;DATAI PRIMARY TRANSFER CONTROL REG
	MOVSI	T2,(.DOPBA)
	PUSHJ	P,RDMBR##
	MOVEM	T2,T78REG+4(U)	;DATAI PRIMARY BLOCK ADDR REG
	PUSH	P,T1
	MOVEI	T1,T78REG+6(U)	;(REG+5 = LAST COMMAND)
	HRLI	T1,-22		;READ ALL REGISTERS
	SETZ	T2,		; STARTING AT 0
RDREG1:	PUSH	P,T2
	PUSHJ	P,RDMBR##
	MOVEM	T2,(T1)		;STORE DATA IN UDB
	POP	P,T2
	ADD	T2,[010000,,0]	;SET FOR NEXT REGISTER
	AOBJN	T1,RDREG1
	JRST	TPOPJ##

;ROUTINE TO SET UP INTERRUPT VECTOR, JSR
SETIVI:	MOVE	T2,KDBVIN(W)	;SET UP JSR IN ICWA+3
	HRLI	T2,(XPCW)

	MOVE	T3,KDBICP(W)
	MOVEM	T2,3(T3)	;FOR VECTORED INTERRUPTS
	MOVE	T2,KDBIVI(W)	;RESET INTERRUPT VECTOR ADDRESS
	XCT	KDBDTO(W)
	POPJ	P,		;AND RETURN
;HERE AFTER SENSE COMPLETES WHICH WAS DONE TO READ REGS 7-10
RDREG2:	MOVSI	T1,T78REG+6+22(U) ;ZERO THE EXTENDED SENSE AREA
	HRRI	T1,T78REG+6+23(U) ; IN CASE WE DONT DO AN EXTENDED SENSE
	SETZM	T78REG+6+22(U)	  ;  OR WE DO ONE AND IT FAILS
	BLT	T1,T78REG+6+22+16(U)
	MOVEI	T1,T78REG+6+7(U)
	HRLI	T1,-3		;WHAT TO READ
	MOVSI	T2,070000
	PUSH	P,T1		;RDREG1 EXITS TPOPJ
	PJRST	RDREG1

;HERE TO READ REGS ON SUCCESSFUL READ
RDREG3:	PUSH	P,T2
	PUSHJ	P,RDREGS	;READ (MOST) REGISTERS
	MOVSI	T2,T78ICS+6+7(U) ;COPY REGS 7-10 FROM WHERE WE READ THEM
	HRRI	T2,T78REG+6+7(U) ; TO THE FEP AREA (ELSE HAVE TO SENSE AGAIN)
	BLT	T2,T78REG+6+11(U) ; AND THESE REGISTERS DON'T CHANGE
	JRST	T2POPJ##
;TABLES TO CONTROL IO
TB.DAT==1B0
TB.WRT==1B1
TB.REV==1B2
TB.SPC==1B3
TB.RD==1B4
TB.ERA==1B5
TB.WTM==1B6
TB.REW==1B7
TB.RRG==1B8	;NOT IN TABLE, LIGHTS ON SENSE FROM RDMBR
TB.XSN==1B9	;NOT IN TABLE, LIGHTS AFTER SENSE IF WE DO EXTENDED SENSE

FNCTBL:	0				;0 - ILLEGAL
	TB.DAT!TB.RD!DF.RED!1B17	;1 - READ FORWARD
	TB.WRT!TB.DAT!DF.WRT!2B17	;2 - WRITE
	TB.DAT!TB.RD!TB.REV!DF.RRV!3B17	;3 - READ REVERSE
	TB.SPC!DF.SPF!4B17		;4 - SKIP RECORD
	TB.SPC!TB.REV!DF.SPR!5B17	;5 - BACKSPACE RECORD
	TB.SPC!DF.SFF!6B17		;6 - SKIP FILE
	TB.SPC!TB.REV!DF.SRF!7B17	;7 - BACKSPACE FILE
	TB.WRT!TB.ERA!DF.ERG!10B17	;10 - ERASE
	TB.WRT!DF.DSE!11B17		;11 - DATA SECURITY ERASE
	TB.REW!TB.REV!DF.REW!12B17	;12 - REWIND
	DF.UNL!13B17			;13 - REW, UNLOAD
	TB.WRT!TB.WTM!DF.WTM!14B17	;14 - WRITE TAPE MARK
FNCNOP:	TB.SPC!DF.NOP!15B17		;15 - YELLOW BALL
	TB.DAT!TB.RD!DF.RED!16B17	;16 - CORRECTION READ
	TB.DAT!TB.RD!DF.RED!17B17	;17 - LOW THRESHOLD READ

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

;HUNG TIMER TABLE
	EXP	^D480			;MAXIMUM TIMEOUT VALUE
HNGTBL:	BYTE(9)	^D000,^D046,^D046,^D046	;IL,RD,WT,RB
	BYTE(9)	^D046,^D046,^D480,^D480	;SR,BR,SF,BF
	BYTE(9)	^D046,^D480,^D225,^D225	;LG,SE,RW,RU
	BYTE(9)	^D046,^D046,^D046,^D046	;TM,YB,CR,RL

;FRAMES/WORD,,MODE BITS
MODTBL:	-1			;0 - ILLEGAL
	5,,30000		;1 - CORE DUMP
	4,,20000		;2 - INDUSTRY COMPAT
	-1			;3 - SIXBIT
	-1			;4 - 7 BIT (ASCII)
	-1			;5 - 7-TRACK CORE DUMP

;MISC BIT DEFINITIONS

;RH20 COMPOSITE BITS
	CI.ERR==CI.DBP!CI.LWC!CI.DRE!CI.RAE!CI.OVR ;CONI ERROR BITS
	CO.CLR==CO.RAE!CO.TEC	;CONO BITS TO CLEAR ERRORS
	CS.ERR==CS.MPE!CS.NAE!CS.NXM!CS.RHE!CS.OVR ;LOGOUT-AREA ERROR BITS
IC.RRG==1B0			;READ REGISTERS
IC.BST==1B1			;SET A BIT IN TKBSTS
IC.DSP==1B2			;DISPATCH TO AN ADDRESS
IC.ASY==1B3			;ASYNCH EVENT (RETURN 0 TO TAPSER)
IC.XSN==1B4			;DO AN EXTENDED SENSE TO GET MORE INFO


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

INTABL:	IFIW	DONE		;(00) ILLEGAL
	IFIW	INTRD		;(01) READ FORWARD
	IFIW	INTWRT		;(02) WRITE
	IFIW	INTRD		;(03) READ BACKWARDS
	IFIW	DONE		;(04) SKIP RECORD
	IFIW	DONE		;(05) BACKSPACE RECORD
	IFIW	DONE		;(06) SKIP FILE
	IFIW	DONE		;(07) BACKSPACE FILE
	IFIW	DONE		;(10) ERASE GAP
	IFIW	DONE		;(11) DATA SECURITY ERASE
	IFIW	INTREW		;(12) REWIND
	IFIW	INTUNL		;(13) UNLOAD
	IFIW	DONE		;(14) WRITE TAPE MARK
	IFIW	DONE		;(15) YELLOW BALL/ILLEGAL FUNCTIONS
	IFIW	INTRD		;(16) CORRECTION READ
	IFIW	INTRD		;(17) LOW-THRESHOLD READ

T78END:	END