Google
 

Trailing-Edge - PDP-10 Archives - de-10-omona-v-mc9 - tmxkon.mac
There are 13 other files named tmxkon.mac in the archive. Click here to see a list.
TITLE TMXKON - TM10A/B DEVICE DEPENDENT CODE FOR TAPSER V7023
SUBTTL T.HESS/TAH/TW	07 NOV 78
	SEARCH	F,S
	$RELOC
	$HIGH



;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1974,1975,1976,1977,1978 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VTMXKN,7023		;DEFINE VERSION NUMBER FOR STORAGE MAP
	SALL

TMXKON::	ENTRY	TMXKON

;DISPATCH TABLE FOR TAPSER CALLS

TMXDSP::JRST	TMXINI		;0 - INITIALIZE
	JRST	TMXRES		;1 - RESET ACTIVE I/O
	JRST	TMXSIO		;2 - START I/O
	JRST	TMXINT		;3 - DEVICE INTERUPT
	POPJ	P,		;4 - DEVICE COMMAND IS DX10 ONLY
	JRST	TMXIDL		;5 - KONTROLLER IS IDLE
	JRST	CPOPJ1##	;6 - TEST IF CTL ON-LINE
	JRST	TMXSCH		;7 - CAUSE A SCHEDULE CYCLE

;BYTE POINTERS

CTYUNI:	POINT	CM.UNS,T1,CM.UNP	;UNIT # IN CMD REG
CTYFCN:	POINT	CM.CMS,T1,CM.CMP	;FCN CODE IN CMD REG

;OFFSETS INTO TKBCCL

TKBSAV==TKBCCL##+2	;PLACE TO SAVE TM10A IOWD
TKBUNI==TKBCCL##+3	;CURRENT UNIT SELECTED (-1 IF NONE)
;DEFINITIONS FOR COMMAND REGISTER

CM.UNS==3		;SIZE OF UNIT FIELD
CM.UNP==^D20		;RIGHT MOST BIT

CM.PAR==1B21		;1=ODD PARITY, 0=EVEN PARITY
CM.CDF==1B22		;CORE DUMP FORMAT (9TK ONLY)

CM.CMS==4		;COMMAND BYTE SIZE
CM.CMP==^D26		;RIGHT MOST BIT
  CM.FNO==00		;NO-OP
  CM.FUR==10		;UNIT READY
  CM.FRW==01		;REWIND
  CM.FUN==11		;REWIND / UNLOAD
  CM.FRD==02		;READ
  CM.FR1==12		;READ ACROSS BOUNDARIES
  CM.FRC==03		;READ / COMPARE
  CM.FR2==13		;READ / COMPARE ACROSS BOUNDARIES
  CM.FWR==04		;WRITE
  CM.FWL==14		;WRITE AFTER LONG ERG
  CM.FTM==05		;WRITE TAPE MARK
  CM.FLG==15		;WRITE 3" BLANK TAPE
  CM.FFB==06		;SKIP FORWARD BLOCK
  CM.FFF==16		;SKIP FORWARD FILE
  CM.FBB==07		;SKIP BACKWARD BLOCK
  CM.FBF==17		;SKIP BACKWARD FILE

CM.NUE==1B27		;NEXT UNIT INTERUPT ENABLE
CM.DNS==2		;DENSITY BYTE SIZE
CM.DNP==^D29		;RIGHT MOST BIT
  CM.D2==000		;200 BPI
  CM.D5==100		;556 BPI
  CM.D8==200		;800 BPI
  CM.DMX==3		;MAX IORB DENSITY VALUE WE CAN HANDLE

CM.MSF==7B32		;MASK FOR FLAGS PIA
CM.MSD==7		;MASK FOR DATA PIA

;FLAGS IN LH SIDE (CONI ONLY)

CM.NUS==3		;NEXT UNIT BYTE SIZE
CM.NUP==^D17		;RIGHT MOST BIT
CM.EOR==1B14		;WRITE EOF (MAINT)

NOPMSK==760300		;UNIT,PARITY,DENSITY,FORMAT MASK
;DEFINITIONS FOR STATUS REGISTER

CI.CHN==1B9		;DF10C FLAG
			;UNKNOWN
CI.CPE==1B11		;CONTROL WORD PARITY ERROR (TM10B)
CI.NXM==1B12		;NON EX MEM (TM10B)
CI.DPE==1B13		;DATA PARITY ERROR (TM10B)
CI.CWW==1B14		;CONTROL WORD WRITTEN (TM10B)

CI.CCS==3		;CHARACTER COUNTER BYTE SIZE
CI.CCP==^D17		;RIGHT MOST BIT

;BITS IN RH SIDE

