Trailing-Edge
-
PDP-10 Archives
-
BB-4170G-SM
-
sources/phym2.mac
There are 48 other files named phym2.mac in the archive. Click here to see a list.
;<3A.MONITOR>PHYM2.MAC.20, 22-Aug-78 14:22:36, EDIT BY FORTMILLER
;Set US.REW in the attention routine instead of START I/O
;<3A.MONITOR>PHYM2.MAC.19, 1-Aug-78 15:26:43, EDIT BY MILLER
;COMPUTE WRITE STATISTICS CORRECTLY
;<3A.MONITOR>PHYM2.MAC.18, 30-Jul-78 17:36:11, Edit by MCLEAN
;<3A.MONITOR>PHYM2.MAC.17, 14-Jul-78 13:44:18, EDIT BY BOSACK
;DONT IGNORE PRE/POSTAMBLE ERRORS ON PE READ
;<3A.MONITOR>PHYM2.MAC.16, 2-Jun-78 14:58:35, EDIT BY BOSACK
;ENSURE TM2POL ALWAYS LEAVES TM02/3 WITH ERRORS RESET
;<3A-NEW>PHYM2.MAC.15, 31-May-78 09:50:11, Edit by FORTMILLER
;<3A-NEW>PHYM2.MAC.14, 25-May-78 22:20:46, Edit by FORTMILLER
;ADD DX20 SUPPORT
;PUT DENSITYS DRIVE IS CAPABLE OF IN UDBCHR
;CONVERT UDBDSN TO DECIMAL SERIAL NUMBER
;<3A.MONITOR>PHYM2.MAC.13, 18-May-78 13:12:37, EDIT BY BOSACK
;CLEAR ERROR BYTE POINTER AT TERMINATION OF ERROR RECOVERY
;<3A.MONITOR>PHYM2.MAC.12, 29-Mar-78 12:11:03, Edit by MCLEAN
;FIX MTINDX TO POINT TO FREE MTCUTB
;<3A.MONITOR>PHYM2.MAC.11, 29-Mar-78 08:19:07, EDIT BY MILLER
;ADD UNIT,KONTROLLER,CHANNEL INFO TO ALL "HARDWARE" BUG TYPEOUTS
;<3A.MONITOR>PHYM2.MAC.10, 9-Mar-78 00:00:34, Edit by MCLEAN
;<3A.MONITOR>PHYM2.MAC.9, 8-Mar-78 23:56:40, Edit by MCLEAN
;MOVE INIUNI CALL SO IT DOESN'T BREAK MULTIPLE UNITS
;AND ISN'T CALLED AS OFTEN
;<2BOSACK>PHYM2.MAC.53, 24-Feb-78 01:49:19, EDIT BY BOSACK
;<2BOSACK>PHYM2.MAC.52, 24-Feb-78 01:36:56, EDIT BY BOSACK
;REWORK ERROR INTERFACE WRT DATA/DEVICE ERRORS
;<4.MONITOR>PHYM2.MAC.7, 1-Feb-78 14:51:28, Edit by MCLEAN
;FIX FOR NEW PHYALC,PHYUDB CALLING SEQ
;<4.MONITOR>PHYM2.MAC.6, 31-Jan-78 00:16:42, Edit by MCLEAN
;<4.MONITOR>PHYM2.MAC.5, 30-Jan-78 21:31:17, Edit by MCLEAN
;ADD CREATION OF UDB FOR UNIT GOING ON LINE
;<3.SM10-RELEASE-3>PHYM2.MAC.3, 15-Jan-78 18:24:04, Edit by MCLEAN
;<3.SM10-RELEASE-3>PHYM2.MAC.2, 13-Jan-78 16:09:53, Edit by MCLEAN
;FIX FCE FOR READ
;<3-MONITOR>PHYM2.MAC.50, 11-Nov-77 01:01:42, EDIT BY BOSACK
;CLEAR TM02 IF NOT ALL RECORDS IN A SKIP COMMAND WERE DONE
;<3-MONITOR>PHYM2.MAC.49, 9-Nov-77 09:56:41, EDIT BY KIRSCHEN
;MORE COPYRIGHT UPDATING...
;<3-MONITOR>PHYM2.MAC.48, 12-Oct-77 14:08:56, EDIT BY KIRSCHEN
;UPDATE COPYRIGHT FOR RELEASE 3
;<2BOSACK>PHYM2.MAC.47, 18-Sep-77 05:35:31, EDIT BY BOSACK
;<2BOSACK>PHYM2.MAC.46, 10-Sep-77 21:05:41, EDIT BY BOSACK
;<2BOSACK>PHYM2.MAC.45, 6-Sep-77 04:44:11, EDIT BY BOSACK
;<2BOSACK>PHYM2.MAC.44, 6-Sep-77 01:57:45, EDIT BY BOSACK
;<2BOSACK>PHYM2.MAC.43, 5-Sep-77 06:42:05, EDIT BY BOSACK
;<SM10-MONITOR>PHYM2.MAC.42, 12-Aug-77 12:06:30, Edit by MCLEAN
;<SM10-MONITOR>PHYM2.MAC.41, 12-Aug-77 11:12:11, Edit by MCLEAN
;MAKE FCE ERROR LEGAL FOR EOF ONLY
;<2BOSACK>PHYM2.MAC.40, 28-Jun-77 17:48:49, EDIT BY BOSACK
;<2BOSACK>PHYM2.MAC.39, 10-Jun-77 14:55:35, EDIT BY BOSACK
;FIX CLOBBERED REGISTER IN FTLCHK
;<2BOSACK>PHYM2.MAC.38, 9-Jun-77 15:03:59, EDIT BY BOSACK
;FIX LOW CORE CLOBBER IF STARTIO FAILS DURING ERROR RECOVERY
;<3-MONITOR>PHYM2.MAC.37, 2-May-77 18:48:26, EDIT BY HURLEY
;<2BOSACK>PHYM2.MAC.36, 7-Apr-77 22:06:02, EDIT BY BOSACK
;<2BOSACK>PHYM2.MAC.35, 2-Apr-77 19:58:25, EDIT BY BOSACK
;<2BOSACK>PHYM2.MAC.34, 1-Apr-77 22:01:50, EDIT BY BOSACK
;<2BOSACK>PHYM2.MAC.33, 1-Apr-77 21:54:39, EDIT BY BOSACK
;ADD BLOCKTYPE CODE, START SUPPORT FOR TM03
;<3-MONITOR>PHYM2.MAC.32, 2-Mar-77 14:17:21, EDIT BY BOSACK
;TCO 1748 - FIX WTM ERROR RECOVERY
;<3-MONITOR>PHYM2.MAC.31, 27-Dec-76 17:35:52, EDIT BY HURLEY
;<3-MONITOR>PHYM2.MAC.30, 27-Dec-76 17:27:38, EDIT BY HURLEY
;<2BOSACK>PHYM2.MAC.1, 22-Dec-76 17:53:57, EDIT BY BOSACK
;<2-MONITOR>PHYM2.MAC.28, 29-Nov-76 17:14:40, EDIT BY BOSACK
;TCO 1672 - FIX MTINDX BUG
;<1B-MONITOR>PHYM2.MAC.27, 11-JUN-76 10:24:47, EDIT BY OSMAN
;INILP NOW LEAVES MTINDX CONTAINING NUMBER OF PHYSICAL MTA'S ON SYSTEM
;<2MONITOR>PHYM2.MAC.26, 23-JAN-76 17:59:07, EDIT BY BOSACK
;MCO 22 - ACCOUNT TAPE READ/WRITES IN FRAMES
;<2MONITOR>PHYM2.MAC.25, 19-JAN-76 12:23:57, EDIT BY MURPHY
;<2MONITOR>PHYM2.MAC.24, 9-JAN-76 11:25:44, EDIT BY HURLEY
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976, 1977, 1978 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
SEARCH PROLOG,PHYPAR,SERCOD ;SYSTEM PARAMETERS
TTITLE (PHYM2,,< - DEVICE DEPENDENT CODE FOR TM02/TU45 MAGTAPES VER 62>)
SUBTTL P.KINZELMAN 25 JULY 75
TM2VER==62 ;EDIT VERSION
ENTRY TM2DSP ;FOR LIBRARY SEARCH
;NEED TO PUT IN NOISE RECORD STUFF?
SUBTTL PARAMETERS
;DRIVE REGISTERS USED IN DATAO'S
DO.CS1==0B5 ;DRIVE CONTROL REGISTER
DO.DS==1B5 ;STATUS REGISTER
DO.ER==2B5 ;ERROR REGISTER
DO.MR==3B5 ;MAINTENANCE REGISTER
DO.AS==4B5 ;ATTENTION SUMMARY
DO.FC==5B5 ;FRAME COUNTER
DO.DT==6B5 ;DRIVE TYPE
DO.CK==7B5 ;CHECK CHARACTER REGISTER
DO.SN==10B5 ;SERIAL NUMBER
DO.TC==11B5 ;TAPE CONTROL REGISTER
;DRIVE FUNCTIONS LOADED INTO DRIVE CONTROL REGISTER
DF.NOP==1 ;NO-OP
DF.UNL==3 ;UNLOAD (REWIND OFF-LINE)
DF.REW==7 ;REWIND
DF.CLR==11 ;DRIVE CLEAR
DF.RIPS==21 ;READ-IN, PRESET
DF.ERA==25 ;ERASE
DF.WTM==27 ;WRITE TAPE MARK
DF.SPF==31 ;SPACE FORWARD
DF.SPR==33 ;SPACE REVERSE
DF.WCF==51 ;WRITE CHECK FORWARD (READ FWD)
DF.WCR==57 ;WRITE CHECK REVERSE (READ REV)
DF.WTF==61 ;WRITE FORWARD
DF.RDF==71 ;READ FORWARD
DF.RDR==77 ;READ REVERSE
DXES==200000 ;DISABLE XFER ON ERROR STOP BIT
;DRIVE STATUS REGISTER
DS.ATA==1B20 ;ATTENTION
DS.ERR==1B21 ;COMPOSITE ERROR
DS.PIP==1B22 ;POSITIONING IN PROGRESS
DS.MOL==1B23 ;MEDIUM ON LINE
DS.WRL==1B24 ;WRITE LOCKED
DS.EOT==1B25 ;END OF TAPE
;SPARE
DS.DPR==1B27 ;DRIVE PRESENT
DS.DRY==1B28 ;DRIVE READY (NOT GO)
DS.SSC==1B29 ;SLAVE STATUS CHANGE
DS.PES==1B30 ;PHASE ENCODED STATUS
DS.SDN==1B31 ;SHUTDOWN BIT
DS.IDB==1B32 ;IDENT BURST (FOR PE)
DS.TM==1B33 ;TAPE MARK
DS.BOT==1B34 ;BEGINNING OF TAPE
DS.SLA==1B35 ;SLAVE ATTENTION
;DRIVE ERROR REGISTER
ER.COR==1B20 ;CORRECTABLE DATA/ CRC ERROR
ER.UNS==1B21 ;UNSAFE
ER.OPI==1B22 ;OPERATION INCOMPLETE
ER.DTE==1B23 ;DRIVE TIMING ERROR
ER.NEF==1B24 ;NON-EXISTANT FUNCTION
ER.CS==1B25 ;CORRECTABLE SKEW/ ILLEGAL TAPE MARK
ER.FCE==1B26 ;FRAME COUNT ERROR
ER.NSG==1B27 ;NON-STANDARD GAP (CRAP IN THE GAP)
ER.LRC==1B28 ;LRC ERROR/ FORMAT (PREAMBLE POSTAMBLE) ERROR
ER.INC==1B29 ;INCORRECTABLE DATA/ VERTICAL PARITY ERROR
ER.DPA==1B30 ;DATA BUS PARITY ERROR
ER.FMT==1B31 ;FORMAT ERROR
ER.CPA==1B32 ;CBUS PARITY ERROR
ER.RMR==1B33 ;REGISTER MODIFICATION REFUSED
ER.ILR==1B34 ;ILLEGAL REGISTER ADDRESS
ER.ILF==1B35 ;ILLEGAL FUNCTION
;DRIVE TYPE BITS NEEDED:
DT.SPR==1B25 ;A SLAVE IS SELECTED
SUBTTL DEVICE DEPENDANT TABLE DEFS
;****************************
;UDB EXTENSIONS
TU6EPS==UDBDDP ;ERROR POSITION
TU6EBP==TU6EPS+1 ;ERROR BYTE POINTER
TU6EBC==TU6EBP+1 ;ERROR BYTE COUNTER
TU6ECL==TU6EBC+1 ;TAPE CLEANER FLAG
LU.TM2==TU6ECL+1 ;LENGTH OF TM02 UDB
;****************************
;KDB DEVICE DEPENDANT PORTION
KDBUDB==KDBDDP ;UDB TABLE (FOR 8 UNITS)
TM2ADR==KDBUDB+^D8 ;MASSBUS ADDRESS OF TM02
SAVUDB==TM2ADR+1 ;CURRENT UDB (0 IF NONE)
TM.CNI==SAVUDB+1 ;CONI OF RH GOES HERE
TM.CS1==TM.CNI+1 ;DATAI RH CONTROL REGISTER
TM.DBF==TM.CS1+1 ;DATAI RH DATA REGISTER
TM2REG==TM.DBF+1 ;DRIVE REGISTERS GO HERE
DR.CS1==0 ;DRIVE CONTROL REGISTER
DR.DS==1 ;STATUS REGISTER
DR.ER==2 ;ERROR REGISTER
DR.MR==3 ;MAINTENANCE REGISTER
DR.AS==4 ;ATTENTION SUMMARY
DR.FC==5 ;FRAME COUNTER
DR.DT==6 ;DRIVE TYPE
DR.CK==7 ;CHECK CHARACTER REGISTER
DR.SN==10 ;SERIAL NUMBER
DR.TC==11 ;TAPE CONTROL REGISTER
LK.TM2==TM2REG+12 ;LENGTH OF KDB
SUBTTL TM02 ERROR RECOVERY DEFS
;PRESENTLY, IF YOU BACKSPACE INTO BOT, YOU MUST WAIT 8 SEC
;TO REGAIN CONTROL OF THE DRIVE AGAIN (OPI TIMEOUT) BY GETTING AN INT.
;THE DRIVES WILL HOPEFULLY BE FIXED SOMEDAY. UNTIL THEN,
;THIS HANDLER TRIES VERY HARD TO KEEP FROM HITTING BOT
;ON A TAPE CLEAN SEQUENCE IF OPIFIX = 0. MAKE OPIFIX NOT 0
;WHEN THE DRIVES ARE FIXED TO GIVE AN INTERRUPT AS SOON AS THEY
;HIT BOT. (TAPE WILL CLEAN BETTER IF YOU LET THE DRIVE HIT
;BOT.)
OPIFIX==0
;RETRY COUNTS:
CLNREC==5 ;SP REVERSE THIS NR RECORDS TO HIT CLEANER
RTYOP==5 ;RETRY OPERATION THIS MANY TIMES BEFORE TAPE CLEAN SEQUENCE
RTYCLN==5 ;RETRY CLEAN SEQUENCE THIS MANY TIMES ON READ
;BEFORE GIVING UP
;THE TOTAL NR OF RD RETRIES = RTYOP*(RTYCLN+1)
RTYWRT==^D20 ;# WRITE RETRIES MAXIMUM BEFORE ABORT
;ERROR WORDS
; TU6EBC ;ERR BYTE COUNTER (USED IF WE HIT BOT
;DURING TAPE CLEAN SEQUENCE)
; TU6EBP ;ERR BYTE POINTER
; TU6ECL ;-1= IN TAPE CLN SEQUENCE, 0= NOT
; UDBERR(RH) ;CURRENT FUNCTION (1 - 17)
;ON RETRY OF ORIGINAL OPERATION, THIS LOC
;MUST BE SET TO THE ORIGINAL OPERATION
; UDBERC ;RETRY COUNT
;CONVERTED TO # RETRIES DONE AT END
; TU6EPS ;WE SHOULD BE HERE WHEN WE'RE
;READY TO RETRY OPERATION
SUBTTL DISPATCH FOR TM02
TM2DSP::JRST TM2INI ;0 - INITIALIZATION
JRST TM2SIO ;1 - START I/O
JRST TM2INT ;2 - HANDLE INTERRUPT (DATA OPERATION OR SPACE)
JRST TM2ERR ;3 - ERROR RECOVERY
JRST TM2HNG ;4 - HUNG DEVICE
RET ;5 - NOT USED
RET ;6 - NOT USED
JRST TM2SIO ;7 - START POSITION OPERATION
JRST TM2ATN ;10 - ATTENTION INTERRUPT (CALLED AS MANY
;TIMES AS THERE ARE TM02 DRAS BITS UP)
JRST TM2PRQ ;11 - SKIP IF POSITION REQUIRED
RET ;12 - STACK SECOND COMMAND, FAIL FOR TM02/3
TM2HNG: MOVX T1,IS.NRT!IS.ERR!IS.DVE ;SET FATAL BITS
IORM T1,IRBSTS(P4) ;AND REFRESH IT
RET
;HERE TO DETERMINE IF THIS REQUEST SHOULD GO ON PWQ OR TWQ
TM2PRQ: LDB T1,IRYFCN ;GET FUNCTION
MOVE T1,TM2FTB(T1) ;GET TABLE ENTRY
TXNN T1,TB.DOP ;DATA OPERATION?
RETSKP ;NO - POSITION ALWAYS REQUIRED
HRRZ T2,UDBPWQ(P3) ;YES - ANY PENDING POSITION OPERATIONS?
JUMPE T2,R ;NONE - APPEND TO TWQ
CAIN T2,(P4) ;AT HEAD OF PWQ?
RET ;YES - NEXT TRANSFER
RETSKP ;APPEND TO PWQ
;ROUTINE TO READ ALL TM02 REGISTERS INTO TM2REG IN THE KDB
TM2RDR: MOVSI T4,-LK.TM2+TM2REG ;-# REGISTERS
TM2RD1: SETZM T2 ;CLEAR REGISTER ADDRESS
DPB T4, [POINT 6,T2,5] ;SETUP REGISTER ADDRESS
CALL RDREG ;READ THE REGISTER
ADD T4,P2 ;POINT TO KDB
MOVEM T1,TM2REG(T4) ;STORE IT IN THE KDB
SUB T4,P2 ;BACK TO RELATIVE POINTER
AOBJN T4,TM2RD1 ;GO BACK FOR REST OF REGISTERS
CALL ERRCNI ;GET CONI AND DATAI
MOVEM T1,TM.CNI(P2) ;SAVE IN KDB
MOVEM T2,TM.CS1(P2) ; ...
MOVEM T3,TM.DBF(P2) ; ...
RET
SUBTTL TM02 INITIALIZING ROUTINE
;THIS ROUTINE IS CALLED ONCE PER TM02 DRIVE ON THE SYSTEM
;SET UP UDB'S - 1 PER DRIVE ON THE TM02
;INPUT C(P1)=CDB C(Q2)=UNIT NR; OUTPUT P2,P3
TM2INI: SAVEQ ;SAVE REGISTERS
MOVX T1,LK.TM2 ;LENGTH OF KDB
CALL PHYALC ;RESERVE SPACE
RET ;RETURN IF NO SPACE FOUND
MOVEM T1,P2 ;SAVE ADDRESS IN PROPER AC
MOVE P3,T1 ;COPY KDB
MOVEI T1,.BTKDB ;MARK AS KDB
DPB T1,USYBKT ; ...
MOVX T2,DO.DT ;GET DRIVE TYPE REG
CALL RDREG3 ; ...
ANDI T1,777 ;GET JUST TYPE CODE
CAIG T1,TY.T2H ;IS THIS A TM02?
CAIGE T1,TY.T2L ; ???
SKIPA T1,[EXP .UTTM3] ;NO - IS TM03
MOVX T1,.UTTM2 ;YES - SET UP UNIT TYPE IN KDB
STOR T1,USTYP,(P2) ;...
UNINI: MOVSI T1,-10 ;SET UP AOBJN INDEX LH
HRRI T1,KDBUDB(P2) ;MAKE RH POINT TO UDB ENTRIES IN KDB
MOVEM T1,KDBIUN(P2) ;INITIAL POINTER
MOVEM T1,KDBCUN(P2) ;CURRENT POINTER
HRRZM Q2,TM2ADR(P2) ;SAVE KDB ADDRESS
MOVEI T1,TM2DSP ;INSERT DISPATCH VECTOR
MOVEM T1,KDBDSP(P2) ; ...
MOVSI Q1,-10 ;SLAVE INDEX
INILP: CALL INIUNI ;INITIALIZE A SINGLE UNIT
JFCL ;IGNORE ERROR RETURN
NODRV: AOBJN Q1,INILP ;TRY NEXT SLAVE
TOORET: MOVE T1,P2 ;TELL RETURN TO PUT KDB INTO CDB
RET
;THIS ROUTINE IS CALLED TO INITIALIZE A SPECIFIC SLAVE
;INPUT C(P1)=CDB C(Q1)=UNIT C(P2)KDB NR; OUTPUT P3
INIUNI: HRRZ T2,Q1 ;GET CURRENT SLAVE #
HRLI T2,(DO.TC) ;SET UP FOR TAPE CNTL REGISTER
CALL WTREG3 ;DO IT
MOVX T2,DO.DT ;GET DRIVE TYPE
CALL RDREG3
TXNN T1,DT.SPR ;DOES IT EXIST?
RET ;NOPE
HRLOI T3,-MTAN-1 ;IF 1ST TIME THRU
INIUN1: AOBJP T3, [BUG(INF,TM2N2S,<PHYM2 - MORE DRIVES THAN TABLE SPACE, EXCESS IGNORED>)
JRST TOORET] ;DON'T INITIALIZE ANY MORE SLAVES
SKIPE MTCUTB(T3) ;CHECK TO SEE IF UNIT FREE
JRST INIUN1 ;NOPE TRY NEXT ONE
MOVEM T3,MTINDX ;SAVE CURRENT LOGICAL INDEX
MOVE T3,[TM2DSP,,LU.TM2] ;YES, SET UP ADDRESS,,LENGTH
ADD P2,Q1 ;POINT TO PROPER KDB ENTRY
CALL PHYUDB ;AND ASK FOR UDB ALLOCATION
RET ;RETURN IF NO SPACE FOUND
HRRZM P3,KDBUDB(P2) ;SAVE LINK
SUB P2,Q1 ;FUDGE IT BACK
HRRZM P2,UDBKDB(P3) ;SAVE BKWDS LINK
MOVE T3,MTINDX ;GET CURRENT LOGICAL INDEX
HRLZM P1,MTCUTB(T3) ;SAVE LINK TO CDB IN LOGICAL TABLE
HRRM P3,MTCUTB(T3) ;SAVE LINK TO UDB
MOVX T2,DO.DS ;GET DRIVE STATUS
CALL RDREG3
MOVX T3,US.TAP ;INDICATE A TAPE TYPE DEVICE
TXNN T1,DS.MOL ;ON LINE?
TXO T3,US.OFS ;NO, SET OFF LINE BIT
TXNE T1,DS.WRL ;WRITE LOCKED?
TXO T3,US.WLK ;YES
HLLM T3,UDBSTS(P3) ;SAVE UDB STATUS
MOVX T3,.UTT45 ;UNIT TYPE
STOR T3,USTYP,(P3) ;SAVE IT
MOVX T3,UC.200!UC.556!UC.800!UC.160!UC.CD!UC.AA!UC.IC ;DENSITYS AND MODES DRIVE IS CAPABLE OF
MOVEM T3,UDBCHR(P3) ; AND PUT THAT INFO INTO THE UDB
MOVX T2,DO.SN ;NOW SERIAL NR
CALL RDREG
CALL PHCVBO ;CONVERT BCD TO OCTAL
MOVEM T1,UDBDSN(P3) ;STORE IT
HRRZM Q1,UDBSLV(P3) ;SET UP SLAVE ADDRESS
AOS JB0FLG ;THIS WILL REQUEST JOB0 INCASE CALLER SETS MTAJB0
RETSKP ;RETURN
SUBTTL START I/O ROUTINE
;C(P4)=IORB C(P1)=CDB C(P2)=KDB C(P3)=UDB
;IF IN ERR RECOVERY, GET FN FROM RH(UDBERR)
;RET MEANS RE-CALL IN 1 MIN TO TRY AGAIN
;PUTS TM02 FN IN Q1, AND DATAO (IF NEEDED) IN T2
;RETSKP (CHSTRT) MEANS OK, IT'S STARTED
TM2SIO: HRRZ Q1,UDBERR(P3) ;GET FUNCTION IF ERROR RECOVERY
SKIPN Q1 ;IN ERROR RECOVERY?
LOAD Q1,ISFCN,(P4) ;NO, GET FN FROM IORB
SKIPG Q1,TM2FTB(Q1) ;VALID FN?
JRST BADSIO ;REFUSE TO START IT
SKIPGE IRBSTS(P4) ;MAKE SURE PAGEM NOT SET
JRST BADSIO ;IS SET REFUSE IT
CALL TM2CON ;CONNECT TO DRIVE (AND CLEAR ERRORS)
RET ;ERROR
MOVX T2,DO.FC ;IN CASE WE DON'T WANT TO LOAD FC
TXNE Q1,TB.NFC ;DO WE LOAD FC WITH SOMETHING SPECIAL?
JRST NOFC ;NO- LOAD 0
TXNN Q1,TB.DOP ;DATA OPERATION?
JRST TM2NDO ;NO, T2=-#RECORDS ON SPACE
MOVN T2,IRBCNT(P4) ;BYTE COUNT FROM IORB
LOAD T1,IRBDM,(P4) ;GET DATA MODE
HLRZ T1,MTBFMT(T1) ;GET MULTIPLIER
SKIPE T1 ;SAVE TIME IF FRAMES=BYTES
IMUL T2,T1 ;CALCULATE # FRAMES
JRST TM2DO ;WE'RE A DATA OPERATION
BADSIO: BUG(CHK,PM2SIO,<PHYM2 - ILLEGAL FUNCTION AT START IO>)
MOVX T1,IS.ERR!IS.NRT!IS.DVE ;MARK AN ERROR OCCURED
IORM T1,IRBSTS(P4) ;IN IORB
RET
TM2NDO: SKIPE UDBERR(P3) ;IN ERROR RECOVERY?
SKIPA T2,[-1] ;YES, SPACE 1 RECORD
MOVN T2,IRBCNT(P4) ;NO, DO # RECORDS FROM IORB
TM2DO: ANDI T2,177777 ;16 BITS OF FRM COUNT
HRLI T2,(DO.FC) ;DO FRM COUNT TO FRM COUNT REGISTER
NOFC: ANDI Q1,77 ;6 BITS OF TM02 FN
HRRZM P3,SAVUDB(P2) ;SAVE CURRENT UDB IN KDB
JRST CHSTRT ;NOW START THINGS MOVING
;ROUTINE TO SELECT A SLAVE, SET UP TCREG
;CHECK FOR NECESSARY STATUS BITS
;CALL IT TO BEGIN AN OPERATION WITH C(Q1)=FN TABLE ENTRY
;RET WITH BITS SET IF NOT RDY (OFF-LINE, ETC.) RETSKP IF ALL OK
TM2CON: MOVX T2,US.IDB ;THE IDB SEEN BIT
ANDCAM T2,UDBSTS(P3) ;CLR THE BIT IN THE UDB
MOVX T2,DO.DS ;READY TO READ STATUS REG
CALL RDREG ;READ IT
TXNN T1,DS.ERR!DS.SSC ;IS ERROR IR SSC UP?
JRST TM2CNO ;NO, DON'T DO DRIVE CLR
MOVX T2,DO.TC ;YES, DO DRIVE CLR
HRR T2,UDBSLV(P3) ;BUT FIRST SELECT DRIVE ABOUT TO BE USED
CALL WTREG ;BECAUSE WE KNOW IT'S NOT BUSY
MOVEI T4,^D10 ;COUNT OF ATTEMPTS TO CLEAR ERR
CON1: MOVX T2,DF.CLR ;FIRST CLEAR OUT DRIVE
CALL WTREG ;DO IT
MOVX T2,DO.DS ;SELECT STATUS
CALL RDREG
TXNE T1,DS.ERR ;IS ERROR UP?
JRST [ SOJG T4,CON1 ;RETRY EXHAUSTED?
RET] ;CANT START IO
CALL TM2POL ;CHECK FOR REWIND DONE
TM2CNO: HRRZ T2,UDBSLV(P3) ;GET SLAVE #
HRLI T2,(DO.TC) ;SELECT TAPE CNTL REGISTER
LOAD T1,IRBDN,(P4) ;GET DENSITY
CAIG T1,4 ;TOO BIG?
SKIPGE T1,MTBDEN(T1) ;OR ILLEGAL?
JRST [MOVX T1,IS.ERR!IS.NRT!IS.DVE ;IF ILLEGAL, TREAT AS HARD ERR
IORM T1,IRBSTS(P4) ;STORE THE STATUS
RET]
DPB T1,[POINT 3,T2,27] ;SET IN POSITION IN ACC
LOAD T1,IRBPAR,(P4) ;GET PARITY
DPB T1,[POINT 1,T2,32] ;SET IN POSITION
LOAD T1,IRBDM,(P4) ;GET DATA MODE
CAIG T1,4 ;TOO BIG?
SKIPGE T1,MTBFMT(T1) ;OR ILLEGAL?
JRST [MOVX T1,IS.ERR!IS.NRT!IS.DVE ;IF ILLEGAL, TREAT AS HARD ERR
IORM T1,IRBSTS(P4) ;STORE THE STATUS
RET]
DPB T1,[POINT 4,T2,31] ;SET FMT
CALL WTREG ;FIRE 1!
MOVX T2,DO.DS
CALL RDREG ;GET STATUS IN T1
SETZM T2 ;STATUS COMPARISON MSK
TXNE Q1,TB.WRT ;IS IT A WRITE OPERATION (TBL ENTRY IN Q1)
TXO T2,DS.WRL ;YES, NEED WRL=0
TXO T2,DS.MOL!DS.DRY ;ALWAYS REQUIRE THESE BITS
TXC T1,DS.MOL!DS.DRY ;NEED ALL THESE BITS TO BE 1 SO INVERT
TDNN T1,T2 ;GOOD STATUS?
RETSKP ;YES, DONE
MOVX T2,US.WLK!US.OFS ;SET UP THESE BITS
ANDCAM T2,UDBSTS(P3) ;1ST CLEAR THEM
TXNN T1,DS.WRL ;WRITE LOCKED?
TXZ T2,US.WLK ;YES
TXNN T1,DS.MOL ;ON LINE? (WE COMPL'ED DS.MOL ABOVE)
TXZ T2,US.OFS ;YES, CLEAR BIT
IORM T2,UDBSTS(P3) ;SET STATUS IN UDB
MOVX T2,IS.WLK ;FIX THIS BIT IN IORB
ANDCAM T2,IRBSTS(P4) ;1ST CLEAR IT
TXNE Q1,TB.WRT ;WRITE OPERATION?
TXNN T1,DS.WRL ;AND WRITE LOCKED?
SKIPA ;NO
TXO T2,IS.ERR!IS.NRT!IS.DVE ;YES, SET ERROR BITS
TXNN T1,DS.WRL ;WRITE LOCKED?
TXZ T2,IS.WLK ;YES, CLEAR BIT
IORM T2,IRBSTS(P4) ;DO IT
RET ;FINISHED
SUBTTL ENTER HERE FROM RH20 COMMAND DONE INTERRUPT
;C(P1)=CDB C(P2)=KDB
TM2INT: PUSH P,Q2 ;LATER DON'T SAVE TILL AFTER FTLCHK
PUSH P,Q1 ;LIKEWISE, I'M SURE
SKIPN P3,SAVUDB(P2) ;DO WE HAVE A CURRENT UDB?
JRST TM2INU ;NO UDB
SETZM SAVUDB(P2) ;CLEAR THE CURRENT UDB
CALL SETIRB ;GET ACTIVE IORB
CALL FTLCHK ;CHECK FOR FATAL ERRS AND PUT DRDS REGISTER
JRST [POP P,Q1 ;INTO Q2, TM2FTB FN ENTRY INTO Q1
POP P,Q2
RET] ;FATAL ERR
TXNN Q1,TB.WRT ;ARE WE READING?
TXZ T1,ER.NSG ;YES, IGNORE NSG ERR
TMENTY: TXNE Q1,TB.REV ;ARE WE BACKWARDS?
SOSA UDBPS2(P3) ;YES, THEN SUBTRACT 1 RECORD
AOS UDBPS2(P3) ;NO, ADD 1
HRRM T1,Q1 ;SAVE ERROR REGISTER (LH OF Q1 IS FLAGS)
TXNN Q2,DS.TM ;IS IT TAPE MARK?
JRST NOTM ;NOT TM
TXNE Q1,TB.REV ;ARE WE REVERSE
SOSA UDBPS1(P3) ;YES, BACK UP 1 FILE
AOS UDBPS1(P3) ;NO, FORWARD 1 FILE
NOTM: TXNN Q2,DS.BOT ;ARE WE AT BOT?
JRST NOBOT ;NO
SETZM UDBPS1(P3) ;YES, FILE 0
SETZM UDBPS2(P3) ;RECORD 0
NOBOT: TXNE Q2,DS.PES ;ARE WE IN PE MODE?
TXNE Q1,TB.WRT ;AND READ?
SKIPA ;NO
TXZ Q1,ER.COR!ER.CS ;YES, THESE ARE NOT ERRORS
TXNE Q1,TB.RD ;ON READ FCE IS LEGAL
TXZ Q1,ER.FCE
TXNN Q1,ER.COR!ER.CS!ER.FCE!ER.NSG!ER.LRC!ER.DPA!ER.INC ;RETRY?
JRST CKCONI ;NO DATA RETRY ERRS HERE
DORTY: TXNE Q1,TB.RD ;IN READ?
TXNN Q2,DS.TM ;AND TM?
SKIPA ;NO
JRST NODERS ;YES, THEN DON'T RETRY
MOVX T3,IS.ERR!IS.DTE ;YES, ERROR- DO RETRY
IORM T3,IRBSTS(P4) ;SET IORB ERR (DATA ERR)
CALL TM2RDR ;GET DEVICE REGISTERS
JRST POPPOL ;POP STACK AND POLL SLAVES
;DON'T BOTHER SETTING UP STATUS BITS
;HERE WHEN DONE INTERRUPT AND NO SAVED UDB
TM2INU: BUG(CHK,TM2NUD,<PHYM2 - CHANNEL DONE INTERRUPT BUT NO UNIT ACTIVE>)
JRST POPPOL ;CLEAN UP STACK
CKCONI: TXNN Q1,TB.DOP ;DATA OPERATION?
JRST NODERS ;NO - DONT ASK CHANNEL IF ANY ERRS
CALL CKERR ;SEE IF ANY RETRIABLE ERRS IN CONI
JRST DORTY ;YES, RETRY THE TRANSFER
NODERS: TXNN Q1,TB.RD ;ARE WE READING?
JRST SPENTY ;NO, DON'T TELL ABT FRM COUNT
MOVX T2,DO.FC ;GET FRM COUNT
CALL RDREG
ADDM T1,UDBRED(P3) ;ACCUMULATE FRAMES READ
LOAD T3,IRBDM,(P4) ;GET DATA MODE
CAIG T3,4 ;LEGAL?
SKIPGE T3,MTBFMT(T3) ;AGAIN?
JRST [ BUG(CHK,TM2IDM,<PHYM2 - ILLEGAL DATA MODE AT DONE INT>)
MOVEI T3,0 ;ACT LIKE WORDS
JRST .+1]
HLRZ T3,T3 ;#FRAMES/BYTE
JUMPE T3,NODIV ;SAVE TIME IF FRAMES=BYTES
IDIV T1,T3 ;CALCULATE # BYTES
SKIPE T2 ;REMAINDER?
AOS T1 ;YES, ANOTHER BYTE
NODIV: MOVEM T1,IRBCNT(P4) ;TELL HOW MANY FRAMES ON READ
SPENTY: TXNN Q1,TB.WRT ;WRITE?
JRST NOTWRT ;NO
LOAD T3,IRBDM,(P4) ;GET DATA MODE
HLRZ T3,MTBFMT(T3) ;GET FRAMES/BYTE
SKIPN T3 ;FRAMES=BYTES
SKIPA T3,IRBCNT(P4) ;YES. JUST GET THE COUNT OF BYTES THEN
IMUL T3,IRBCNT(P4) ;GET FRAMES
ADDM T3,UDBWRT(P3) ;ACCUMULATE FRAMES WRITTEN
NOTWRT: MOVX T2,IS.BOT!IS.EOT!IS.TPM!IS.WLK ;ZERO BITS
ANDCAM T2,IRBSTS(P4) ;DO IT TO IT
TXNN Q2,DS.BOT ;AT BOT?
TXZ T2,IS.BOT ;NO
TXNE Q1,TB.WRT ;ARE WE WRITING?
TXNN Q2,DS.EOT ;AND AT EOT?
TXZ T2,IS.EOT ;NO TO EITHER
TXNN Q2,DS.TM ;TP MK
TXZ T2,IS.TPM ;NO, CLEAR TM FLAG
TXNE Q1,TB.REV ;SPACE REVERSE OR READ REVERSE
TXNN Q2,DS.BOT ;AND AT BOT?
SKIPA ;NO TO EITHER
TXO T2,IS.TPM ;YES TO BOTH, RETURN TAPE MARK
TXNN Q2,DS.WRL ;WRITE LOCKED?
TXZ T2,IS.WLK ;NO
IORM T2,IRBSTS(P4) ;AND SAVE IT (LEAVE ERR SET IF IT WAS SET)
MOVX T2,US.OFS!US.BOT ;CLEAR THESE BITS
ANDCAM T2,UDBSTS(P3) ;DO IT
TXNE Q2,DS.MOL ;ON LINE?
TXZ T2,US.OFS ;YES, CLR BIT
TXNN Q2,DS.BOT ;AT BOT?
TXZ T2,US.BOT ;NO, CLEAR BIT
TXNE Q2,DS.IDB ;IS THE STATUS REG IDB BIT SET?
TXNE Q1,TB.WRT ;AND ARE WE READING?
SKIPA ;NO, DON'T SET BIT
TXO T2,US.IDB ;YES, DO SET BIT
IORM T2,UDBSTS(P3) ;SAVE IT
TXNE Q1,TB.DOP ;IF A DATA OPERATION,
AOS -2(P) ;SKIP RETURN TO THE CHANNEL
JRST POPPOL ;ANYBODY DONE A REWIND?
;AND THEN A WORD FROM OUR SPONSOR...
;COMES HERE ON AN ATA INTERRUPT (INCLUDING SPACING OPS)
;C(P1)=CDB C(P2)=KDB
;WILL SET C(P4)= 0 IF NONE
;SETS C(P3)=UDB
;ALWAYS RET (NEVER SKP RET'S)
;IF ERR, IS.ERR AND EITHER <IS.DVE OR IS.DTE> WILL BE SET
;IF IS.ERR NOT SET, WE ARE FINISHED WITH THIS IORB
TM2ATN: PUSH P,Q2 ;SAVE Q2
MOVE Q2,TM2ADR(P2) ;GET OUR MASSBUS ADDRESS
MOVX T2,1
LSH T2,(Q2) ;MASK TO CLEAR OUR ATTENTION BIT
HRLI T2,(DO.AS) ;REGISTER ADDRESS
CALL WTREG3 ;CLEAR THE BIT
PUSH P,Q1
HRRZ P3,SAVUDB(P2) ;GET ACTIVE UDB (IF ANY)
JUMPE P3,CHKNEW ;IF NO UDB, JUST CHECK FOR REWS AND UNITS ON LINE
MOVX T1,US.ACT ;UNIT ACTIVE?
TDNE T1,UDBSTS(P3) ; ??
JRST CKNDOP ;YES - FINISH UP THEN POLL
HRRZ Q1,UDBADR(P3) ;GET UNIT ADDRESS
MOVE P3,TM2ADR(P2) ;GET KONTROLLER ADDRESS
HRRZ T1,CDBADR(P1) ;GET CHANNEL ADDRESS
BUG(INF,TM2UNA,<PHYM2 - DONE INTERRUPT AND UDB NOT ACTIVE>,<Q1,P3,T1>)
SETZB P3,SAVUDB(P2) ;RESET SAVED UDB
JRST POPPOL ;AND GO POLL
CKNDOP: CALL SETIRB ;GET CURRENT IORB
HRRZ Q1,UDBERR(P3) ;GET FUNCTION CODE
SKIPN Q1 ;IN ERROR RECOVERY?
LOAD Q1,ISFCN,(P4) ;NO, GET IT FROM IORB
MOVE Q1,TM2FTB(Q1) ;GET FUNCTION ENTRY
TXNN Q1,TB.DOP ;DATA OPERATION?
JRST NDOP ;NO
;THE FOLLOWING COMMENTED CODE CAUSES THE 2020 TO GET INTO AN
;INTERRUPT LOOP SINCE THE OPERATION APPEARS NOT TO BE CORRECTLY TERMINATED
; MOVX T2,DO.DS ;CHECK IF DEVICE STILL ON LINE
; CALL RDREG ; ...
; TXNN T1,DS.MOL ;ONLINE?
; JRST NDOP ;NO - TREAT AS IF TERMINATING NONDATA OP
MOVEI P4,0 ;YES, ENSURE RECALL AT INTERRUPT ENTRY
JRST TM2ATX ;AND EXIT ATN
NDOP: SETZM SAVUDB(P2) ;CLEAR SAVED UDB
CALL FTLCHK ;ANY FATAL ERRORS? (PUT DRIVE STATUS IN Q2,
TM2ATX: JRST [POP P,Q1 ;YES TM2FTB ENTRY IN Q1)
POP P,Q2
RET] ;FATAL ERR
TXNE Q1,TB.TM ;WRITE TM OPERATION?
JRST TMENTY ;YES, USE DATA ROUTINES
TXNE Q1,TB.ERA ;ERASE OPERATION?
JRST SPENTY ;YES, DON'T CHECK TAPE POSITION
TXNE Q1,TB.REW ;REWIND?
JRST REWSTA ;YES, CLEAR REC CNTRS
MOVX T2,DO.FC
CALL RDREG
MOVN T3,T1 ;NEGATE FRM COUNT
ANDI T3,177777 ;ITS ONLY 16 BIT NEG NR
SKIPE T1,UDBERR(P3) ;ARE WE IN ERR RECOVERY?
JRST RTYATN ;YES
EXCH T3,IRBCNT(P4) ;SAVE RESIDUE (# RECORDS NOT SPACED)
SUB T3,IRBCNT(P4) ;CALCULATE # RECORDS MOVED
TXNE Q1,TB.REV ;IN REVERSE DIR?
MOVNS T3 ;YES, NEGATE
ADDM T3,UDBPS2(P3) ;UPDATE REC COUNT
MOVE T3,IRBCNT(P4) ;GET FRM COUNT AGAIN
JUMPE T3,NOCKER ;IF ALL RECORDS SPACED, DON'T CHECK ERR
RES1: TXNN Q2,DS.BOT!DS.EOT!DS.TM ;EARLY TERM OK IF EOT, BOT, OR TM
RESERR: JRST [ MOVX T1,IS.ERR!IS.DVE!IS.NRT ;INDICATE ERRORS
IORM T1,IRBSTS(P4)
CALL TM2RDR ;GET DEVICE REGISTERS
JRST SPENTY]
PUSH P,Q2 ;MUST EXPLICITLY CLEAR TM02 HERE
MOVE Q2,TM2ADR(P2) ;GET DEVICE ADDRESS
MOVX T2,DF.CLR ;CLEAR
CALL WTREG3 ; ...
POP P,Q2
; ...
; ...
;ALL RECORDS SPACED, DON'T BOTHER CHKING ERROR BITS
NOCKER: TXNN Q2,DS.TM ;TAPE MK?
JRST NOSTM ;NO
TXNE Q1,TB.REV ;IN REVERSE DIR?
SOSA UDBPS1(P3) ;YES, THEN -1
AOS UDBPS1(P3) ;NO, THEN +1 FILE
NOSTM: TXNN Q2,DS.BOT ;AT BOT?
JRST SPENTY ;NO
REWENT: SETZM UDBPS2(P3) ;YES, ZERO RECORDS
SETZM UDBPS1(P3) ;ZERO FILES
JRST SPENTY ;NOW SET STATUS AND RET
REWSTA: MOVX T1,US.REW ;SET REWINDING
IORM T1,UDBSTS(P3) ; IN THE UDB
JRST REWENT ;
POPPOL: POP P,Q1 ;RESTORE REGISTERS
POP P,Q2
JRST TM2POL ;AND CHECK FOR REWIND INTERRUPTS
;COME HERE AT END OF SPACE DURING RETRY
RTYATN: JUMPN T3,RESERR ;FRAME COUNT 0?
TXNN Q1,TB.REV ;IN REVERSE DIRECTION?
AOSA UDBPS2(P3) ;NO FORWARD THE RECORD COUNTER
SOS UDBPS2(P3) ;YES, BACK IT UP
TRNN Q2,DS.BOT ;AT BOT?
JRST NOCKER ;NO, CONT
JRST RESERR ;CONFUSED ERROR RECOVERY
CHKNEW: MOVE T4,KDBIUN(P2) ;GET AOBJN POINTER
CHKNW1: SKIPE (T4) ;EXIST?
JRST CHKNW2 ;YUP DON'T BOTHER WITH IT
MOVE Q1,T4 ;GET UNIT NUMBER
SUB Q1,KDBIUN(P2)
HRRZS Q1 ;UNIT ONLY
CALL INIUNI ;INITALIZE UNIT
SKIPA ;NOT FOUND
AOS MTAJB0 ;TELL JOB0 ABOUT IT
CHKNW2: AOBJN T4,CHKNW1 ;GET NEXT UNIT
JRST POPPOL ;DO POLLING
;ROUTINE TO CHECK FOR ANY OBVIOUS FATAL ERRORS
;RET IF ERR (WITH IORB STATUS BITS SET)
;SKP RET IF OK
;RETURNS WITH C(T1) THE ERROR REGISTER, C(Q2) DRIVE STATUS REGISTER
;AND C(Q1) THE TABLE ENTRY FOR CURRENT
;FTLCCHK MUST NOT BE CALLED UNLESS AN IORB EXISTS FOR THE UNIT
FTLCHK: MOVX Q1,IS.DVE!IS.DTE ;READY TO CLEAR THESE BITS
ANDCAM Q1,IRBSTS(P4) ;DO IT TO IT
HRRZ T4,UDBERR(P3) ;GET FUNCTION IF ERROR RECOVERY
SKIPN T4 ;IN ERROR RECOVERY?
LOAD T4,ISFCN,(P4) ;GET FN
SKIPG Q1,TM2FTB(T4) ;VALID?
JRST [ BUG(CHK,TM2IF2,<PHYM2 - ILLEGAL FUNCTION ON COMMAND DONE>)
JRST FTLERR]
MOVSI T2,(DO.ER) ;GET ERROR REGISTER
CALL RDREG ; ...
TXNN T1,ER.RMR!ER.UNS!ER.FMT!ER.DTE!ER.ILR!ER.ILF!ER.CPA ;FATAL ERRS
JRST DOPCK ;NO FATAL ERRORS HERE
FTLERR: CALL TM2RDR ;READ ALL REGISTERS
MOVX T3,US.OFS ;GET OFF LINE
MOVE T1,TM2REG+DR.ER(P2) ;GET ERROR REG AGAIN
TXNE T1,ER.UNS ;UNS ERR?
IORM T3,UDBSTS(P3) ;YES, SET OFF-LINE BIT
MOVX T3,IS.NRT!IS.ERR!IS.DVE ;SET BITS
IORM T3,IRBSTS(P4) ;PUT BITS IN IRBSTS
HRRZ T1,TM2REG+DR.DS(P2) ;GET STATUS REG
MOVX T3,IS.WLK ;CLEAR STATUS BIT
ANDCAM T3,IRBSTS(P4) ;CLEAR WRITE LOCK BIT
TXNE T1,DS.WRL ;WRITE LOCKED?
IORM T3,IRBSTS(P4) ;YES, SET THE BIT AGAIN
JRST TM2POL ;REWINDS DONE? (THEN RET)
DOPCK: MOVE Q2,T1 ;SAVE ERROR REGISTER
MOVSI T2,(DO.DS) ;GET DRIVE STATUS REGISTER
CALL RDREG ; ...
EXCH Q2,T1 ;PUT DS IN Q2, ER IN T1
TXNE Q1,TB.RD ;ON READ FCE IS LEGAL (IT IS SHORT RECORD)
JRST DOPCK1
TXNE Q1,TB.DOP ;DATA OPERATION?
TXNE Q2,DS.TM ;EOF ERROR (EOF CAUSES FCE ON RH11)
JRST DOPCK1 ;NON DATA OR EOF -- ALL OK
TXNE T1,ER.FCE ;FRAME COUNT ERROR CHECK
JRST FTLERR ;FATAL ERROR ON DATA OPERATIONS
DOPCK1: CAIE T4,IRFRUN ;UNLOAD FUNCTION?
TXNE Q2,DS.MOL ;NO, MEDIUM ON LINE?
SKIPA ;YES, OK
JRST FTLERR ;NO - QUITE FATAL.
TXNN T1,ER.OPI!ER.NEF ;OPI OR NEF?
RETSKP ;OK RET, NO ERR
TXNE Q1,TB.REV ;IF ERRS, OK IF REVERSE
TXNN Q2,DS.BOT ;AND AT BOT
JRST FTLERR ;BAD RET
RETSKP ;GOOD RET
SUBTTL ERROR RETRY ENTRY POINT
;P1, P2, P3, P4 SET UP
;ROUTINE PUTS ER BLK ADDRESS IN Q1
TM2ERR: SAVEQ
CALL SETIRB ;GET OUR IORB
HRRZ Q1,UDBERP(P3) ;GET ERROR BLOCK IF PRESENT
HLLZ T1,IRBSTS(P4) ;GET IORB STATUS
;IF UNS (OFF-LINE ERR), SOMEDAY SHOULD RETRY IN A MIN OR SO.
HRRZ T4,UDBERR(P3) ;GET FUNCTION IF ERROR RECOVERY
SKIPN T4 ;IN ERROR RECOVERY?
LOAD T4,ISFCN,(P4) ;NO, GET FN FROM IORB
MOVE T4,TM2FTB(T4) ;NOW TABLE ENTRY
TXNN T1,IS.NRT!IS.IER ;FATAL OR INHIBIT ERR RECOVERY?
JRST TMERTY ;NO, RETRY THE ERROR
SKIPE TU6EBP(P3) ;WAS FATAL ERR DURING RETRY?
JRST ABTNOS ;YES, WE ALREADY HAVE BEGIN DATA
AOS (P) ;SKIP RET FROM LOD1 - DONE WITH IORB
JRST LOD1 ;LOAD UP ERR BLK FOR FATAL ERR
;DO RETRY
TMERTY: HLR T4,T4 ;COPY LH OF FNTBL
TRZ T4,777770 ;SAVE ONLY RETRY INDEX IN RH
SKIPE UDBERC(P3) ;1ST TIME FOR HERE?
JRST NOT1ST ;NO
SETZM TU6ECL(P3) ;NOT DOING TAPE CLEAN
SKIPN T1,RTYBPT(T4) ;GET RETRY BYTE POINTER
JRST [ BUG(INF,TM2IDX,<PHYM2 - ILLEGAL RETRY BYTE POINTER>)
JRST ABTNOS] ;CALL IT FATAL
MOVEM T1,TU6EBP(P3) ;SAVE IT
MOVE T1,UDBPS2(P3) ;GET # RECORDS
SOS T1 ;CALCULATE WHERE WE SHOULD BE AFTER REPOS
TXNE T4,TB.REV ;IF IN FORWARD, WE WANT (CUR POSITION-1)
ADDI T1,2 ;IF REVERSE, WE WANT (CUR POSITION+1)
MOVEM T1,TU6EPS(P3) ;WHERE WE SHOULD BE SOMEDAY
MOVEI T1,RTYWRT+1 ;ON WRITE, THIS MANY RETRIES
TXNN T4,TB.WRT ;ARE WE RIGHT (WRITE)?
MOVE T1,[RTYCLN+1,,RTYOP+1] ;NO, THIS IS FOR READ
MOVEM T1,UDBERC(P3) ;THE RETRY COUNTER
CALL LOD1 ;LOAD UP ERR BLK WITH BEGIN DATA
JRST NXTBYT ;1ST TIME THRU TM2ERR
NOT1ST: MOVE T1,TU6EBP(P3) ;GET RETRY BYTE POINTER
ILDB T1,T1 ;LOOK AT NEXT OPERATION
CAIE T1,16 ;END OF RETRY?
JRST CKBOT ;NO
HLLZ T1,IRBSTS(P4) ;GET IORB STATUS
TXNN T1,IS.DTE ;WAS THERE DATA ERR?
JRST RTYNOE ;NO, WE'VE RECOVERED!
MOVE T1,RTYBPT(T4) ;GET BYTE POINTER
MOVEM T1,TU6EBP(P3) ;RESET IT
SETZM TU6ECL(P3) ;NOT DOING TAPE CLN SEQUENCE
HRRZ T1,UDBERC(P3) ;GET ABORT COUNTER
SOS T1 ;ANOTHER RETRY - SEE IF WE'VE LOST
HRRM T1,UDBERC(P3) ;SAVE IT
JUMPN T1,NXTBYT ;IF NOT 0, TRY AGAIN
TXNE T4,TB.DOP ;DATA OP?
TXNN T4,TB.RD ;WRITE OR READ?
JRST ABTRTY ;NONDATA OR WRITE - WE'VE FAILED
HLRZ T1,UDBERC(P3) ;GET TAPE CLNR COUNTER
SOJE T1,ABTRTY ;RUN OUT OF RETRIES? - YES
HRLM T1,UDBERC(P3) ;NO, UPDATE CLN COUNTER
MOVX T1,RTYOP+1 ;NOW RESET (RH) COUNTER
HRRM T1,UDBERC(P3) ;FOR NEXT CLEAN RETRY
MOVE T1,RTYBPT+1(T4) ;GET CLEANER SEQ BYTE POINTER
MOVEM T1,TU6EBP(P3) ;SAVE FOR USE LATER
SETZM TU6EBC(P3) ;RESET COUNT FOR USE IF WE HIT BOT
SETOM TU6ECL(P3) ;WE ARE DOING A CLEAN
JRST NXTBYT ;NOW DO NEXT OPERATION
CKBOT: SKIPN TU6ECL(P3) ;DOING TAPE CLEAN?
JRST NXTBYT ;NO DON'T CHECK BOT
HLLZ T1,IRBSTS(P4) ;GET STATUS
IFE OPIFIX,<SKIPE UDBPS2(P3)>; ARE WE ALMOST AT BOT?
TXNE T1,IS.BOT ;OR DID WE HIT BOT?
SKIPA T1,[CLNREC] ;YES, FIGURE OUT HOW TO FUDGE BYTE POINTER
JRST NXTBYT ;NO, CONTINUE NORM RETRY
LOAD T3,ISFCN,(P4) ;GET ORIGINAL FN
MOVE T3, TM2FTB(T3) ;GET FLAGS
TXNE T3,TB.WRT ;IS IT A WRITE?
JRST NXTBYT ;WRITE RETRY WON'T EVER HIT BOT SO NO FUDGE
TXNN T3,TB.REV ;ADD 1 IF FORWARD
AOS T1 ;DO IT ON FORWARD
SUB T1,TU6EBC(P3) ;SUBT # RECORDS SPACED
LSH T1,1 ;TIMES 2 (COMMENTS ASSUME CLNREC=5)
AOS T1 ;ON FORWARD, SKIP (6-CNT)*2+1 BYTES
CAIL T1,1 ;ON REVERSE, SKIP (5-CNT)*2+1 BYTES
IFN OPIFIX,<CAILE T1,^D9>; RESULT MUST BE BETWEEN 1 AND 9
IFE OPIFIX,<CAILE T1,^D11>; BETWEEN 1 AND 11 IF OPI NOT FIXED
JSP CX,CNFERR ;BAD INCR, WE ARE CONFUSED
IFE OPIFIX,<SKIPE UDBPS2(P3)>; IF ALMOST AT BOT, FUDGE 1 LESS
IBPLP: IBP TU6EBP(P3) ;INCR THE POINTER
SOJG T1,IBPLP ;ANOTHER?
NXTBYT: AOS TU6EBC(P3) ;ANOTHER BYTE FOR THE COUNTER
ILDB T3,TU6EBP(P3) ;GET NEXT FUNCTION
CAIE T3,17 ;IS IT CHECK POSITION OPERATION?
JRST NOTCKP ;NO
MOVE T1,UDBPS2(P3) ;YES, GET OUR POSITION
CAMN T1,TU6EPS(P3) ;ARE WE WHERE WE WANT TO BE?
JRST NXTBYT ;YES, ALL OK
JSP CX,CNFERR ;POSITION CONFUSED,SIGNAL ERROR
JRST ABTNOS ;BOMB OUT
NOTCKP: CAIE T3,16 ;END OF RETRY?
SKIPG T3 ;IS FUNCTION VALID?
JRST [ BUG(INF,TM2IRF,<PHYM2 - ILLEGAL FUNCTION DURING RETRY>)
JRST ABTNOS] ;IMAGINE FATAL
HRRM T3,UDBERR(P3) ;SAVE FUNCTION
HRRZ T1,CDBDSP(P1) ;GET CHANNEL DISPATCH
CALL CDSSIO(T1) ;START IO
;SHOULD RETRY EVERY MIN OR SO
JRST ABTNOS ;COULDN'T START UP RETRY OPERATION
RET ;AND WAIT
RTYNOE: TXNE T1,IS.NRT ;HARD ERRS SHOULDN'T EVER GET HERE
BUG(CHK,TM2HER,<TM2ERR - IS.HER SET ON SUCCESSFUL RETRY>)
MOVX T1,IS.ERR ;WE DID IT! CLEAR ERR BIT
ANDCAM T1,IRBSTS(P4) ;AND SKP RETURN
TXNN T4,TB.WRT ;ARE WE WRTING?
AOSA UDBSRE(P3) ;NO, A SOFT READ ERR
AOS UDBSWE(P3) ;YES, A SOFT WRITE ERR
JRST ABTNOS
;HERE WHEN ERROR RECOVERY GETS CONFUSED(FLAKEY HARDWARE W I L L DO IT)
CNFERR: HRRZ T1,UDBADR(P3) ;GET UNIT NUMBER
MOVE Q1,TM2ADR(P2) ;GET KNOTROLLER NUMBER
HRRZ T3,CDBADR(P1) ;GET CHANNEL NUMBER
BUG(CHK,TM2RFU,<PHYM2 - ERROR RECOVERY CONFUSED>,<T1,Q1,T3>)
MOVSI T1,(IS.ERR!IS.NRT) ;INDICATE RATHER HARD ERR
IORM T1,IRBSTS(P4) ; ...
JRST ABTNOS ;AND ABORT
ABTRTY: ;WE RAN OUT OF RETRIES
TXNN T4,TB.WRT ;ARE WE WRTING?
AOSA UDBHRE(P3) ;NO, A HARD READ ERR
AOS UDBHWE(P3) ;YES, A HARD WRITE ERR
ABTNOS: AOS (P) ;SKIP RET FROM LODE
HRRZ Q1,UDBERP(P3) ;GET ERROR BLOCK
SKIPN TU6EBP(P3) ;DONE ANY RETRIES?
JRST LODE ;NO, LOAD UP ERR BLK WITH END DATA
TXNN T4,TB.WRT ;YES, IN A WRITE?
JRST RDCNT ;NO
MOVEI T1,RTYWRT+1 ;YES, CALCULATE # RETRIES DONE
SUBM T1,UDBERC(P3) ;RESIDUE
JRST LODE ;NOW LOAD UP ERR BLK
RDCNT: HLRZ T1,UDBERC(P3) ;GET CLN COUNTER
IMULI T1,RTYOP ;CONVRT JUST TO # RETRIES
ADD T1,UDBERC(P3) ;ADD IN REGULAR RETRIES
MOVEI T2,<RTYCLN+2>*RTYOP+1 ;COUNT AT START
SUB T2,T1
HRRZM T2,UDBERC(P3) ;SAVE # RETRIES
JRST LODE ;NOW LOAD UP ERR BLK
;LOAD UP ERR BLK AT START OF ERR
;C(Q1)=ERR BLK
LOD1: JUMPE Q1,R ;IF NO ERROR BLOCK, PUNT
MOVE T1,Q1 ;COPY ERROR BLOCK
MOVE T2,[-NITAB,,ITAB] ;POINTER TO INFORMATION TABLE
CALL SEBCPY ;COPY INFORMATION
JFCL
MOVS T1,UDBPS1(P3) ;GET FILE
HRR T1,UDBPS2(P3) ;AND RECORD (JUST AFTER ERROR)
MOVEM T1,SEBDAT+MB%LOC(Q1) ;AND SAVE AS LOCATION OF ERROR
MOVEI T1,SEBDAT+MB%REG(Q1) ;MOVE REGISTERS TO HERE
MOVEM T1,T2 ;SAVE FOR RH OF BLT
ADDI T2,11 ;11 WDS
HRLI T1,TM2REG(P2) ;GET REGISTERS FROM HERE
HRLI T2,(BLT T1,) ;SET UP INST FIELD
XCT T2 ;DO IT
RET
;LOAD UP ERR BLK AT END
LODE: SETZM TU6EBP(P3) ;RESET ERROR BYTE POINTER
JUMPE Q1,R ;IF NO ERROR BLOCK, CANT SAVE DATA
MOVE T3,[-12,,TM2REG] ;CASE FOR START
ADD T3,P2 ;POINTS TO REGISTER DATA
MOVEI T2,SEBDAT+MB%REG(Q1) ;REGISTER DATA GOES HERE
LDELP: MOVE T1,(T3) ;GET REGISTER
HRLM T1,(T2) ;PUT IT
AOS T2 ;NEXT WD
AOBJN T3,LDELP ;DONE?
MOVE T1,TM.CNI(P2) ;GET CONI
MOVEM T1,SEBDAT+MB%CIF(Q1) ;SAVE
MOVE T1,TM.CS1(P2) ;GET TCR
MOVEM T1,SEBDAT+MB%D1F(Q1) ;SAVE
MOVE T1,TM.DBF(P2) ;GET BAR
MOVEM T1,SEBDAT+MB%D2F(Q1) ;SAVE
RET
;TABLE OF ITEMS TO COPY INTO ERROR BLOCK
ITAB: SEBPTR MB%CS0,SBTWD,CDBCS0(P1) ;CHANNEL STATUS 0
SEBPTR MB%CS1,SBTWD,CDBCS1(P1) ;CHANNEL STATUS 1
SEBPTR MB%CS2,SBTWD,CDBCS2(P1) ;CHANNEL STATUS 2
SEBPTR MB%CC1,SBTWD,CDBCC1(P1) ;CCW 1
SEBPTR MB%CC2,SBTWD,CDBCC2(P1) ;CCW 2
SEBPTR MB%ICR,SBTWD,CDBICR(P1) ;INITIAL CONTROL REGISTER
SEBPTR MB%CNI,SBTWD,TM.CNI(P2) ;CONI INITIAL
SEBPTR MB%D1I,SBTWD,TM.CS1(P2) ;TCR
SEBPTR MB%D2I,SBTWD,TM.DBF(P2) ;BAR/DBF
NITAB==.-ITAB
SUBTTL ROUTINE TO POLL SLAVES TO SEE IF DONE REWIND
TM2POL: PUSH P,P4 ;SAVE PERMANENT ACCUMULATORS
MOVEI P4,11 ;GUARD AGAINST BROKEN HARDWARE
PUSH P,Q2 ;WE WILL CLOBBER IT
PUSH P,P3 ;IN CASE WE MUST SWITCH UNITS
PUSH P,[0] ;VARIABLE FOR REWIND DONE
POLAGN: MOVSI T4,-10 ;#SLVS POSSIBLE
SETOM T1 ;SAYS THAT WE HAVEN'T READ A REGISTER YET
POLLP: ADD T4,P2 ;BUILD POINTER TO KDB ENTRY
MOVE P3,KDBUDB(T4) ;GET UDB ADDRESS FOR THIS SLAVE
SUB T4,P2 ;FUDGE IT BACK
MOVE Q2,TM2ADR(P2) ;GET TM02 ADDRESS
JUMPE P3,TM2PNO ;UNIT NOT KNOWN
MOVX T2,DO.TC ;READY TO LOAD TAPE CNTL REGISTER
TRO T2,(T4) ;SELECT THIS SLAVE
CALL WTREG3 ;...
MOVX T2,DO.DS ;NOW GET STATUS REGISTER
CALL RDREG3
HLLZ T2,UDBSTS(P3) ;GET STATUS OF DRIVE
MOVX T3,US.OFS!US.BOT!US.REW!US.WLK ;CLEAR THESE BITS
ANDCAM T3,UDBSTS(P3) ;DO IT
TXNE T1,DS.MOL ;ON LINE?
TXZ T3,US.OFS ;YES, CLEAR FLAG
TXNN T1,DS.BOT ;AT BOT?
TXZA T3,US.BOT ;NO
JRST [SETZM UDBPS1(P3) ;YES, ZERO REC CNTRS
SETZM UDBPS2(P3)
JRST .+1]
TXNN T1,DS.PIP ;REWINDING? (PIP=1?)
TXZ T3,US.REW ;NO, CLEAR BIT
TXNN T1,DS.WRL ;WRITE LOCKED?
TXZ T3,US.WLK ;NO
IORM T3,UDBSTS(P3) ;STORE THE STATUS
TXNE T2,US.REW ;ARE WE REWINDING?(T2 IS OLD UDBSTS)
JRST [MOVX T2,US.REW ;OLD STATUS WAS REWINDING, CHECK
TDNN T2,UDBSTS(P3) ;NEW STATUS FOR CHANGE
MOVEM P3,(P) ;SAVE UDB WHICH FINISHED REWIND
JRST .+1] ;AND CONTINUE LOOP
TM2PNO: AOBJN T4,POLLP ;DO REST OF SLAVES
JUMPGE T1,TM2NRD ;JUMP IF WE HAVE READ THE STATUS REGISTER
MOVE Q2,TM2ADR(P2) ;IF NOT, READ IT NOW
MOVX T2,DO.DS
CALL RDREG3 ;READ THE DRIVE STATUS REGISTER
TM2NRD: TRNE T1,DS.SSC!DS.ERR ;IS SSC OR ERR UP?
JRST FNDCLR ;YES, FIND AN INACTIVE DRIVE FOR DRIVE CLEAR
TM2BCK: POP P,P3 ;RECOVER POSSIBLE REWIND DONE UDB
JUMPE P3,TM2NR1 ;IS THERE ONE?
SKIPN -2(P) ;YES, IS IT LEGAL TO START UP
CALL PHYRWD ;YES, NOTIFY PHYSIO, MAY START IO
TM2NR1: POP P,P3
POP P,Q2
POP P,P4
RET
FNDCLR: MOVE T2,KDBIUN(P2) ;GET AOBJN POINTER
FNDLP: SKIPN P3,(T2) ;IS ENTRY 0?
JRST RDYCLR ;YES, DO DRIVE CLEAR HERE
MOVE T3,UDBSTS(P3) ;GET UDB STATS
TXNE T3,US.REW ;ARE WE REWINDING?
AOBJN T2,FNDLP ;YES, TRY NEXT DRIVE
RDYCLR: SUB T2,KDBIUN(P2) ;SUBT AOBJN POINTER BASE
HRLI T2,(DO.TC) ;IF ALL REWINDING, DO IT TO 7
CALL WTREG3 ;SELECT IT
MOVX T2,DF.CLR ;SET UP TO DO CLEAR
CALL WTREG3 ;LOAD IT INTO CONTRL REGISTER (0)
SOJN P4,POLAGN ;BEGIN POLL AGAIN (THANX TO MATEL ENG)
BUG(CHK,TM2CCI,<PHYM2 - TM02 SSC OR SLA WONT CLEAR>)
JRST TM2BCK ;HOPE AND HOPE
SUBTTL TM02 FUNCTION TABLE
;EACH ENTRY MUST BE NON-0
;1B0 ;ILLEGAL FUNCTION
TB.WRT==1B1 ;THIS FUNCTION WRITES ON TAPE
TB.REV==1B2 ;THIS OPERATION MOVES TAPEIN REVERSE DIRECTION
TB.DOP==1B3 ;THIS IS A DATA OPERATION
TB.SPC==1B4 ;THIS IS A SPACE OPERATION
TB.RD==1B5 ;THIS IS A READ
TB.ERA==1B6 ;ERASE OPERATION
TB.TM==1B7 ;WRITE TAPE MARK
TB.NFC==1B8 ;DON'T LOAD FRM COUNT WHEN DOING OPERATION
TB.REW==1B9 ;OPERATION IS A REWIND
;BITS 15,16,17 CONTAIN AN INDEX TO RTYBPT TO TELL US HOW
;TO RETRY AN OPERATION (0 IF NO RETRY)
;BITS 30-35 CONTAIN THE EQUIVALENT TM02 FUNCTION
TM2FTB: 1B0 ;0- ILLEGAL
TB.DOP!TB.RD!TB.NFC!2B17!DF.RDF ;1- READ FORWARD (IRFRED)
1B0 ;2- ILL (RD FMT)
TB.WRT!TB.DOP!1B17!DF.WTF ;3- WRITE FORWARD (IRFWRT)
1B0 ;4- ILL (WRT FMT)
1B0 ;5- ILL (SEEK)
TB.SPC!DF.SPF ;6- SPCE FORWARD
TB.REV!TB.SPC!DF.SPR ;7- SPCE REVERSE
TB.WRT!TB.TM!6B17!DF.WTM ;10- WRITE TM
TB.WRT!TB.ERA!TB.NFC!DF.ERA ;11- ERASE
TB.NFC!TB.REW!DF.REW ;12- REWIND
TB.NFC!DF.UNL ;13- UNLOAD
TB.REV!TB.DOP!TB.RD!TB.NFC!4B17!DF.RDR ;14- READ REVERSE
1B0 ;15- ILL (RECOVERY RD)
1B0 ;16- ILL (USED FOR END OF RECOVERY ACTION)
1B0 ;17- ILL (USED FOR CHECK POSITION ACTION)
;CONVT SOFTWARE MODE CODE TO TM02/3 FMT CODE (1B0 IS ILLEGAL)
;LH IS #FRAMES/BYTE (0 MEANS FRAMES=BYTES), RH IS TM02 FORMAT TYPE
MTBFMT: 1B0 ;0 - ILLEGAL FMT
5,,0 ;1 - COR DMP (LH MEANS 5 FRAMES PER BYTE)
1B0 ;2 - SIXBIT (7TRK) ILLEGAL
2 ;3 - 7-BIT (ASCII)
3 ;4 - 8-BIT (COMPAT)
;CONVT SOFTWARE DENS CODE TO TM02/3 DENSITY CODE (1B0 IS ILLEGAL)
MTBDEN: 1B0 ;0 - ILLEGAL DEN
0 ;1 - 200BPI
1 ;2 - 556BPI
2 ;3 - 800BPI
4 ;4 - 1600BPI
;RETRY TABLES TO TELL HOW TO RETRY
RTYBPT: 0 ;ILLEGAL RETRY
POINT 4,TBRWRT ;WRITE RETRY
POINT 4,TBRRF ;READ FORWARD RETRY
POINT 4,TBRRFC ;READ FORWARD TAPE CLEAN
POINT 4,TBRRR ;READ REVERSE RETRY
POINT 4,TBRRRC ;READ REVERSE TAPE CLEAN
POINT 4,TBRWTM ;WRITE TAPE MARK
0 ;ILLEGAL
;THE FOLLOWING MACROS HELP ME GET AROUND SOME SHORTCOMINGS IN MACRO:
;NOTE: THE MACRO'S MUST BE FIXED IN THE UNLIKELY EVENT THAT
;SOMEBODY WANTS TO CHANGE TO A BYTE SIZE WHICH DOESN'T GO
;EVENLY INTO 36(10). RIGHT NOW IT'S 4.
DEFINE FOO (XXA) <
WD==0
BYC==0
ZZ==0 ;FLIP-FLOP
IRP XXA,<
IFE ZZ,<RP==XXA>
IFN ZZ,<FOO1 RP,XXA>
ZZ==ZZ+1
IFE ZZ-2,<ZZ==0>>
IFN BYC,<EXP WD>>
DEFINE FOO1 (A1,A2) <
REPEAT A1,<
WD==WD+<A2>B<4*BYC+3>
BYC==BYC+1
IFGE BYC-^D9, <
EXP WD
WD==0
BYC==0>>>
TBRWRT: BYTE (4) IRFBSB,IRFERG,17,IRFWRT,16
;WRITE RETRY - SPACE REVERSE, ERASE, CHECK POSITION, WRITE
TBRWTM: BYTE (4) IRFBSB,IRFERG,17,IRFWTM,16
;WTM RETRY - SPACE REVERSE, ERASE, CHECK POS, WTM, EOR
TBRRF: BYTE (4) IRFBSB,17,IRFRED,16
;READ FORWARD RETRY - SPACE REVERSE, CHECK POSITION, READ FORWARD
TBRRR: BYTE (4) IRFFSB,17,IRFRDR,16
;READ REVERSE RETRY - SPACE FORWARD, CHECK POSITION, READ REVERSE
TBRRFC: FOO<CLNREC+1,IRFBSB, CLNREC,IRFFSB, 1,17, 1,IRFRED, 1,16>
;RD FORWARD TAPE CLEAN: 6 SP REVERSE, 5 SP FORWARD, CHECK POSITION, RD FORWARD
TBRRRC: FOO<CLNREC,IRFBSB, CLNREC+1,IRFFSB, 1,17, 1,IRFRDR, 1,16>
;RD REVERSE TAPE CLEAN: 5 SP REVERSE, 6 SP FORWARD, CHECK POSITION, RD REVERSE
TNXEND
END