!** MTSUPP09S MODIFIED TO ALLOW TAPE CLAIMING ONLY AT ACR 9 OR LESS

!MODIFIED 16.11.79 TO ACCEPT TAPE CLAIMS WITH ? AS THE
!LAST CHARACTER OF VOL. MEANS LOAD WITH OPTIONAL RING
!ALSO DIFFERENT HANDLING OF FAILURES. I FLAG IS 2 THEN
!CATASTROPHIC FAILURE - DECK HAS POWERED OFF OR SIMILAR
!IF 1 THEN HARDWARE FAULT - ALLOW 10 ON A CHANNEL THEN ABANDON
!MAG TAPE SUPPORT ROUTINES FOR UTILITY PROGRAMS
!R.MCLEOD APRIL 1978
!*
!*
!*    EXTERNAL SPECS
!*
!*
CONSTINTEGER  MAXFAULTCOUNT = 10;       !ABANDON AFTER 10 HARDWARE FAULTS
CONSTINTEGER  MINCHAN = 1
CONSTINTEGER  MAXCHAN = 8
EXTERNALINTEGERFNSPEC  UINFI(INTEGER  N)
EXTERNALINTEGERFNSPEC  DMAGCLAIM(STRING  (6) TSN,  C 
   INTEGERNAME  SNO, INTEGER  REQ, MODE)
EXTERNALINTEGERFNSPEC  DMAGIO( C 
   INTEGERNAME  REPLY, CONTROL, LEN, INTEGER  TYPE, SNO, ADR)
OWNINTEGER  CONTROL;                    !USED FOR DMAGIO CALLS - NO EFFECT PROTEM
OWNINTEGERARRAY  SNO(1 : 8) =     -1(8);!SERVICE NOS
OWNINTEGERARRAY  FAULTCOUNT(1 : 8);     !COUNT OF HARDWARE FAULTS
OWNSTRING  (6) ARRAY  VOL(1 : 8)
OWNINTEGERARRAY  MODE(1 : 8)
ROUTINESPEC  SKIPTMMAG(INTEGER  CHAN, N)

ROUTINE  FAIL(STRING  (255) S)
   SELECTOUTPUT(0)
   NEWLINES(2)
   PRINTSTRING(S)
   MONITOR 
   STOP 
END ;                                   !OF FAIL

ROUTINE  RECORDFAULT(INTEGER  CHAN, INTEGERNAME  FLAG)
   IF  FLAG = 2 THEN  FAIL("CATASTROPHIC TAPE FAILURE")
   IF  FAULTCOUNT(CHAN) >= MAXFAULTCOUNT C 
      THEN  FAIL("MORE THAN 10 TAPE FAILURES")
   FAULTCOUNT(CHAN) = FAULTCOUNT(CHAN)+1
   FLAG = 2;                            !FOR RETURN TO USER
END ;                                   !OF RECORDFAULT

EXTERNALROUTINE  OPENMAG(INTEGER  CHAN, STRING  (7) S)
INTEGER  FLAG,LNB,ACR
   UNLESS  MINCHAN <= CHAN <= MAXCHAN C 
      THEN  FAIL("INVALID CHAN")
   *STLN_LNB;                           !TO FIND ACR LEVEL
   ACR = (INTEGER(LNB+4)>>20)&X'F';     !PRIV IF 5 OR LESS
   IF  ACR > 9 AND  UINFI(2)&1 = 1 START ;   !UN-PRIV ATTEMT TO USE TAPE
                                        !FROM INTERACTIVE TERMINAL
FAIL("No tape access allowed from interactive terminal")
   FINISH 
   IF  SNO(CHAN) # -1 THEN  FAIL("TAPE ALREADY CLAIMED")
   IF  S -> VOL(CHAN).("?") THEN  MODE(CHAN) = 3 ELSE  START 
                                        !OPTIONAL RING
      IF  S -> VOL(CHAN).("*") THEN  MODE(CHAN) = 2 C 
         ELSE  VOL(CHAN) = S AND  MODE(CHAN) = 1
      !WRITE OR READ
   FINISH 
   WHILE  LENGTH(VOL(CHAN)) < 6 THEN  VOL(CHAN) = VOL(CHAN)." "
   FLAG = DMAGCLAIM(VOL(CHAN),SNO(CHAN),0,MODE(CHAN))
   IF  FLAG # 0 THEN  FAIL("FAILURE TO CLAIM TAPE")
   IF  MODE(CHAN) = 3 THEN  MODE(CHAN) = 2;  !IF RING OPTIONAL
   !THEN TREAT AS IF THERE IS ONE. IT'S UP TO THE USER TO TAKE CARE
   FAULTCOUNT(CHAN) = 0;                !RESET COUNT OF FAULTS