CI.HNG==1B18		;UNIT HUNG
CI.REW==1B19		;REWINDING
CI.LDP==1B20		;TAPE AT LOAD POINT (BOT)
CI.ILL==1B21		;ILLEGAL OPERATION
CI.TPE==1B22		;TAPE PARITY ERROR
CI.EOF==1B23		;END OF FILE (TAPE MARK SEEN)
CI.EOT==1B24		;TAPE INDICATE (EOT)
CI.RCE==1B25		;READ / COMPARE ERROR
CI.RLD==1B26		;RECORD LENGTH DIFFERS
CI.DLE==1B27		;DATA LATE ERROR (OVERRUN)
CI.BDT==1B28		;BAD TAPE FLAG
CI.JBD==1B29		;JOB DONE
CI.IDL==1B30		;UNIT IDLE
CI.CHE==1B31		;CHANNEL ERROR (BITS 11,12,13,OR 14)
CI.WLK==1B32		;UNIT WRITE LOCKED
CI.7TK==1B33		;7 TRACK UNIT
CI.LNU==1B34		;LOAD NEXT UNIT
CI.DAT==1B35		;DATA REQUEST

;BITS USED FOR CONO TMS,

CO.CPE==1B31		;CLEAR PARITY ERROR
CO.CCW==1B32		;CLEAR CONTROL WORD WRITTEN
CO.WCW==1B33		;WRITE CONTROL WORD
CO.MBH==1B34		;MOVE BR TO HR
CO.STP==1B35		;STOP CURRENT COMMAND

ALLERS==CI.DLE!CI.TPE!CI.BDT!CI.RCE!CI.ILL!CI.HNG!CI.CHE
			;ALL ERROR FLAGS OF INTEREST
SUBTTL TAPE INTERUPT SERVICE
;CALLED FROM TAPSER WITH W := KDB

TMXINT:	XCT	TTMCIC##(W)	;GET COMMAND REG
	LDB	T2,CTYUNI	;GET UNIT SELECTED
	PUSHJ	P,SETUDB##	;SET UP U
	  PJRST	SETM1		;NON-EX UNIT
	XCT	TTMCIC##(W)	;GET CMD REG AGAIN
	MOVEM	T1,TTMFCC##(U)	;SAVE IN UDB
	LDB	T4,CTYFCN	;GET FCN
	XCT	TTMCIS##(W)	;GET STATUS REG
	MOVEM	T1,TTMFCS##(U)	;STASH STATUS REG IN UDB
	PUSHJ	P,CHKIRB##	;GET IORB
	  JRST	TAPDIS##	;NONE - DISMISS INT.
	MOVE	T3,TTMFCS##(U)	;GET STATUS IN T3
	CAIN	T4,CM.FUR	;IF A NOP
	JRST	TMXSTS		;READ THE STATUS NOW
	MOVSI	T2,TUSBOT##	;CLEAR BOT INDICATION
	ANDCAM	T2,TUBSTS##(U)	;  WE WILL SET IT AGAIN IF NECESSARY
	LDB	T2,PRBFCN##	;GET DESIRED FCN
	CAILE	T2,TMIMAX	;CHECK VALIDITY
	JRST	TAPIFI##	;FUNCTION ERROR
	JRST	@TMIDSP(T2)	;DO IT

TMIDSP:	0,,-1			;0 - ILLEGAL
	TMIRD			;1 - READ
	TMIWT			;2 - WRITE
	TAPIFI##		;3 - READ BACKWARDS (ILLEGAL)
	TMISR			;4 - SKIP RECORD
	TMIBR			;5 - BACKSPACE RECORD
	TAPIFI##		;6 - SKIP FILE
	TAPIFI##		;7 - BACKSPACE FILE
	TMIEG			;10 - ERASE GAP
	TAPIFI##		;11 - DSE (ILLEGAL)
	TMIRW			;12 - REWIND
	TMIUN			;13 - REWIND / UNLOAD
	TMITM			;14 - WRITE TAPE MARK
	TMXOFL			;15 - FAKED INTERRUPT IF UNIT OFF-LINE
	TMIRD			;16 - CORRECTION READ
	TMIRD			;17 - READ LOW THRESHOLD

TMIMAX==.-TMIDSP-1
;ROUTINE TO MAKE CONTROLLER IDLE

CLRCTL:	LDB	T2,TUYKTP##	;UNIT TYPE
	JUMPN	T2,TMXIDL	;GO IF TM10B
	MOVSI	T2,(HALT)	;DON'T LEAVE DATAI/O ADDRESS
	MOVEM	T2,@TKBICP##(W)	; HANGING AROUND IN PI LOC
TMXIDL:	PUSH	P,T1		;SAVE IORB
	SETZM	TTMCHE##(W)	;CLEAR ERROR FLAG
	HLLZS	TKBCSO##(W)	;NO MORE INTS
	XCT	TTMCIC##(W)	;GET CTL CMD REG
	ANDI	T1,NOPMSK	;PRESERVE UNIT # ETC.
	XCT	TTMCOC##(W)	;DO NO-OP TO DRIVE W/ PIA=0
	SETOM	TKBUNI(W)	;NO UNIT SELECTED
	PJRST	TPOPJ##		;RETURN

;HERE TO RESET ACTIVE I/O

TMXRES:	MOVEI	T1,CO.STP	;STOP CURRENT COMMAND
	XCT	TTMCOS##(W)	;...
	MOVSI	T2,TKSSEL##	;SELECT BIT
	HRRZ	T1,TUBQUE##(U)	;GET HEAD OF Q
	JUMPE	T1,CLRCTL	;NONE - EXIT
	TDNE	T2,TKBSTS##(W)	;SELECTED?
	PUSHJ	P,ZAPEXL	;YES - FIX IOWD
	PJRST	CLRCTL		;CLEAR WORLD & EXIT

