!TITLE Magnetic Tape Facilities
!<DMAGCLAIM
externalintegerfn DMAG CLAIM(string (6)TSN, integername SNO,
integer REQ, MODE)
!
! The magnetic tape volume labelled TSN is either claimed (REQ=0) or
! released (REQ=1). MODE should be set to 1 to allow read access to the
! tape, 2 if write access is required, or 3 for either read or write
! access. If a CLAIM call is successful, SNO is set with a number to be
! used in subsequent calls of DMAG IO.
!
! If TSN is null in a RELEASE call, then all claimed tapes are released.
!
! Possible error results from Volumes:
! 101 Bad parameters
! 102 Duplicate request
! 103 Request lists full
! 104 Volume not available (Operators have said "NO <val id>")
! 105 Volume request list full
! 106 No tapes in tape list (A, B, S or E)
! 107 Device not claimed when a "release" is done.
!>
INTEGER J, K, L
K = IN2(256 + 37)
-> OUT UNLESS K = 0
!
K = 45
-> OUT IF VAL(ADDR(SNO), 4, 1, DCALLERS PSR) = 0
!
K = 8
-> OUT UNLESS 0<=REQ<=1
L = LENGTH(TSN)
-> OUT UNLESS (L=0 OR L=6)
UCTRANSLATE(ADDR(TSN)+1, 6) IF L = 6
!
IF REQ=0 START
! CLAIM
-> OUT UNLESS L = 6
!
K = 90; ! MAX TAPES ALREADY CLAIMED
-> OUT IF TAPES CLAIMED > TOP ENT
-> OUT IF UINF_REASON = BATCH AND TAPES CLAIMED >= UINF_DECKS
!
K = 92; ! INTERACTIVE USE OF TAPES NOT ALLOWED
-> OUT IF UINF_REASON = INTER AND DTRYING << 16 >= 0
!
K=VOL REQ(TSN,SNO,REQ,MODE)
IF K=0 START
CYCLE J=0,1,TOP ENT
IF CLAIMED(J)_TSN="" START
CLAIMED(J)_TSN=TSN
CLAIMED(J)_SNO=SNO
TAPES CLAIMED=TAPES CLAIMED + 1
-> OUT
FINISH
REPEAT
K=73; ! SHOULD NOT ARRIVE HERE !
FINISH
FINISH ELSE START
! RELEASE
K=0
CYCLE J=0,1,TOP ENT
IF TSN = "" # CLAIMED(J)_TSN C
OR (""#CLAIMED(J)_TSN=TSN) C
START
K=VOL REQ(CLAIMED(J)_TSN,CLAIMED(J)_SNO,1,0)
IF K=0 START
CLAIMED(J)=0
TAPES CLAIMED=TAPES CLAIMED - 1
FINISH
FINISH
REPEAT
FINISH
!
OUT:
RESULT = OUT(K, "SJII")
END ; ! DMAG CLAIM
!
!-----------------------------------------------------------------------
!
!<DMAGIO
externalintegerfn DMAG IO(integername REPLY FLAG, CONTROL, LEN,
integer TYPE, SNO, ADR)
!
! The parameter TYPE determines the action of the procedure:
! TYPE = 0 erase
! 1 read
! 2 write
! 3 check-write (not implemented)
! 4 check-read (no data transfer)
! 5 private chain (not implemented)
! 6 rewind to BT
! 7 spare
! 8 file position
! 9 tape position
! 10 write tape-mark
!
! SNO should be set with the value returned by a previous CLAIM
! (procedure DMAG CLAIM). ADR and LEN specify the area from or to which
! data is to be transferred (if relevant). In the case of TYPE = 1
! (read) LEN is set on return to be the number of bytes transferred.
!
! Bits in parameter CONTROL are used to specify detailed actions by the
! tape handler routine, as follows:
!
! 2**0 -
! 2**1 suppress error re-try
! 2**2 ignore short-block indication
! 2**3 ignore long-block indication
!
! Bits in CONTROL on return are used to indicate the occurrence of
! conditions during execution of a request, as follows:
!
! 2**0 short-block indication
! 2**1 long-block indication
!
! These bits will not be set on return if the respective bits for
! "ignore short/long-block indication" were specified in the request.
! REPLY FLAG (valid when the result of the function is zero) is set
! to zero for a successful operation, or
!
! 1 failure (parity etc.)
! 2 request rejected
! 4 beginning of tape, end of tape or unexpected tape
! mark found, but operation otherwise successful
!
!
! TYPE=8
!
! For request TYPE=8 (file position), LEN specifies the number of blocks
! to be skipped: negative means backwards, positive forwards, zero is
! invalid. If a tape-mark is found (REPLY FLAG=4) then a skip back of one
! block is performed before the reply is given. It is thus impossible
! to pass a tape-mark except by the use of a "tape position" request.
!
! TYPE=9
! For request TYPE=9 (tape position), LEN is the number of (notional)
! files to be skipped, and CONTROL is the number of tape-marks in a
! notional file, CONTROL must be positive. If LEN is negative the skip
! is backwards, if positive then it is forwards, zero is invalid.
! CONTROL*LEN tape-marks are skipped. A backwards skip will stop at BT.
! A forward skip will stop if the first block within a (notional) file is
! a tape-mark, the tape will then be positioned before the tape-mark and
! REPLY FLAG=4 will be returned. Thus if CONTROL=1 and LEN="very large",
! the tape will be positioned between the first double tape-mark
! encountered.
!>
! 09876543210
CONSTINTEGER VALMASK=B'11111010111'
! DATA TRAN MASK has bits set for operations for which:
! data transfer is to be done
! hence validate to be done on the area
! the area is to be locked down, and
! OUT 18 is to be done.
! 09876543210
CONSTINTEGER DATA TRAN MASK=B'00000001110'
CONSTINTEGER OUT11MASK =B'10000010001'
! Other operations get OUT 7 (an ordinary OUT) unless OUT11MASK has a bit set,
! when they get an OUT 11.
INTEGER ENTRY,LLEN, LCONTROL
INTEGER READWRITE,OUT18,K,DUM,EPAGE BYTES,TIMES,SAVID
INTEGER FLAG
RECORD (PARMF)Q
RECORD (PARMF)NAME P
!
LLEN = 0
LCONTROL = 0
!
FLAG = IN2(256 + 38)
-> OUT UNLESS FLAG = 0
!
FLAG = 45
-> OUT IF VAL(ADDR(REPLY FLAG),4,1,DCALLERS PSR)=0
-> OUT IF VAL(ADDR(CONTROL),4,1,DCALLERS PSR)=0
-> OUT IF VAL(ADDR(LEN),4,1,DCALLERS PSR)=0
!
FLAG=8
UNLESS (1<<TYPE)&VALMASK#0 THEN -> OUT
!
CYCLE ENTRY=0,1,TOPENT
IF CLAIMED(ENTRY)_SNO=SNO AND CLAIMED(ENTRY)_TSN#"" C
THEN -> GOTT
REPEAT
FLAG=67; ! TAPE NOT CLAIMED
-> OUT
GOTT:
LLEN = LEN
LCONTROL = CONTROL
Q = 0
!
IF TYPE = 7 START
! PASS REQUEST ON TO TAPE FOR SENSE ETC
! INPUT: SNO AND ADR
! OUTPUT: 5 WORDS IN ADR, ADR+4, ETC
P == RECORD(OUTPAD)
P = 0
P_P1 = SNO
P_DEST = X'310009'
*OUT_11
FLAG = 45
-> OUT IF VAL(ADR, 20, 1, DCALLERS PSR) = 0
MOVE(20, ADDR(P_P2), ADR)
FLAG = 0
-> OUT
FINISH
!
IF TYPE=6 THEN TYPE=17
OUT18=0; ! SAYS WHETHER OR NOT TO USE THE SPECIAL OUT 18
IF (1<<TYPE)&DATA TRAN MASK#0 START
! DATA AREA MUST BE READ-MODE FOR WRITING TO TAPE, AND WRITE MODE FOR
! READING FROM TAPE
READWRITE=0; ! FOR READ-ACCESS CHECK
IF TYPE=1 THEN READWRITE=1; ! FOR WRITE ACCESS CHECK
FLAG=45; ! AREA NOT AVAILABLE
-> OUT IF VAL(ADR,LLEN,READWRITE,DCALLERS PSR)=0
! ALSO THE DATA AREA MUST NOT CROSS A SEG BOUNDARY, AS THE GPC
! CANNOT COPE WITH THIS.
FLAG=56; ! CROSSES SEG BOUNDARY
IF ADR>>18 # (ADR+LLEN-1)>>18 THEN -> OUT; ! crosses seg bdy
OUT18=1
FINISH
! FOR A DATA TRANSFER WE REFERENCE ALL THE PAGES IN THE DATA AREA, TO GET THEM INTO
! MAIN STORE. IF THEY ARE NOT STILL THERE AT THE TIMEOF THE OUT 18, THEN
! P_DEST WILL BE SET TO -1, AND WE TRY AGAIN, UP TO FOUR TIMES (SAY).
TIMES=0
P==RECORD(OUTPAD)
UNTIL OUT18=0 C
OR (OUT18#0 AND (TIMES>4 OR P_DEST#-1)) C
CYCLE
! PASS REQUEST TO THE TAPE ROUTINE
Q_DEST=CLAIMED(ENTRY)_SNO
!Q_P1=ID - NOT REQUIRED
Q_P2=LCONTROL<<8 ! TYPE
Q_P3=ADR
Q_P4=LLEN
Q_P5=LLEN ! (DCALLERS ACR<<24)
! SET TOP BIT FOR A READ SO THAT SUPVR CAN MAKE SURE THAT
! THE WRITTEN BITS ARE SET - THE GPC DOESN'T DO IT!
IF TYPE=1 THEN Q_P5=Q_P5 ! (1<<31)
Q_P6=ADR
IF OUT18=0 START
SRCE ID=(SRCE ID + 1)&X'FFFF'
SAVID=SRCE ID
Q_SRCE=SAVID
LOUTP=Q
P=Q
MOUT AGAIN:
IF (1<<TYPE)&OUT11MASK#0 START
LOUTP STATE="DMAG IO DOUT 11"
*OUT_11
FINISH ELSE START
LOUTP STATE="DMAG IO OUT 7"
*OUT_7; ! PON AND SUSPEND
FINISH
IF P_DEST#-1 AND P_DEST&X'FFFF'#SAVID START
Q=P
PRINTSTRING("NREQ: ")
DDUMP(ADDR(Q),ADDR(Q)+32,-1,-1)
P_DEST=0; ! POFF
-> MOUT AGAIN
FINISH
FINISH ELSE START
! NOW REFERENCE ALL THE PAGES
EPAGE BYTES=EPAGE SIZE<<10
K=ADR & (¬(EPAGE BYTES - 1))
WHILE K<ADR+LLEN CYCLE
DUM=BYTEINTEGER(K)
K=K+EPAGE BYTES
REPEAT
P=Q
*OUT_18; ! SPECIAL PON AND SUSPEND
FINISH
TIMES=TIMES+1
REPEAT
IF P_DEST = -1 START
PREC("DMAGIO, FLAG=68", P, 0)
WRSN("TIMES ", TIMES)
WRSN("OUT18 ", OUT18)
FLAG = 68; ! Lock down fails
-> OUT
FINISH
!
FLAG=P_P2
! LEN is also used to return no. of tape marks passed, in the case of
! 'tape position', 'file position', etc.
!
!
K = P_P3; ! length of data read, or almost anything else!
IF TYPE = 1 START ; ! READ
IF K < 0 START ; ! backward read
K = -K
MOVE(K, ADR+LLEN-K, ADR) IF K < LLEN; ! need to move data down
FINISH
LLEN = K
FINISH
LLEN = K
!
LCONTROL=P_P4
OUT:
LOUTP STATE="DMAG IO exit"
!
IF 45 # FLAG # 47 START
! USER FIELDS ARE ACCESSIBLE
REPLY FLAG = FLAG
CONTROL = LCONTROL
LEN = LLEN
FINISH
!
RESULT = OUT(FLAG, "")
END ; ! DMAG IO
!
!-------------------end-of-included-file---------------------------------
!