END ;                                   !OF OPENMAG

EXTERNALROUTINE  UNLOADMAG(INTEGER  CHAN)
INTEGER  FLAG
   UNLESS  MINCHAN <= CHAN <= MAXCHAN C 
      THEN  FAIL("INVALID CHAN")
   RETURN  IF  SNO(CHAN) < 0
   FLAG = DMAGCLAIM(VOL(CHAN),SNO(CHAN),1,MODE(CHAN))
                                        !GIVE BACK TAPE
   VOL(CHAN) = ""
   SNO(CHAN) = -1
END ;                                   !OF UNLOADMAG

EXTERNALROUTINE  READMAG(INTEGER  CHAN, AD,  C 
   INTEGERNAME  LEN, FLAG)
INTEGER  DFLAG
   UNLESS  MINCHAN <= CHAN <= MAXCHAN C 
      THEN  FAIL("INVALID CHAN")
   IF  SNO(CHAN) < 0 THEN  FAIL("TAPE NOT CLAIMED")
   IF  LEN <= 0 THEN  FAIL("INVALID READ LENGTH")
   CONTROL = 4;                         !IGNORE SHORT BLOCK INDICATION
   DFLAG = DMAGIO(FLAG,CONTROL,LEN,1,SNO(CHAN),AD)
   IF  DFLAG > 7 THEN  FAIL("DMAGIO FAILS IN READMAG")
   IF  FLAG # 0 START 
      IF  FLAG = 4 START ;              !TAPE MARK HIT
         SKIPTMMAG(CHAN,1);             !SKIP OVER THE TAPE MARK
         FLAG = 1
      FINISH  ELSE  RECORDFAULT(CHAN,FLAG)
   FINISH 
END ;                                   !OF READMAG

EXTERNALROUTINE  WRITEMAG(INTEGER  CHAN, AD, LEN,  C 
   INTEGERNAME  FLAG)
INTEGER  DFLAG
   UNLESS  MINCHAN <= CHAN <= MAXCHAN C 
      THEN  FAIL("INVALID CHAN")
   IF  SNO(CHAN) < 0 THEN  FAIL("TAPE NOT CLAIMED")
   IF  MODE(CHAN) = 1 THEN  FAIL("WRITING NOT ALLOWED")
   CONTROL = 0
   DFLAG = DMAGIO(FLAG,CONTROL,LEN,2,SNO(CHAN),AD)
   IF  DFLAG > 7 THEN  FAIL("DMAGIO FAILS IN WRITEMAG")
   IF  FLAG # 0 THEN  RECORDFAULT(CHAN,FLAG)
END ;                                   !OF WRITEMAG

EXTERNALROUTINE  WRITETMMAG(INTEGER  CHAN, INTEGERNAME  FLAG)
INTEGER  DFLAG
   UNLESS  MINCHAN <= CHAN <= MAXCHAN C 
      THEN  FAIL("INVALID CHAN")
   IF  SNO(CHAN) < 0 THEN  FAIL("TAPE NOT CLAIMED")
   IF  MODE(CHAN) = 1 THEN  FAIL("WRITING NOT ALLOWED")
   CONTROL = 0
   DFLAG = DMAGIO(FLAG,CONTROL,CONTROL,10,SNO(CHAN),0)
   IF  DFLAG > 7 THEN  FAIL("DMAGIO FAILS IN WRITETMMAG")
   IF  FLAG # 0 THEN  RECORDFAULT(CHAN,FLAG)
END ;                                   !OF WRITETMMAG

EXTERNALROUTINE  REWINDMAG(INTEGER  CHAN)
INTEGER  DFLAG, FLAG
   UNLESS  MINCHAN <= CHAN <= MAXCHAN C 
      THEN  FAIL("INVALID CHAN")
   IF  SNO(CHAN) < 0 THEN  FAIL("TAPE NOT CLAIMED")
   CONTROL = 0
   DFLAG = DMAGIO(FLAG,CONTROL,CONTROL,6,SNO(CHAN),CONTROL)
   IF  DFLAG > 7 THEN  FAIL("DMAGIO FAILS IN REWINDMAG")
END ;                                   !OF REWINDMAG