;HERE AT SYSTEM STARTUP - CHECK CORRECT KONTROLLER TYPE

TMXINI:	PUSHJ	P,CLRCTL	;CLEAR WORLD
	MOVE	T1,TTMJSR##(W)	;GET JSR WORD
	JUMPE	T1,CPOPJ##	;ZERO IF TM10B
	HRRZ	T2,TKBICP##(W)	;ELSE GET PNTR TO PI LOC
	MOVEM	T1,1(T2)	;PUT IN PLACE
	POPJ	P,		;RETURN



;ROUTINE TO CAUSE AN INTERUPT TO FORCE A SCHEDULE CYCLE

TMXSCH:	HRRZ	T1,TUBADR##(U)	;GET UNIT ADDRS
	LSH	T1,^D35-CM.UNP
	IORI	T1,CM.NUE+MTAFLG##	;INT ON NEXT UNIT AVAIL
	MOVEI	T2,CI.LNU	;ENABLE FOR LOAD NEXT UNIT
	CONO	PI,PI.OFF	;AVOID RACE
	HRRM	T2,TKBCSO##(W)	;...
	XCT	TTMCOC##(W)	;...
	CONO	PI,PI.ON
	POPJ	P,
SUBTTL START I/O

;ROUTINE TO START I/O
;USER JOB MUST BE NAILED DOWN - CAUSE SELECTION INTERUPT
;OR JUST START I/O IF UNIT ALREADY SELECTED
TMXSIO:	MOVSI	T1,TKSOFL##	;SET THE UNIT ON-LINE
	ANDCAM	T1,TUBSTS##(U)	; WILL SET OFF-LINE IF IT ISN'T OK
	HLRZ	T1,TUBAKA##(U)	;GET UNIT ADDRS DESIRED
	LSH	T1,^D35-CM.UNP	;PUT IN PROPER PLACE
	XCT	TTMCOC##(W)	;SELECT UNIT

	XCT	TTMCIS##(W)	;GET CTL STATUS
	MOVEM	T1,TTMFCS##(U)	;SAVE IN UDB

;HERE WHEN DESIRED DRIVE HAS BEEN SELECTED
;CHECK FOR ERRORS AND UNIT IDLE
TMXSEL:	PUSHJ	P,CHKIRB##	;GET IORB
	  JRST	TAPDIS##	;NONE
	MOVE	T3,TTMFCS##(U)	;GET STATUS REG
	MOVSI	T4,TUSWTL##	;WRITE LOCKED BIT
	ANDCAM	T4,TUBSTS##(U)
	TRNE	T3,CI.WLK	;WRITE LOCKED?
	IORM	T4,TUBSTS##(U)	;YES -SET BIT
	LDB	T2,PRBFCN##	;SEE WHAT FCN
	TRC	T3,CI.LNU	;MAKE NEXT TEST EASIER
	TRNN	T3,CI.REW!CI.IDL!CI.LNU ;IS UNIT READY OR REWINDING?
	HRROI	T2,RB.FYB	;NO, SET UP AS A YELLOW BALL
	DPB	T2,PRBFCN##	; FOR INTERRUPT LEVEL TO USE AS A FLAG
	CAIN	T2,RB.FYB	;STATUS CHECK?
	JRST	STSSEL		;YES - GO HANDLE
	TRNE	T3,CI.HNG!CI.ILL!CI.CHE
	JRST	TMXOFL		;UNIT OFFLINE
	PUSH	P,T1		;SAVE IORB PNTR
	SETZM	TTMCHE##(W)	;CLEAR CHL ERROR FLAG
	HRRZ	T1,TKBICP##(W)	;SET UP ICPC IF TM10B
	XCT	TTMDOS##(W)	;...
	POP	P,T1		;RESTORE IORB PNTR
	PUSHJ	P,SETCMD	;SET UNIT,PAR,DENS,COMPAT,FCN
	  PJRST	TMIDON		;WRITE LOCKED
	MOVEI	T3,CI.HNG!CI.ILL!CI.JBD!CI.CHE
DOIT:	MOVEI	T1,MTAFLG##(T2)	;ADD PIA & MOVE TO T1
	CONO	PI,PI.OFF	;SAVE US FROM OTHERS
	HRRM	T3,TKBCSO##(W)	;SET UP INT MASK
	XCT	TTMCOC##(W)	;START DEVICE
	CONO	PI,PION##	;OK NOW
NXTINT:	TDZA	T1,T1		;MORE INTERRUPTS COMING
SETM1:	MOVNI	T1,1
	POPJ	P,		;EXIT THIS INT
;HERE TO READ STATUS. HAVE TO HANDLE AFTER AN INTERRUPT
STSSEL:	HLRZ	T2,TUBAKA##(U)	;UNIT
	LSH	T2,^D35-CM.UNP	;PUT IT IN RIGHT PLACE
	TRO	T2,<CM.FUR>B<CM.CMP>+CM.NUE
	MOVEI	T3,CI.HNG!CI.ILL!CI.JBD!CI.CHE!CI.LNU
	JRST	DOIT		;GO CAUSE A UNIT-SELECTED INTERRUPT

;HERE TO GET UNIT STATUS UPDATE ON REQUEST

TMXSTS:	TRNE	T3,CI.HNG	;IF HUNG?
	JRST	TMXOFL		;MUST BE OFF-LINE
	TRNN	T3,CI.LDP	;AT LOAD POINT?
	TRNN	T3,CI.REW	;OR NOT REW'D
	PUSHJ	P,REWDON##	;YES - SET BOT / CLR REW
	PJRST	TMIDON		;EXIT INTERUPT

;HERE IF NO STATUS WORTH REMEMBERING

TMXOFL:	MOVSI	T2,RB.SOL!RB.SER!RB.SNM ;SET OFF-LINE STATUS
	IORM	T2,TRBSTS(T1)
	MOVSI	T2,TKSOFL##	;TELL UPPER LEVEL THAT THE TAPE ISN'T THERE
	IORM	T2,TUBSTS##(U)
	PUSHJ	P,CLRCTL	;RESET CTL
	PJRST	TMIDON		;AND RETURN
SUBTTL COMMAND SETUP
;ROUTINE TO SET UP CMD
;T1 := IORB FOR THIS REQUEST
;T3 CONTAINS CONI MTS,  - DESTROYED
;T2 := COMMAND FOR CTL ON EXIT

SETCMD:	LDB	T4,PRBFCN##	;GET DESIRED FCN
	SKIPN	T2,IOFTAB(T4)	;CHECK LEGAL
	JRST	SETILG		;NOPE - ERROR
	TLNE	T2,(IOXWRT)	;WRITE OP?
	JRST	SETCMW		;YES - CHECK WRITE LOCK
	PUSH	P,TTMBLK##(W)	;GET BLKI OR ZERO
SETCM1:	HLRZ	T2,TUBAKA##(U)	;UNIT ADDRS
	LSH	T2,^D35-CM.UNP	;WHERE IT WILL DO THE MOST GOOD
	IOR	T2,IOFTAB(T4)	;GET FCN CODE
	TLZ	T2,(IOXREW!IOXWRT) ;CLR UNWANTED BITS
	IORI	T2,MTDCHN##	;SET DATA CHL NOW
	POP	P,T4		;GET BLKI/O
	HRR	T4,TRBXCW(T1)	;GET DATA ADDRS OR SPACING COUNT
	TLZE	T2,(IOXLST)	;DATA?
	JRST	[PUSHJ P,SETCMX	;DO CTL SPECIFIC SETUP
		 JRST SETCM2]	;PROCEED
	TLZN	T2,(IOXSPC)	;SPACING OP?
	JRST	[MOVEI T4,0	;NO - ILLEGAL DATA REQUEST
		 JRST SETCM2]	;SET IN CHL AREA
	MOVNI	T4,-1(T4)	;GET COUNT -1 NEGATED
	JUMPE	T4,[TRZ T2,7	;CLEAR DATA PIA IF ONLY ONE
		    JRST SETCM2];AND STORE ZERO
IFN FT22BIT,<
	LDB	T3,TUYKTP##	;GET KONTROLLER TYPE
	JUMPE	T3,.+4		;NO CHL IF TM10A
	HRRZ	T3,TKBCDB##(W)	;CHECK DF10C CHL
	SKIPGE	CHB22B##(T3)
	LSH	T4,4		;ONLY 14 BITS OF INFO
>
	HRLZM	T4,TKBCCL##(W)	;SAVE IN CHL PGM AREA
	HRLZ	T4,TTMBLK##(W)	;GET BLKO OR ZERO
	HRRI	T4,TKBCCL##(W)	;SET ADDRS
	SETZM	TKBCCL##+1(W)	;CHL HALT IF TM10B
SETCM2:	MOVEM	T4,@TKBICP##(W)	;PUT IN CORRECT PLACE
	LDB	T4,PRBMOD##	;GET DESIRED MODE
	CAIN	T4,RB.MCD	;CORE-DUMP?
	IORI	T2,CM.CDF	;YES - SET BIT
	LDB	T4,PRBDEN##	;GET DENSITY BYTE
	CAILE	T4,CM.DMX	;CHECK MAX
	MOVEI	T4,CM.DMX
	DPB	T4,PRBDEN##	;REMEMBER SELECTED DENSITY
	IOR	T2,[CM.PAR+0
		    CM.PAR+CM.D2
		    CM.PAR+CM.D5
		    CM.PAR+CM.D8](T4)
	MOVSI	T4,RB.PAR	;CHECK PARITY
	TDNE	T4,TRBLNK(T1)	;ON FOR EVEN PARITY
	TRZ	T2,CM.PAR	;CLEAR BIT IN CMD
	PJRST	CPOPJ1##	;GIVE GOOD RETURN

;SET IMPROPER MODE AND RETURN

SETILG:	MOVSI	T2,RB.SIL!RB.SER ;ILLEGAL OP
	IORM	T2,TRBSTS(T1)	;SET IN IORB
	POPJ	P,		;ERROR RETURN
;HERE IF WRITING - CHECK WRLK