EXTERNALROUTINE  SKIPMAG(INTEGER  CHAN, N)
!SKIP N BLOCKS(A TAPE MARK COUNTING AS A BLOCK) BACKWARDS OR FORWARDS
INTEGER  FLAG, DIRECTION, I, DFLAG, LEN
   UNLESS  MINCHAN <= CHAN <= MAXCHAN C 
      THEN  FAIL("INVALID CHAN")
   IF  SNO(CHAN) < 0 THEN  FAIL("TAPE NOT CLAIMED")
   RETURN  IF  N = 0;                   !NULL CALL
   IF  N > 0 THEN  DIRECTION = 1 ELSE  N = -N AND  DIRECTION = -1
   CYCLE  I = 1,1,N
      CONTROL = 0
      LEN = DIRECTION
      DFLAG = DMAGIO(FLAG,CONTROL,LEN,8,SNO(CHAN),0)
                                        !TRY AND SKIP 1 BLOCK
      IF  DFLAG > 7 THEN  FAIL("DMAGIO FAILS IN SKIPMAG")
      IF  1 <= FLAG <= 2 THEN  FAIL("FAILURE IN SKIP")
                                        !SKIP SHOULD NEVER FAIL
      IF  FLAG = 4 START ;              !TAPE MARK FOUND
         CONTROL = 1
         LEN = DIRECTION
         DFLAG = DMAGIO(FLAG,CONTROL,LEN,9,SNO(CHAN),0)
                                        !TRY AND SKIP THE TM
         IF  DFLAG > 7 THEN  FAIL("DMAGIO FAILS IN SKIPMAG")
         IF  1 <= FLAG <= 2 THEN  FAIL("FAILURE IN SKIP")
      FINISH 
   REPEAT 
END ;                                   !OF SKIPMAG

EXTERNALROUTINE  SKIPTMMAG(INTEGER  CHAN, N)
INTEGER  FLAG, DFLAG, LEN, DIRECTION, I
   UNLESS  MINCHAN <= CHAN <= MAXCHAN C 
      THEN  FAIL("INVALID CHAN")
   IF  SNO(CHAN) < 0 THEN  FAIL("TAPE NOT CLAIMED")
   IF  N = 0 THEN  RETURN 
   IF  N > 0 THEN  DIRECTION = 1 ELSE  DIRECTION = -1 AND  N = -N
   CYCLE  I = 1,1,N
      CONTROL = 1
      LEN = DIRECTION
      DFLAG = DMAGIO(FLAG,CONTROL,LEN,9,SNO(CHAN),0)
      IF  DFLAG > 7 THEN  FAIL("DMAGIO FAILS IN SKIPTMMAG")
      IF  1 <= FLAG <= 2 THEN  FAIL("FAILURE IN SKIP")
   REPEAT 
END ;                                   !OF SKIPTMMAG

EXTERNALROUTINE  FSKIPTMMAG(INTEGER  CHAN, N, INTEGERNAME  FLAG)
INTEGER  DFLAG, LEN, I
   UNLESS  MINCHAN <= CHAN <= MAXCHAN C 
      THEN  FAIL("INVALID CHAN")
   IF  SNO(CHAN) < 0 THEN  FAIL("TAPE NOT CLAIMED")
   IF  N = 0 THEN  RETURN 
   CONTROL = 1
   LEN = N;                             !NO OF TAPEMARKS FORE OR AFT
   DFLAG = DMAGIO(FLAG,CONTROL,LEN,9,SNO(CHAN),0)
   IF  DFLAG > 7 THEN  FAIL("DMAGIO FAILS IN SKIPTMMAG")
   IF  1 <= FLAG <= 2 THEN  FAIL("FAILURE IN SKIP")
   IF  FLAG = 4 THEN  FLAG = 1;         !GOT TO DOUBLE TM BEFORE SKIPPING ENOUGH
END ;                                   !OF FSKIPTMMAG
!THE FOLLOWING ROUTINES ARE PROVIDED FOR BACK COMPATIBILITY

EXTERNALROUTINE  OPENMT(STRING  (7) VOL)
   OPENMAG(1,VOL)
END ;                                   !OF OPENMT

EXTERNALROUTINE  UNLOADMT
   UNLOADMAG(1)
END ;                                   !OF UNLOADMT

EXTERNALROUTINE  REWINDMT
   REWINDMAG(1)
END ;                                   !REWINDMT

EXTERNALROUTINE  READMT(INTEGER  AD, INTEGERNAME  LEN, FLAG)
   READMAG(1,AD,LEN,FLAG)
END ;                                   !OF READMT

EXTERNALROUTINE  WRITEMT(INTEGER  AD, LEN, INTEGERNAME  FLAG)
   WRITEMAG(1,AD,LEN,FLAG)
END ;                                   !OF WRITEMT

EXTERNALROUTINE  WRITETMMT(INTEGERNAME  FLAG)
   WRITETMMAG(1,FLAG)
END ;                                   !OF WRITETMMT

EXTERNALROUTINE  SKIPMT(INTEGER  N)
   SKIPMAG(1,N)
END ;                                   !OF SKIPMT

EXTERNALROUTINE  SKIPTMMT(INTEGER  N)
   SKIPTMMAG(1,N)
END ;                                   !OF SKIPTMMT
ENDOFFILE