SETCMW:	MOVS	T2,TTMBLK##(W)	;GET BLKO OR ZERO
	PUSH	P,T2		;SAVE ON PDL
	TRNN	T3,CI.WLK	;WRITE LOCKED?
	JRST	SETCM1		;NO - PROCEED
	MOVSI	T2,RB.SLK!RB.SER ;AND IN IORB
	IORM	T2,TRBSTS(T1)	;...
	PJRST	SETCM1	;ERROR RETURN

;ROUTINE TO SETUP CMD LIST TERMINATION WORD FOR
;SPECIFIC CONTROLLER (A OR B)
;T4 := ADDRS OF CHL PGM

SETCMX:	LDB	T3,TUYKTP##
	JRST	@[SETCXA
		  SETCXB](T3)	;DISPATCH ACCORDING TO TYPE

;HERE FOR TM10A

SETCXA:	MOVE	T3,0(T4)	;SAVE ADDRS
	HRLM	T3,TRBEXL(T1)	;  OF FIRST WORD FOR WORD-COUNT
	MOVEM	T3,TKBSAV(W) 	;BLKI/O WORD SAVED
	POPJ	P,		;  COMPUTATION AND RETURN

;HERE FOR TM10B

SETCXB:	HLRZ	T3,TRBEXL(T1)	;END OF XFER LIST
	HRLI	T3,TKBCCL##(W)	;HANDY ZERO
	HLRZM	T3,0(T3)	;CHL JUMP TO ZERO
	SETZM	TKBCCL##(W)	;GRNTEE ZERO
	POPJ	P,		;RETURN
;TABLE FOR I/O FUNCTIONS - ALREADY IN POSITION

DEFINE IOT(CMD,BITS) <
	BITS+<CMD>B<CM.CMP>
>

;ALLOWABLE SPECIAL FCN BITS

IOXLST==1B0		;DATA XFER LIST REQUIRED
IOXSPC==1B1		;SPACING OPERATION
IOXREW==1B2		;REWIND
IOXWRT==1B3		;WRITE OPERATION

IOFTAB:	0			;0 - ILLEGAL
	IOT(CM.FRD,IOXLST)	;1 - READ
	IOT(CM.FWR,IOXLST!IOXWRT) ;2 - WRITE
	0			;3 - ILLEGAL
	IOT(CM.FFB,IOXSPC)	;4 - FORWARD SPACE BLOCK
	IOT(CM.FBB,IOXSPC)	;5 - BACKWARD SPACE BLOCK
	IOT(CM.FFF,0)		;6 - FORWARD SPACE FILE
	IOT(CM.FBF,0)		;7 - BACKSPACE FILE
	IOT(CM.FLG,IOXWRT)	;10 - WRITE LONG GAP
	0			;11 - ILLEGAL
	IOT(CM.FRW,IOXREW)	;12 - REWIND
	IOT(CM.FUN,0)		;13 - REWIND / UNLOAD
	IOT(CM.FTM,IOXWRT)	;14 - WRITE TAPE MARK
	IOT(CM.FFB,IOXSPC)	;15 - USED WHEN UNIT DETECTED OFF-LINE
	IOT(CM.FRD,IOXLST)	;16 - CORRECTION READ
	IOT(CM.FRD,IOXLST)	;17 - READ LOW THRESHOLD
SUBTTL READ
;HERE ON DONE INTERUPT FOR READ

TMIRD:	PUSHJ	P,TMCKMV	;SEE IF TAPE MOVED
	  JSP	T4,TMERD0	;NO - PROBS
	PUSHJ	P,CHRCT		;GET CHARACTER COUNT
	  JRST	[MOVSI T4,RB.STL +RB.SER
		 IORM T4,TRBSTS(T1)
		 JRST .+1]
	MOVEM	T2,TRBRCT(T1)	;SAVE COUNT IN IORB
	MOVE	T3,TTMFCS##(U)	;RESTORE STATUS
	SKIPN	TTMCHE##(W)	;CHL ERROR
	TRNE	T3,CI.CHE	;???
	JRST	TMECHN		;YES - HANDLE
	PUSHJ	P,TMSTM		;ENCOUNTER EOF?
	  JRST	TMIRD1		;NO - GO ON
	AOS	TUBFIL##(U)	;PLUS 1 MORE FILE
TMIRD1:	TRNE	T3,ALLERS	;CHECK BADNESS
	JSP	T4,TMERD1	;ERROR - HANDLE
	MOVE	T2,TRBRCT(T1)	;GET CHAR COUNT FOR THIS RECORD
	ADDM	T2,TUBCRD##(U)	;AND UPDATE STATISTICS

;HERE TO FINISH INTERUPT AND EXIT TO TAPSER

TMIDON:	PUSHJ	P,ZAPEXL	;CLEAN UP
	HLRZ	T3,TUBAKA##(U)	;GET LAST UNIT REF'D
	MOVEM	T3,TKBUNI(W)	;AND SAVE IT FOR LATER CHECK
	HLRZ	T3,TRBSTS(T1)	;LOOK AT FLAGS
	JUMPE	T3,CPOPJ##	;RETURN IF NONE
	MOVSI	T2,RB.EXC	;ELSE SET EXCEPTION
	IORM	T2,TRBLNK(T1)	;IN IORB
	POPJ	P,		;AND RETURN

;ROUTINE TO FIXUP TM10B XFER LIST

ZAPEXL:	LDB	T3,TUYKTP##	;GET TYPE
	HLRZ	T2,TRBEXL(T1)	;PNTR TO END OF XFER LIST
	JUMPE	T2,CPOPJ##	;RETURN IF NONE
	JUMPE	T3,ZAPEXA	;JUMP IF TM10A
	SETZM	0(T2)		;CLEAR IT
	POPJ	P,		;RETURN

;RESTORE BLKI/O WORD

ZAPEXA:	MOVE	T2,TKBSAV(W)
	HRRZ	T3,TRBXCW(T1)	;PNTR TO XFER LIST
	MOVEM	T2,0(T3)	;STORE WORD
	POPJ	P,		;RETURN
SUBTTL WRITE
;HERE ON DONE INTERUPT FOR WRITE

TMIWT:	PUSHJ	P,TMCKMV	;DID IT MOVE
	  JSP	T4,TMEWT0	;NO - TRY TO FIX
	SKIPN	TTMCHE##(W)	;CHL ERROR?
	TRNE	T3,CI.CHE
	JRST	TMECHN		;YES - LOOK AT THAT
	MOVSI	T2,RB.SET	;NOW CHECK EOT
	TRNE	T3,CI.EOT	;???
	IORM	T2,TRBSTS(T1)	;SET INFO IN IORB
	TRNE	T3,ALLERS	;EVERYTHING OK?
	JSP	T4,TMEWT1	;NO - TRY TO FIX
	PUSHJ	P,CHRCT		;GET CHARACTER COUNT
	  JFCL			;DON'T CARE
	ADDM	T2,TUBCWR##(U)	;ADD TO STATS
	PJRST	TMIDON		;AND EXIT

;HERE ON DONE INTERUPT FOR WRITE TAPE MARK

TMITM:	MOVSI	T2,RB.SET	;JUST IN CASE
	TRNE	T3,CI.EOT	;WE SAW A TI
	IORM	T2,TRBSTS(T1)	;SET FLG IF SEEN
	TRNE	T3,ALLERS	;ANYTHING WRONG?
	JSP	T4,TMEWT1	;YES - SORRY
	SETZM	TUBREC##(U)	;ZEROTH RECORD
	AOS	TUBFIL##(U)	;AND 1 MORE FILE
	PJRST	TMIDON		;EXIT

;ROUTINE SET SAY WE'VE SEEN A TAPE MARK
;ALSO RESETS RECORD COUNTER

TMSTM:	TRNN	T3,CI.EOF	;SEEN EOF?
	POPJ	P,		;NO - RETURN
	MOVSI	T2,RB.STM	;IORB FLAG ALSO
	IORM	T2,TRBSTS(T1)	;...
	SETZM	TUBREC##(U)	;CLEAR RECORD COUNT
	PJRST	CPOPJ1##	;SKIP RETURN FOR FURTHER PROCESSING
SUBTTL REWIND/UNLOAD/BACKSPACE RECORD
;HERE ON INTERUPT AFTER STARTING REWIND
TMIUN:	MOVE	T2,TUBSTS##(U)
	TLZ	T2,TUSREW##	;NOT REWINDING
	JRST	TMIRWU		;CARRY ON

TMIRW:	TRNE	T3,CI.HNG!CI.ILL ;CHECK BADNESS
	JSP	T4,TMERW	;HANDLE PROBLEM
	MOVE	T2,TUBSTS##(U)
	TLO	T2,TUSREW##	;SAY WE ARE REWINDING
TMIRWU:	MOVEM	T2,TUBSTS##(U)
	TRNE	T3,CI.LDP	;ALREADY DONE?
	PUSHJ	P,REWDON##	;YES - CLEAN UP THEN
	SETZM	TUBREC##(U)	;IN CASE WE DON'T FINISH
	SETZM	TUBFIL##(U)	;CLEAR THESE NOW
	PJRST	TMIDON		;AND EXIT

;HERE ON DONE INTERUPT FROM BACKSPACE RECORD

TMIBR:	TRNE	T3,CI.HNG!CI.CHE ;DEVICE PROBS?
	JSP	T4,TMERD1	;WHOOPS PROBLEM
	PUSHJ	P,TMSTM		;LOOK FOR TM
	  JRST	TMIBR1		;NONE SEEN
	SOS	TUBFIL##(U)	;ONE  LESS FILE
TMIBR1:	SOS	TUBREC##(U)	;ALSO ONE LESS RECORD
	TRNN	T3,CI.LDP	;SEE IF WE CRASHED INTO BOT
	PJRST	TMIDON		;NO - DONE
	MOVSI	T2,RB.SBT!RB.SNM ;YES - LITE BITS
	SKIPN	TUBREC##(U)	;TRY TO GUESS IF TAPE MOVED
	SKIPE	TUBFIL##(U)	;  BY SEEING IF AT LOGICAL BOT
	TLZ	T2,RB.SNM	;FIRST TIME HERE
	IORM	T2,TRBSTS(T1)	;SET RESULT IN IORB
	MOVSI	T2,TUSBOT##	;AND UDB
	IORM	T2,TUBSTS##(U)	;...
	SETZM	TUBREC##(U)	;GET THINGS RIGHT
	SETZM	TUBFIL##(U)
	PJRST	TMIDON		;EXIT
SUBTTL SKIP RECORD/ERASE GAP
SUBTTL ERROR PROCEDURES
;HERE ON DONE INTERUPT FROM SKIP FORWARD RECORD

TMISR:	PUSHJ	P,TMCKMV	;SEE IF WE MOVED?
	  JSP	T4,TMERD0	;NOPE
	TRNE	T3,ALLERS	;CHECK ERRORS
	JSP	T4,TMERD1	;HANDLE IT
	PUSHJ	P,TMSTM		;CHECK FOR TAPE MARK
	  JRST	TMIDON		;NO TAPE MARK
	AOS	TUBFIL##(U)	;INCR FILE COUNTER
	JRST	TMIDON		;AND EXIT

;HERE ON DONE INTERUPT FROM ERASE GAP

TMIEG:	MOVSI	T2,RB.SET	;IN CASE TAPE INDICATE
	TRNE	T3,CI.EOT	;SEEN ONE?
	IORM	T2,TRBSTS(T1)	;YES - SET BIT
	TRNE	T3,CI.HNG!CI.ILL!CI.CHE ;ERROR ALLOWED
	JRST	TMEWT1		;YES - TREAT IT
	PJRST	TMIDON		;EXIT INT
;HERE FOR CHANNEL ERROR

TMECHN:	TLNN	T3,(CI.DPE)	;DATA PARITY ERROR?
	JRST	TMECH1		;NO - HANDLE NOW
	MOVEI	T1,CO.STP!CO.CPE
	XCT	TTMCOS##(W)	;STOP CHL & CLEAR ERROR
	MOVEM	T3,TTMCHE##(W)	;FLAG ERROR & SAVE CONI BITS
	PJRST	NXTINT		;AND WAIT FOR JOB DONE

TMECH1:	MOVE	T2,TTMCHE##(W)	;GET ERROR CONI BITS
	MOVEM	T2,TTMFCS##(U)	;SO DAEMON GETS THEM
	PUSHJ	P,SAVE1##	;SAVE P1
	MOVEI	T2,CHNNXM##	;ASSUME NXM
	TLNE	T3,(CI.DPE!CI.CPE)
	MOVEI	T2,CHNMPE##	;NO - PARITY ERROR
	PUSH	P,T1		;SAVE IORB PNTR
	HRRZ	T1,TKBICP##(W)	;PNTR TO CCW
	HRRZ	P1,TKBCDB##(W)	;PNTR TO CHL DATA BLOCK
	PUSHJ	P,0(T2)		;EXERCISE ROUTINE
	MOVEI	T1,CO.CCW	;CLEAR CONTROL WORD WRITTEN
	XCT	TTMCOS##(W)	;...
	POP	P,T1		;RESTOR IORB
	MOVSI	T2,RB.SER!RB.SED
	IORM	T2,TRBSTS(T1)	;TELL HIM WORLD ENDED
	PJRST	TMIDON		;RETURN - NO RETRIES

;ROUTINE TO DETERMINE IF TAPE MOVED (DIVINATION)

TMCKMV:	TRNE	T3,CI.HNG!CI.ILL
	POPJ	P,		;TRY THIS FOR NOW
	AOS	TUBREC##(U)	;MOVIN' ALONG
	JRST	CPOPJ1##	;SKIP RETURN
;ERRORS DETECTED DURING WRITE OPERATIONS

TMEWT0:	MOVSI	T2,RB.SNM!RB.SED ;TAPE DIDN'T MOVE
	IORM	T2,TRBSTS(T1)
TMEWT1:	PUSHJ	P,TMEANL	;ANALYSE ERROR
	MOVSI	T2,RB.SLK	;CHECK FOR WRITE LOCK
	TRNE	T3,CI.WLK
	IORM	T2,TRBSTS(T1)	;YES - SET BIT
	PJRST	TMIDON		;EXIT INTERUPT

;ERRORS DETECTED DURING READ / SPACING OPS

TMERD0:	MOVSI	T2,RB.SNM!RB.SED ;TAPE DIDN'T MOVE
	IORM	T2,TRBSTS(T1)
TMERD1:	PUSHJ	P,TMEANL	;ERROR ANALYSIS
	PJRST	TMIDON		;EXIT INT

;PROBLEM STARTING REWIND

TMERW:	MOVSI	T2,RB.SED!RB.SNM!RB.SOL
	IORM	T2,TRBSTS(T1)	;SET OFF-LINE ETC.
	PUSHJ	P,CLRCTL	;RESET CTL
	PJRST	TMIDON		;EXIT INT
;ROUTINE TO ANALYSE ERROR BITS IN RH(T3)

TMEANL:	MOVEI	T2,0		;SET INITIAL ZERO
	TRNE	T3,CI.HNG
	JRST	TMEOFL		;DRIVE OFF-LINE
	TRNE	T3,CI.ILL
	JRST	TMECMR		;COMMAND REJECT
	TRNE	T3,CI.DLE
	JRST	TMEOVR		;OVERRUN
	TRNE	T3,CI.TPE!CI.BDT!CI.RCE
	JRST	TMEDC		;DATA CHECK
TMEXIT:	IORM	T2,TRBSTS(T1)	;SET SELECTED BITS
	POPJ	P,		;RETURN

TMEOFL:	PUSHJ	P,TMXOFL	;SET UNIT OFF-LINE
TMECMR:	MOVSI	T2,RB.SNM!RB.SED ;SET BITS (TAPE DIDN'T MOVE)
	PJRST	TMEXIT

TMEDC:	TLO	T2,RB.SDE	;DATA ERROR
TMEOVR:	TLO	T2,RB.SED	;ERROR DETECTED - RETRY
	PJRST	TMEXIT
SUBTTL COMPUTE CHARACTER COUNTS
;ROUTINE COMPUTES CHARACTER COUNT
;RETURNS COUNT IN T2 , T1 SAVED
;CALLED WITH C(T3) := CONI MTS,

CHRCT:	PUSH	P,T1		;SAVE IORB PNTR
	LDB	T2,TUYKTP##	;GET CNTRL TYPE
	PUSHJ	P,@[WRDCTA
		    WRDCTB](T2)	;CALL CORRECT ROUTINE
	  SKIPA			;LENGTH ERROR RETURN
	AOS	-1(P)		;SET FOR SKIP RETURN
	MOVEI	T2,-1(T1)	;WORD COUNT -1 INTO T2
	HLRZ	T4,T3		;NOW PLAY WITH BC CHAR CNT
	ANDI	T4,7		;TO DETERMINE BYTE RESIDUE
	JUMPE	T4,[AOJA T2,CHRCT1] ;IF ZERO RE-ADJUST WORD COUNT
CHRCT1:	DPB	T4,PMTNCR##	;SAVE RESIDUE FOR MTCHR.
	HRLM	T2,TUBCHR##(U)	;STORE LAST WORD COUNT FOR MTCHR.
	TRNE	T3,CI.7TK	;REAL EASY IF 7-TRACK
	JRST	CHRCT2		;...
	XCT	TTMCIC##(W)	;9TK - SEE WHAT MODE
	MOVEI	T3,5		;ASSUME CORE-DUMP
	TRNN	T1,CM.CDF	;IS IT?
	MOVEI	T3,4		;NO - COMPAT THEN
	IMUL	T2,T3		;CONVERT TO BYTES
	ADD	T2,T4		;PLUS REMAINDER
	XCT	TTMDIC##(W)	;AND FETCH CRC
CHRCT3:	DPB	T1,PMTCRC##	;STORE IT FOR MTCHR.
	PJRST	TPOPJ##		;RESTORE T1 AND EXIT

CHRCT2:	MOVE	T1,(P)		;GET IORB
	LDB	T1,PRBMOD##	;MODE
	IMUL	T2,TMODTB##(T1)	;CHARS TAPUUO THINKS ARE IN A WORD

	ADD	T2,T4		;PLUS LEFT OVERS
	MOVEI	T1,0		;NO CRC FOR 7TK
	JRST	CHRCT3
;ROUTINE TO COMPUTE WORD COUNT FOR TM10A
;RETURNS WORD COUNT IN T1 , T3 PRESERVE
;CALLED WITH T1 := IORB

WRDCTA:	HRRZ	T4,TRBXCW(T1)	;ADDRS OF RESIDUE PNTR
	HLRZ	T2,TRBEXL(T1)	;ADR OF FIRST WORD -1
	HRRZ	T1,0(T4)	;LAST ADDRS
	SUB	T1,T2		;DIFFERENCE IS WORD COUNT
	TRNE	T3,CI.RLD	;CHECK LENGTH ERROR
	SKIPGE	0(T4)		;YES - SHORT RECORDS OK
	JRST	CPOPJ1##	;OK - LEN .LE. ACTUAL
	POPJ	P,		;ERRORR IF RECORD TOO LARGE

;ROUTINE TO COMPUTE WORD COUNT FOR TM10B
;CALLING CONVENTIONS SAME AS WRDCTA

WRDCTB:	MOVE	T1,TKBICP##(W)	;PNTR TO INITIAL CONTROL WORD
IFN FT22BIT,<
	PUSHJ	P,SAVE1##	;SAVE P1
	MOVE	P1,TKBCDB##(W)	;ADDRS OF CDB
>
	PUSH	P,T3		;SAVE T3
	PUSHJ	P,WRDCNT##	;CALL ROUTINE IN COMMON
	POP	P,T3		;RESTORE T3
	TRNN	T3,CI.RLD	;LENGTH = REQUEST?
	JRST	CPOPJ1##	;OK - GIVE GOOD RETURN
	MOVE	T2,TKBICP##(W)	;ICPC PNTR
	HLRZ	T2,1(T2)	;LH TERMINATION WORD
IFN FT22BIT,<
	SKIPGE	CHB22B##(P1)	;SKIP IF DF10
	LSH	T2,-4		;DF10C HAS 14 BIT ADDRS
>
	SKIPN	(T2)		;ARE WE AT END OF LIST
	SOJA	T1,CPOPJ##	;YES - RECORD IS TOO LONG
	SOJA	T1,CPOPJ1##	;NO - SHORT RECORD, OK

TMXEND:	END