@L3 COUK1247
80
@X @~
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H             SYS052
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL
~
~
                                                           ISSUE 11~
~V9 -1
~P
~V9 1
~YSYS052
~M~OSYS IMPLEMENTATION DESCRIPTION~
~
~M~OSection 5 version 2~
~S1~OSection 5.1 Exchangeable Storage Media Management~
~S1~O1. General Description
~BThis module provides basic facilities for handling exchangeable storage media
devices,
i.e. magnetic tape and exchangeable disc units. It is divided into three sets of
 procedures: those common to all ESM units,
those specific to magnetic tape units, and those specific to EDS units. The firs
t
group handles the identification of discs and tapes, and the assigning of units
to processes,
while the latter two deal with the actual driving of devices. Only the first two
 sets are implemented in this version.
~S1~O2. Interface
~
Other modules used~
Section 1 (Co-ordinator)~
Section 8 (Real Time Clock)~
Section 13 (Process Management)~
Section 14 (Virtual Store Management)~
Section 15 (Message Management)~
Organisational commands~
MOUNT (MEDIUM, REQ.NAME, REQ.LABEL)~
RELEASE (UNIT.NO)~
WRITE.LABEL (UNIT.NO, NEW.NAME, NEW.LABEL)~
RELABEL (UNIT.NO, NEW.NAME, NEW.LABEL)~
CANT.DO (PROC.NAME)~
MT.SKIP (UNIT.NO, DIRN)~
MT.READ (UNIT.NO, BUFFER.ADDR, COUNT, DIRN)~
MT.WRITE (UNIT.NO, BUFFER.ADDR, COUNT)~
MT.SKIP.TM (UNIT.NO, DIRN)~
MT.WRITE.TM (UNIT.NO)~
MT.REWIND (UNIT.NO)~
Configuration parameters~
NO.OF.UNITS~
NO.OF.MT.UNITS~
NO.OF.ED.UNITS~
FIRST.MT.UNIT~
FIRST.ED.UNIT~
MAX.MT.TRANSFER~
MT.PAR
~S1~O2.1 Hardware interface
~S1~O2.1.1 Magnetic Tape Interface
~BThe magnetic tape units are controlled by three arrays of registers indexed by
 unit number,
V.MT.CONTROL, V.MT.COUNT, and V.MT.ADDRESS. To initiate a magnetic tape operatio
n the core address
and size in bytes of the transfer, if any, is written to V.MT.ADDRESS and V.MT.C
OUNT,
respectively, and the code for the required operation is written to V.MT.CONTROL
.
V.MT.CONTROL also contains bits indicating the state of the device and
the reason for any interrupts induced by the unit. Its format is shown in the
diagram below:~
~3
~Q9
~

      |Unit      Interrupt|Command |~
       ~O|status     |status |        |~O~
       ~O| | |       | | | | |        |~O~
OFFLINE~O |~O |         | | | ~O| ~OOPERATION COMPLETE~
INITIAL~O   |~O         | | ~O|   ~OOPERATION FAILED~
                    | ~O|     ~OEOT / TM ENCOUNTERED~
                    ~O|       ~OSTATUS CHANGE~
~0
~S1~O2.1.1.1 Operator Control
~BAssociated with each magnetic tape unit is one operator control,
an ONLINE / OFFLINE button, indicating whether a tape is loaded and available
for use or not. This button directly controls the OFFLINE status bit.
~S1~O2.1.1.2 Unit States
~
~T# 12
~
00 ONLINE~IUnit isinitialised with tape online.~
10 OFFLINE~IUnit does not have a tape online.
~
01 INITIAL~IUnit will only accept INIT command.
~

~BOn system restart each unit interrupts with a STATUS CHANGE interrupt, in
the INITIAL state. An INIT command changes the state to either ONLINE or OFFLINE
depending on the operator button. From then on, state changes occur only on each
 use of
the operator button. All state changes cause a STATUS CHANGE interrupt.
~S1~O2.1.1.3 Interrupt States
~
~T# 25
~
?001 OPERATION COMPLETE~IOperation has completed successfully.
~
??10 OPERATION FAIL~IOperation has not succeeded.
~
?110 EOT / TM~IOperation failed because end-of-tape or tape mark encountered.
~
1??? STATUS CHANGE~IUnit status has changed.
~
~S1~O2.1.1.4 Commands
~T# 18
~
0000 STOP~ITerminates the current operation, if any, and clears any interrupts.
~
0001 INIT~IResets the operating parameters of the unit from the value in V.MT.AD
DRESS, and takes unit out of INITIAL state.
~
?010 SKIP~ISkips one record.
~
?011 SKIP.TM~ISkips records until the next tape mark is reached.
~
?100 READ~IReads one record.
~
0101 WRITE~IWrites one record.
~
0110 WRITE.TM~IWrites one tape mark.
~
0111 REWIND~IRewinds tape.
~
1??? [direction]~IIf set in SKIP, SKIP.TM, or READ command the operation occurs
in
the reverse direction.
~
~S1~O2.2 Software Interface
~S11) NO.OF.UNITS
~BThis configuratiion parameters sets the total number of ESM units of both type
s.
~S12) NO.OF.MT.UNITS
~BThis configuration parameter sets the number of magnetic tape units.
~S13) NO.OF.ED.UNITS
~BThis configuration parameter sets the number of exchangeable disc units.
~S14) FIRST.MT.UNIT
~BThis confguration parameter gives the unit number of the first magnetic tape u
nit.
~S15) FIRST.ED.UNIT
~BThis configuration parameter gives the unit number of the first exchangeable d
isc unit.
~S17) MAX.MT.TRANSFER
~BThis configuration parameter gives the size in bytes of the maximum magnetic
tape transfer.
~S18) MT.PAR
~BThis configuration parameter is used to set the operating parameters of magnet
ic tape units to a standard value.

~S1~O3. Implementation
~S1~O3.1 Outline of Operation
~BThe module consists of an interrupt activity, an interrupt procedure, a task
procedure, and various commands. The interrupt activity initially handles
all magnetic tape interrupts. Then, if necessary, it frees a process waiting for
 the interrupt or
sets a task. The interrupt procedure is used by the commands and task
to initiate operations. The task reads the name and label from a tape
when it first comes online.
~BThese various levels communicate using a variable associated with the unit
which contains all the necessary information about the status of the unit, the o
peration in progress, and the tape online.

~S1~O3.2 Data Structures
~
~T# 25
~
ESM.VARS~IAn array indexed by unit  number holding all the information relating
to the
control of a particular unit. Each entry is a record with the following fields:~
   :FILLER1~IA dummy field used to allign VOL.LABEL within the alternative field
 HEADER.
~
   :VOL.LABEL~IThe part of the ANSI standard header containing the volume label
(user identification in the standard).~
   :FILLER2~IA dummy field covering the rest of HEADER.~
   :STATUS~IThe status of the unit. The following literals are associated with i
t:~
      :LOADED~ISet when a tape is online and its header has been read.~
      :OP.FAIL.STATUS~ISet when an operation has failed.~
      :EOT.TM.STATUS~ISet when an EOT or tape mark has caused an operation to
fail.~
      :TASK.REQUEST~ISet when a task is requested for the unit.~
      :REWOUND~IIndicates tape has been or is being rewound in order for task to
read header.~
      :HEADER.READ~IIndicates header has been or is being read by task.~
      :RELABELED~ISet by RELABEL command to indicate header need not be read
by task.~
   :DISP~IThe displacement within the segment SEG of a read/write buffer.~
   :SEG~IThe segment containing a read/write buffer.~
   :SPN~IThe SPN of the process to which the unit is assigned.~
   :COUNT~IThe size in bytes of a read/write transfer.~
   :BUFFER.RA~IThe real address of a buffer segment.~
   :NAME~IThe name of the tape currently loaded on the unit.~
   :HEADER~IAn alternative field to the first three above containing the
full ANSI standard header.~

ABANDON.MNT~IAn array containing one variable for each process which is
set by CANT.DO when a MOUNT request cannot be satisfied.~
HALT.FOR.MT~IAn array containing one variable for each unit, set to the activity
bit of a process waiting for an operation on that unit to complete.~
~
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H                SYS052
~V9 -1
~F
@TITLE SYS05(2,11)

@COL 1S-2R-3R-4R-5R-6F

@FLOW 1-2-3-4-5-6

@BOX 1.0
EXCHANGEABLE STORAGE MEDIA MANAGEMENT
@BOX 4.0
PROCEDURES IN MODULE:
   INT1 MT INTERRUPT
   INT2 MT OPERATION
   INT3 ED INTERRUPT
   INT4 ED TRANSFER
   INT5 FIND NEW VOLUMES
   CMD1 MOUNT
   CMD2 RELEASE
   CMD3 WRITE LABEL
   CMD4 MONITOR
   CMD5 MT SKIP
   CMD6 MT READ
   CMD7 MT WRITE
   CMD8 MT SKIP TM
   CMD9 MT WRITE TM
   CMD10 MT REWIND
   CMD11 MT OPERATION
   CMD12 RELABEL
   CMD13 CANTDO
   CMD14 TINI.ESM
@BOX 6.0
END
@BOX 1.1
#SYS05/1
MODULE SYS05 (MT.INTERRUPT, ED.INTERRUPT, MOUNT, RELEASE, WRITE.LABEL,
   MT.SKIP, MT.READ, MT.WRITE, MT.SKIP.TM, MT.WRITE.TM, MT.REWIND,
   RELABEL, CANT.DO, TINI.ESM,
   ED.READ, ED.WRITE);
@BOX 2.1
LITERAL / INTEGER LABEL.SIZE = 14, HEADER.SIZE = 80;
TYPE BUFFER.TYPE IS
   LOGICAL32 [MAX.BLOCKS.MT.XFER] MT.BUFFER.RA
   INTEGER8 BLOCKS.USED;
TYPE ESM.VARS.TYPE IS
   LOGICAL8 [37] FILLER1
   LOGICAL8 [LABEL.SIZE] VOL.LABEL
   LOGICAL8 [29] FILLER2
   LOGICAL STATUS, DISP
   INTEGER SPN, SEG, BLOCK, COUNT, SECTOR.SIZE
   LOGICAL32 DISC.SIZE, DISC.BLOCK
   BUFFER.TYPE BUFFER.RA
   LOGICAL64 NAME
OR
   LOGICAL8 [HEADER.SIZE] HEADER;
@BOX 3.1
*GLOBAL 5;
LITERAL / INTEGER LOADED = 1, OP.FAIL.STATUS = 2, EOT.TM.STATUS = 4,
   NEW.VOL = %8000, REWOUND = %4000, HEADER.READ = %2000,
   RELABELED = %1000;
LITERAL / LOGICAL TRANSFER.COMPLETE = %100, TRANSFER.FAIL = %200,
   START.READ.TRANSFER = 1, START.WRITE.TRANSFER = 2, INT.BITS = %F00,
   ED.STATUS.CHANGE = %800;
LITERAL / LOGICAL STOP.CMD = 0, INIT.CMD = 1, SKIP = 2, SKIP.TM = 3, READ = 4,
   WRITE = 5, WRITE.TM = 6, REWIND = 7, OP.FAIL = %20, EOT.TM = %40,
   STATUS.CHANGE = %80, NEW.VOLUME = %8000, INITIAL = %4000, OP.MASK = %F, INT.M
ASK = %F0;
LITERAL / INTEGER MOUNT.REQUEST = 0, ASSIGNED = 1, RELEASED = 2;
ESM.VARS.TYPE [NO.OF.UNITS] ESM.VARS;
LOGICAL8 [SYS13.NO.OF.PROCS] ABANDON.MNT;
LOGICAL [NO.OF.MT.UNITS] HALT.FOR.MT;
LOGICAL [NO.OF.ED.UNITS] HALT.FOR.ED;
@BOX 4.1
::*INIT %6000;
*CODE 2;
::*INIT %6000;
PSPEC MT.INTERRUPT ();
PSPEC MT.INT.OP (INTEGER, INTEGER);
PSPEC ED.INTERRUPT ();
PSPEC ED.TRANSFER (INTEGER, INTEGER);
PSPEC FIND.NEW.VOLUMES (INTEGER, INTEGER);
   #SYSINT05.1
   #SYSINT05.2
   #SYSINT05.3
   #SYSINT05.4
   #SYSINT05.5
::*INIT %7000;
LSPEC ED.WRITE (INTEGER, ADDR, LOGICAL32, LOGICAL32);
*CODE 25;
LSPEC MOUNT (LOGICAL64, LOGICAL64, ADDR [LOGICAL8]);
LSPEC RELEASE (INTEGER);
LSPEC WRITE.LABEL (INTEGER, LOGICAL64, ADDR [LOGICAL8]);
PSPEC MONITOR (INTEGER, LOGICAL64, LOGICAL64, INTEGER);
LSPEC MT.SKIP (INTEGER, INTEGER, INTEGER);
LSPEC MT.READ (INTEGER, ADDR, INTEGER, INTEGER);
LSPEC MT.WRITE (INTEGER, ADDR, INTEGER);
LSPEC MT.SKIP.TM (INTEGER, INTEGER, INTEGER);
LSPEC MT.WRITE.TM (INTEGER);
LSPEC MT.REWIND (INTEGER);
PSPEC MT.OPERATION (INTEGER, LOGICAL, LOGICAL, ADDR, INTEGER);
LSPEC ED.READ (INTEGER, ADDR, LOGICAL32, LOGICAL32);
::LSPEC ED.WRITE (INTEGER, ADDR, INTEGER, INTEGER);
LSPEC RELABEL (INTEGER, LOGICAL64, ADDR [LOGICAL8]);
LSPEC CANT.DO (LOGICAL64);
   #SYSCMD05.1
   #SYSCMD05.2
   #SYSCMD05.3
   #SYSCMD05.4
   #SYSCMD05.12
   #SYSCMD05.13
   #SYSCMD05.5
   #SYSCMD05.6
   #SYSCMD05.7
   #SYSCMD05.8
   #SYSCMD05.9
   #SYSCMD05.10
   #SYSCMD05.11
   #SYSCMD05.15
   #SYSCMD05.16
*CODE 19;
PSPEC TINI.ESM (INTEGER);
   #SYSCMD05.14
@BOX 6.1
*END
@END
@TITLE SYS05/1(2,11)

@COL 1S-2R-3R-4R

@FLOW 1-2-3-4
@BOX 1.0
OTHER MODULES REFERENCED
@BOX 4.0
SYS01 COORDINATOR
SYS03 DRUM MANAGER
SYS08 REAL TIME CLOCK
SYS13 PROCESS MANAGER
SYS14 VIRTUAL STORE MANAGER
SYS15 MESSAGE MANAGEMENT
@BOX 1.1
::EXTERNAL ENVIROMENT
@BOX 2.1
IMPORT LITERAL NO.OF.UNITS, NO.OF.MT.UNITS, FIRST.MT.UNIT, FIRST.ED.UNIT,
   NO.OF.ED.UNITS, MAX.MT.TRANSFER, MT.PAR, MAX.BLOCKS.MT.XFER, ED.BLOCK;
IMPORT VSTORE V.MT.CONTROL [], V.MT.COUNT [];
IMPORT VSTORE LOGICAL32 V.MT.ADDRESS [];
IMPORT VSTORE V.DISC.CONTROL [], V.DISC.CADDRESS [], V.DISC.SIZE [];
IMPORT VSTORE LOGICAL32 V.DISC.DADDRESS [];
@BOX 3.1
PSPEC VALIDATE (ADDR, LOGICAL) / INTEGER;
@BOX 4.1
IMPORT LITERAL SYS01.TAPE.ACTIVITY, SYS01.DISC.ACTIVITY, SYS01.ESM.HALT;
LOGICAL SYS01.CURRENT.ACTIVITY.BIT;
PSPEC SYS01.NEXT.ACTIVITY ();
PSPEC SYS01.HALT (LOGICAL, INTEGER);
PSPEC SYS01.FREE (LOGICAL, INTEGER);
PSPEC SYS01.CHECK.IN (INTEGER, INTEGER);
PSPEC SYS01.CHECK.OUT (INTEGER, INTEGER);
PSPEC TIME.AND.DATE ();
IMPORT LITERAL SYS13.NO.OF.PROCS;
INTEGER SYS13.CURRENT.SPN;
PSPEC SYS13.INT.PROC (LOGICAL, LOGICAL);
PSPEC SYS13.ENTER.INT.LEVEL (ADDR SYS13.INT.PROC, LOGICAL, LOGICAL);
PSPEC NAMES ();
PSPEC LOOK.UP.PROCESS (LOGICAL64, LOGICAL64);
PSPEC SYS13.CHECK.PRIV ();
IMPORT LITERAL SYS14.SEG.SHIFT, SYS14.PAGE.SHIFT, SYS14.PAGE.SIZE;
IMPORT LITERAL ADDR SYS14.SEG.SIZE;
PSPEC CREATE.SEGMENT (INTEGER, ADDR);
PSPEC RELEASE.SEGMENT (INTEGER);
PSPEC MAP (INTEGER, INTEGER, INTEGER);
PSPEC SYS14.CMD.MAP (INTEGER, INTEGER);
PSPEC SYS14.GET.BLOCK (INTEGER, INTEGER) / INTEGER32;
PSPEC SYS14.UPDATE.BLOCK (INTEGER32);
PSPEC SYS14.REL.BLOCK (INTEGER32);
PSPEC WAIT (LOGICAL, INTEGER);
PSPEC SEND.MESSAGE (ADDR [LOGICAL8], ADDR [INTEGER], INTEGER, INTEGER,
   INTEGER, LOGICAL);
ADDR PW0, PW1, PW2, PW3;
LOGICAL64 PWW1, PWW2, PWW3;
@END
@TITLE SYSINT05.1(2,11)

@COL 1S-16N-2T-3R-20T-17R-4T-5R-6R-7R-8T-13R-11N-12F
@COL 14N-15R-22R-19N

@ROW 16-14
@ROW 3-15
@ROW 22-17
@ROW 19-11

@FLOW 1-16-2FOUND-3-20NO-17-4NO-5-6-7-8NO-13-11-19-14-16
@FLOW 2NONE-15-14-16
@FLOW 4YES-8
@FLOW 8YES-11
@FLOW 20YES-22-14

@BOX 1.0
MT INTERRUPT ()
@BOX 2.0
FIND A UNIT TO SERVICE
@BOX 3.0
NOTE INTERRUPT STATUS AND CLEAR
INTERRUPTS
@BOX 4.0
STATUS CHANGE INTERRUPT ONLY?
@BOX 5.0
SET UNIT STATUS
@BOX 6.0
RELEASE BUFFER SEG
IF ANY
@BOX 7.0
FREE USER ACTIVITY
@BOX 8.0
OPERATION COMPLETE INTERRUPT ONLY?
@BOX 12.0
END
@BOX 13.0
MARK AS OFFLINE AND
UNASSIGNED
@BOX 15.0
NEXT ACTIVITY
[SYS01]
@BOX 17.0
SELECT ESM VARS
@BOX 20.0
INITIAL INTERRUPT?
@BOX 22.0
INITIALISE UNIT
@BOX 1.1
PROC MT.INTERRUPT;
INTEGER UNIT.NO, BLK, INDEX;
LOGICAL INT.STATUS;
@BOX 2.1
-1 => UNIT.NO;
WHILE 1 +> UNIT.NO < NO.OF.MT.UNITS AND
   V.MT.CONTROL [UNIT.NO] => INT.STATUS & INT.MASK = 0
DO OD
IF UNIT.NO = NO.OF.MT.UNITS
@BOX 3.1
STOP.CMD => V.MT.CONTROL [UNIT.NO];
@BOX 4.1
IF INT.STATUS & %FE = 0
@BOX 5.1
%6 & STATUS -=> STATUS;
INT.STATUS ->> 4 & %6 !> STATUS;
V.MT.COUNT [UNIT.NO] => COUNT;
@BOX 6.1
SELECT BUFFER.RA;
FOR INDEX < BLOCKS.USED DO
   IF MT.BUFFER.RA [INDEX] => BLK /= 0 THEN
      IF INT.STATUS & 7 = READ THEN
         SYS14.UPDATE.BLOCK (BLK);
      FI
      SYS14.REL.BLOCK (BLK);
      0 => MT.BUFFER.RA [INDEX];
   FI
OD
0 => BLOCKS.USED;
@BOX 7.1
SYS01.FREE (HALT.FOR.MT [UNIT.NO], SYS01.ESM.HALT);
@BOX 8.1
IF INT.STATUS & STATUS.CHANGE = 0
@BOX 12.1
END
@BOX 13.1
0 => STATUS;
0 => SPN;
@BOX 15.1
SYS01.NEXT.ACTIVITY ();
@BOX 17.1
SELECT ESM.VARS [UNIT.NO];
@BOX 20.1
IF INT.STATUS & INITIAL /= 0
@BOX 22.1
MT.PAR => V.MT.COUNT [UNIT.NO];
INIT.CMD => V.MT.CONTROL [UNIT.NO];
@END
@TITLE SYSINT05.2(2,11)

@COL 1S-8R-2T-3R-4R-5R-6R-7F

@FLOW 1-8-2NO-3-4-5-6-7
@FLOW 2YES-5

@BOX 1.0
MT INT OP (UNIT NO., OPERATION)
@BOX 2.0
NON-TRANSFER OPERATION?
@BOX 3.0
FIND CORE ADDRESS OF BUFFER
SEGMENT
@BOX 4.0
SET ADDRESS AND COUNT FOR TRANSFER
@BOX 5.0
START OPERATION
@BOX 6.0
HALT ACTIVITY FOR MT OPERATION
@BOX 7.0
END
@BOX 8.0
SELECT ESM VARS
@BOX 1.1
PROC MT.INT.OP (UNIT.NO, OP);
INTEGER INDEX, BLK, UNIT.SPAN, COUNT.COPY;
LOGICAL32 DISP32;
@BOX 2.1
IF OP /= READ /= WRITE
@BOX 3.1
UNIT.NO * MAX.BLOCKS.MT.XFER - 1 => UNIT.SPAN;
-1 => INDEX;
DISP => DISP32;
COUNT + SYS14.PAGE.SIZE => COUNT.COPY;
BLOCK - 1 => BLK;
@BOX 4.1
SELECT BUFFER.RA;
WHILE SYS14.PAGE.SIZE -> COUNT.COPY > 0 DO
   SYS14.GET.BLOCK (SEG, 1 +> BLK) => MT.BUFFER.RA [1 +> INDEX]
      + DISP32 => V.MT.ADDRESS [1 +> UNIT.SPAN];
   0 => DISP32;
OD
INDEX + 1 => BLOCKS.USED;
@BOX 5.1
COUNT => V.MT.COUNT [UNIT.NO];
OP => V.MT.CONTROL [UNIT.NO];
@BOX 6.1
IF SPN /= 0 OR OP & 7 /= 7 THEN
   SYS01.HALT (SYS01.CURRENT.ACTIVITY.BIT => HALT.FOR.MT [UNIT.NO], SYS01.ESM.HA
LT);
FI
@BOX 7.1
END
@BOX 8.1
SELECT ESM.VARS [UNIT.NO];
@END
@TITLE SYSINT05.3(2,11)
@COL 13R-20T
@COL 1S-2R-17N-3T-15T-4T-16R-5R-8R-9N-11F
@COL 19N-10N

@ROW 17-19
@ROW 4-13
@ROW 9-10

@FLOW 1-2-17-3OK-15NO-4YES-5-8-9-10-19-17
@FLOW 4NO-16-5
@FLOW 3FAIL-2
@FLOW 15YES-13-20NO-8
@FLOW 20YES-4
@BOX 1.0
ED INTERRUPT
@BOX 2.0
CALL LOW LEVEL SCHEDULER
[SYS01]
@BOX 3.0
FIND INTERRUPTING UNIT
@BOX 4.0
TRANSFER SUCCESSFUL ?
@BOX 5.0
FREE ACTIVITY HALTED
FOR THIS TRANSFER
[SYS01]
@BOX 8.0
RESET INTERRUPTS FOR UNIT
@BOX 11.0
END
@BOX 13.0
NOTE STATUS CHANGE
@BOX 15.0
STATUS CHANGE?
@BOX 16.0
RETURN FAULT TO
ACTIVITY
@BOX 20.0
TRANSFER FINISHED ALSO?
@BOX 1.1
PROC ED.INTERRUPT;
INTEGER UNIT.COUNT, UNIT, ED.STATUS;
-1 => UNIT;
@BOX 2.1
SYS01.NEXT.ACTIVITY ();
@BOX 3.1
IF 1 +> UNIT = NO.OF.ED.UNITS THEN
   0 => UNIT;
FI
-1 => UNIT.COUNT;
WHILE 1 +> UNIT.COUNT < NO.OF.ED.UNITS AND
   V.DISC.CONTROL [UNIT] & INT.BITS = 0 DO
   IF 1 +> UNIT = NO.OF.ED.UNITS THEN
      0 => UNIT;
   FI
OD
IF UNIT.COUNT = NO.OF.ED.UNITS
@BOX 4.1
IF ED.STATUS & TRANSFER.COMPLETE /= 0
@BOX 5.1
SYS01.FREE (HALT.FOR.ED [UNIT], SYS01.ESM.HALT);
@BOX 8.1
0 => V.DISC.CONTROL [UNIT];
@BOX 11.1
END
@BOX 13.1
0 => SPN => STATUS;
@BOX 15.1
SELECT ESM.VARS [UNIT + FIRST.ED.UNIT];
IF V.DISC.CONTROL [UNIT] => ED.STATUS & ED.STATUS.CHANGE /= 0
@BOX 16.1
OP.FAIL.STATUS !> STATUS;
@BOX 20.1
IF TRANSFER.COMPLETE ! TRANSFER.FAIL & ED.STATUS /= 0
@END
@TITLE SYSINT05.4(2,11)

@COL 1S-2R-10T-3R-4R-5R-6T-7T-8F
@COL 9R

@ROW 9-3

@FLOW 1-2-10OK-3-4-5-6NO-7NO-8
@FLOW 10FAIL-9-8
@FLOW 6YES-8
@FLOW 7YES-10

@BOX 1.0
ED TRANSFER (UNIT NO., OPERATION)
@BOX 2.0
SELECT ESM VARS
@BOX 3.0
START TRANSFER
@BOX 4.1
HALT CURRENT ACTIVITY
FOR TRANSFER
@BOX 5.0
RELEASE STORE BLOCK
[SYS14]
@BOX 6.0
TRANSFER FAILED?
@BOX 7.0
TRANSFER CONTINUING?
@BOX 8.0
END
@BOX 9.0
RETURN ERROR STATUS
@BOX 10.0
GET STORE BLOCK
[SYS14]
@BOX 1.1
PROC ED.TRANSFER (UNIT.NO, OP);
INTEGER I, SECTORS.PER.PAGE, ED.UNIT, TRAN.SIZE;
INTEGER32 BLOCK.RA;
@BOX 2.1
SELECT ESM.VARS [UNIT.NO];
SYS14.PAGE.SIZE / SECTOR.SIZE => SECTORS.PER.PAGE;
@BOX 3.1
UNIT.NO - FIRST.ED.UNIT => ED.UNIT;
STATUS & OP.FAIL.STATUS -=> STATUS;
DISC.BLOCK => V.DISC.DADDRESS [ED.UNIT];
IF SECTORS.PER.PAGE => TRAN.SIZE > COUNT THEN
   COUNT => TRAN.SIZE;
FI
TRAN.SIZE => V.DISC.SIZE [ED.UNIT];
BLOCK.RA ->> SYS14.PAGE.SHIFT * SECTORS.PER.PAGE
   => V.DISC.CADDRESS [ED.UNIT];
IF OP = 0 THEN
   START.READ.TRANSFER => V.DISC.CONTROL [ED.UNIT];
ELSE
   START.WRITE.TRANSFER => V.DISC.CONTROL [ED.UNIT];
FI
@BOX 4.1
SYS01.CURRENT.ACTIVITY.BIT => HALT.FOR.ED [ED.UNIT];
SYS01.HALT (SYS01.CURRENT.ACTIVITY.BIT, SYS01.ESM.HALT);
@BOX 5.1
IF OP = 0 THEN
   SYS14.UPDATE.BLOCK (BLOCK.RA);
FI
SYS14.REL.BLOCK (BLOCK.RA);
@BOX 6.1
IF STATUS & OP.FAIL.STATUS /= 0
@BOX 7.1
1 +> BLOCK;
TRAN.SIZE +> DISC.BLOCK;
IF TRAN.SIZE -> COUNT > 0
@BOX 8.1
END
@BOX 9.1
OP.FAIL.STATUS !> STATUS;
@BOX 10.1
IF SYS14.GET.BLOCK (SEG, BLOCK) => BLOCK.RA = -1
@END

@TITLE SYSINT05.5(2,11)
@COL 1S-2R-3R-4F

@FLOW 1-2-3-4

@BOX 1.0
FIND NEW VOLUMES
@BOX 2.0
CHECK TAPE VOLUMES
@BOX 3.0
CHECK DISC VOLUMES
@BOX 4.0
END
@BOX 1.1
PROC FIND.NEW.VOLUMES (DUMMY1, DUMMY2);
INTEGER UNIT;
@BOX 2.1
FOR UNIT < NO.OF.MT.UNITS DO
   IF SPN OF ESM.VARS [UNIT] = 0 AND
      V.MT.CONTROL [UNIT] & NEW.VOLUME /= 0 THEN
      NEW.VOL !> STATUS OF ESM.VARS [UNIT];
   FI
OD
@BOX 3.1
FOR UNIT < NO.OF.ED.UNITS DO
   IF SPN OF ESM.VARS [UNIT + FIRST.ED.UNIT] = 0 AND
      V.DISC.CONTROL [UNIT] & NEW.VOLUME /= 0 THEN
      BEGIN
         SELECT ESM.VARS [UNIT + FIRST.ED.UNIT];
         NEW.VOL !> STATUS;
         V.DISC.SIZE [UNIT] => SECTOR.SIZE;
         V.DISC.DADDRESS [UNIT] + 1 => DISC.SIZE;
      END
   FI
OD
@BOX 4.1
END
@END


@TITLE SYSCMD05.1(2,11)

@COL 1S-2T-3R-4R-5T-6R-23R-7T-8R-9R-18R-10T-11R-12R-13R-14R-21N-15F
@COL 22R-16R-19R-17R-20N

@ROW 16-6
@ROW 19-11
@ROW 20-21
@ROW 22-3

@FLOW 1-2OK-3-4-5NO-6-23-7FAIL-8-9-18-5
@FLOW 2FAIL-22-20
@FLOW 5YES-16-20-21
@FLOW 7SUCCEED-10NO-11-12-13-14-21-15
@FLOW 10YES-19-17-20

@BOX 1.0
MOUNT (MEDIUM, REQUIRED NAME, REQUIRED LABEL)
@BOX 2.0
VALIDATE LABEL
@BOX 3.0
LIMIT SEARCH TO REQUIRED MEDIUM
@BOX 4.0
CLEAR ABANDON INDICATOR
@BOX 5.0
ABANDON MOUNT?
@BOX 6.0
CHECK IN
[SYS01]
@BOX 7.0
SEARCH FOR REQUIRED VOLUME
@BOX 8.0
CHECK OUT
[SYS01]
@BOX 9.0
SEND REQUEST FOR VOLUME TO
BE MOUNTED
@BOX 10.0
LABEL INCORRECT?
@BOX 11.0
ASSIGN UNIT TO USER
@BOX 12.0
CHECK OUT
[SYS01]
@BOX 13.0
MONITOR ASSIGNMENT
@BOX 14.0
REWIND IF TAPE
@BOX 15.0
END
@BOX 16.0
RETURN FAULT STATUS -70
(MOUNT ABANDONED)
@BOX 17.0
RETURN FAULT STATUS -71
(LABEL INCORRECT)
@BOX 18.0
WAIT BEFORE RETRYING
@BOX 19.0
CHECK OUT
[SYS01]
@BOX 22.0
RETURN FAULT STATUS -8
(VALIDATE FAIL)
@BOX 23.0
CHECK VOLUMES
#SYSCMD05.1.1
@BOX 1.1
PROC MOUNT (MEDIUM, REQ.NAME, REQ.LABEL);
INTEGER REQ.LABEL.SIZE, SEARCH.START, SEARCH.END, UNIT.NO, I;
@BOX 2.1
IF SIZE (REQ.LABEL) => REQ.LABEL.SIZE > 0 AND
   [VALIDATE (BYTE (^REQ.LABEL^ [0]), %C) /= 0 OR
      VALIDATE  (BYTE (^REQ.LABEL^ [REQ.LABEL.SIZE - 1]), %C) /= 0]
@BOX 3.1
IF MEDIUM = "DISC" THEN
   FIRST.ED.UNIT - 1 => SEARCH.START;
   FIRST.ED.UNIT + NO.OF.ED.UNITS => SEARCH.END;
ELSE
   "TAPE" => MEDIUM;
   FIRST.MT.UNIT - 1 => SEARCH.START;
   FIRST.MT.UNIT + NO.OF.MT.UNITS => SEARCH.END;
FI
@BOX 4.1
0 => ABANDON.MNT [SYS13.CURRENT.SPN];
@BOX 5.1
IF ABANDON.MNT [SYS13.CURRENT.SPN] /= 0
@BOX 6.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECK.IN, 0, 0);
@BOX 7.1
SEARCH.START => UNIT.NO;
WHILE 1+> UNIT.NO < SEARCH.END AND
   [STATUS OF ESM.VARS [UNIT.NO] & LOADED = 0 OR
      REQ.NAME /= NAME OF ESM.VARS [UNIT.NO] OR
      SPN OF ESM.VARS [UNIT.NO] /= 0]
DO OD
IF UNIT.NO < SEARCH.END
@BOX 8.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECK.OUT, 0, 0);
@BOX 9.1
MONITOR (MOUNT.REQUEST, MEDIUM, REQ.NAME, 0);
@BOX 10.1
SELECT ESM.VARS [UNIT.NO];
-1 => I;
WHILE 1 +> I < REQ.LABEL.SIZE
   AND REQ.LABEL^ [I] = VOL.LABEL [I]
DO OD
IF REQ.LABEL.SIZE < LABEL.SIZE
   AND I = REQ.LABEL.SIZE
THEN
   1 -> I;
   WHILE 1 +> I < LABEL.SIZE AND VOL.LABEL [I] = " "
   DO OD
FI
IF I /= LABEL.SIZE
@BOX 11.1
SYS13.CURRENT.SPN => SPN;
@BOX 12.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECK.OUT, 0, 0);
@BOX 13.1
MONITOR (ASSIGNED, 0, 0, UNIT.NO);
@BOX 14.1
IF UNIT.NO >= FIRST.MT.UNIT < FIRST.MT.UNIT + NO.OF.MT.UNITS THEN
   SYS13.ENTER.INT.LEVEL (^MT.INT.OP, UNIT.NO, REWIND);
ELSE
   DISC.SIZE * SECTOR.SIZE => PW2;
FI
UNIT.NO => PW1;
@BOX 15.1
END
@BOX 16.1
-70 => PW0;
@BOX 17.1
-71 => PW0;
@BOX 18.1
WAIT (0, 15);
@BOX 19.1
SYS13.ENTER.INT.LEVEL (^SYS01.CHECK.OUT, 0, 0);
@BOX 22.1
-8 => PW0;
@BOX 23.1
#SYSCMD05.1.1
@END
@TITLE SYSCMD05.1.1(2,11)

@COL 12N-7R-13N
@COL 1S-14N-20R-2T-3R-15T-18T-4T-10R-6R-11N
@COL 8F-16R-19R-17N

@ROW 16-18
@ROW 19-4
@ROW 17-11
@ROW 12-14
@ROW 13-11
@ROW 8-3
@ROW 7-10

@FLOW 1-14-20-2FOUND-3-15NO-18NO-4NO-10-6-11-13-12-14
@FLOW 2NONE-8
@FLOW 4YES-7-10
@FLOW 15YES-16-17-11
@FLOW 18YES-19-6

@BOX 1.0
CHECK VOLUMES
@BOX 2.0
FIND UNIT TO SERVICE
@BOX 3.0
CLEAR NEW VOLUME FLAG
@BOX 4.0
DOES UNIT NEED REWOUND?
@BOX 6.0
SET NAME AND INDICATE UNIT LOADED
@BOX 7.0
EXECUTE REWIND OPERATION
@BOX 8.0
END
@BOX 10.0
READ HEADER FROM TAPE
@BOX 15.0
IS UNIT RELABELED?
@BOX 16.0
SET LOADED STATUS
@BOX 18.0
DISC UNIT?
@BOX 19.0
READ HEADER FROM DISC
@BOX 20.0
FIND NEW VOLUMES
@BOX 1.1
::CHECK VOLUMES
BEGIN
INTEGER UNIT.NO, I, SHIFT, CH;
LOGICAL8 [HEADER.SIZE] HDR;
ADDR [LOGICAL8] PTR;
-1 => UNIT.NO;
@BOX 2.1
WHILE 1 +> UNIT.NO < NO.OF.UNITS AND
   STATUS OF ESM.VARS [UNIT.NO] & NEW.VOL = 0
DO OD
IF UNIT.NO = NO.OF.UNITS
@BOX 3.1
SELECT ESM.VARS [UNIT.NO];
NEW.VOL -=> STATUS;
@BOX 4.1
IF STATUS & REWOUND = 0
@BOX 6.1
0 => NAME;
48 => SHIFT
FOR I < 6 DO
   8 -> SHIFT;
   IF HEADER [4 + I] => CH = %20 THEN
      0 => CH;
   FI
   CH <<- SHIFT !> NAME;
OD
LOADED !> STATUS;
@BOX 7.1
REWOUND !> STATUS;
MT.OPERATION (UNIT.NO, REWIND, 0, 0, 0);
@BOX 8.1
END
@BOX 10.1
HEADER.READ !> STATUS;
MT.OPERATION (UNIT.NO, READ, 0, BYTE (^HDR), HEADER.SIZE);
FOR I < HEADER.SIZE DO
   HDR [I] => HEADER [I];
OD
@BOX 15.1
IF STATUS & RELABELED /= 0
@BOX 16.1
LOADED !> STATUS;
@BOX 18.1
IF UNIT.NO >= FIRST.ED.UNIT
@BOX 19.1
0 => SEG;
ED.BLOCK => BLOCK;
0 => DISC.BLOCK;
1 => COUNT;
SYS13.ENTER.INT.LEVEL (^ED.TRANSFER, UNIT.NO, 0);
MAKE (LOGICAL8, HEADER.SIZE, ED.BLOCK <<- SYS14.PAGE.SHIFT)
   => PTR;
FOR I < HEADER.SIZE DO
   PTR^ [I] => HEADER [I];
OD
@BOX 20.1
SYS13.ENTER.INT.LEVEL (^FIND.NEW.VOLUMES, 0, 0);
@END
@TITLE SYSCMD05.2(2,11)

@COL 7R-8R-10N
@COL 1S-2T-3T-4T-5R-11N-6F
@COL 9R

@ROW 7-4
@ROW 8-5
@ROW 9-3
@ROW 10-11

@FLOW 1-2NO-3NO-4NO-5-11-6
@FLOW 2YES-9-11
@FLOW 3YES-7-10-11
@FLOW 4YES-8-10
@BOX 1.0
RELEASE (UNIT NO.)
@BOX 2.0
RELEASE ALL UNITS?
@BOX 3.0
IS UNIT NUMBER INVALID
@BOX 4.0
UNIT UNAVAIABLE TO THIS PROCESS?
@BOX 5.0
RELEASE UNIT
@BOX 6.0
END
@BOX 7.0
RETURN FAULT STATUS -73
(ILLEGAL UNIT NUMBER)
@BOX 8.0
RETURN FAULT STATUS -76
(UNIT NOT ASSIGNED TO PROCESS)
@BOX 9.0
RELEASE ALL UNITS OF THIS PROCESS
@BOX 1.1
PROC RELEASE (UNIT.NO);
@BOX 2.1
IF UNIT.NO < 0
@BOX 3.1
IF UNIT.NO >= NO.OF.UNITS
@BOX 4.1
SELECT ESM.VARS [UNIT.NO];
IF SYS13.CURRENT.SPN /= SPN
@BOX 5.1
0 => SPN;
MONITOR (RELEASED, 0, 0, UNIT.NO);
@BOX 6.1
END
@BOX 7.1
-73 => PW0;
@BOX 8.1
-76 => PW0;
@BOX 9.1
FOR UNIT.NO < NO.OF.UNITS DO
   IF SYS13.CURRENT.SPN = SPN OF ESM.VARS [UNIT.NO] THEN
      0 => SPN OF ESM.VARS [UNIT.NO];
      MONITOR (RELEASED, 0, 0, UNIT.NO);
   FI
OD
@END
@TITLE SYSCMD05.3(2,11)
@COL 10R
@COL 1S-2T-3T-4T-5R-6R-12T-7R-8R-9F
@COL 16R-11R-15T-13R-14N
@ROW 11-4
@ROW 10-5
@ROW 15-7
@ROW 16-3
@FLOW 1-2OK-3NO-4NO-5-6-12NO-7-8-9
@FLOW 2FAIL-16-14
@FLOW 4YES-10-9
@FLOW 3YES-11-14-9
@FLOW 12YES-15OK-13-14
@FLOW 15FAIL-9
@BOX 1.0
WRITE LABEL (UNIT NO., NEW NAME, NEW LABEL);
@BOX 2.0
VALIDATE LABEL
@BOX 3.0
IS UNIT NUMBER INVALID?
@BOX 4.0
UNIT AVALIABLE TO THIS PROCESS?
@BOX 5.0
INITIALISE HEADER
@BOX 6.0
COPY NEW NAME AND LABEL
INTO HEADER
@BOX 7.0
GET TRANSFER INFORMATION
FOR HEADER
@BOX 8.0
EXECUTE TRANSFER
@BOX 9.0
END
@BOX 10.0
RETURN FAULT STATUS -76
(UNIT NOT ASSIGNED TO PROCESS)
@BOX 11.0
RETURN FAULT STATUS -73
(ILLEGAL UNIT NUMBER)
@BOX 12.0
WRITE TO DISC?
@BOX 13.0
TRANSFER TO DISC
@BOX 15.0
CREATE BUFFER SEGMENT
@BOX 1.1
PROC WRITE.LABEL (UNIT.NO, NEW.NAME, NEW.LABEL);
INTEGER NEW.LABEL.SIZE, I, SHIFT, T.SEG, T.BLOCK, T.DISP, CH;
ADDR TEMP, BUFF.ADDR, BUFF.SEG;
LOGICAL8 [HEADER.SIZE] HDR;
ADDR [LOGICAL8] PTR;
@BOX 2.1
IF SIZE (NEW.LABEL) => NEW.LABEL.SIZE > 0 THEN
   VALIDATE (BYTE (^NEW.LABEL^ [0]), %C);
   VALIDATE (BYTE (^NEW.LABEL^ [NEW.LABEL.SIZE - 1]), %C);
@BOX 16.0
RETURN FAULT STATUS -8
(VALIDATE FAIL)
@BOX 1.1
PROC WRITE.LABEL (UNIT.NO, NEW.NAME, NEW.LABEL);
INTEGER NEW.LABEL.SIZE, I, SHIFT, T.SEG, T.BLOCK, T.DISP, CH;
ADDR TEMP, BUFF.ADDR, BUFF.SEG;
LOGICAL8 [HEADER.SIZE] HDR;
ADDR [LOGICAL8] PTR;
@BOX 2.1
IF SIZE (NEW.LABEL) => NEW.LABEL.SIZE > 0 AND
   [VALIDATE (BYTE (^NEW.LABEL^ [0]), %C) /= 0 OR
      VALIDATE (BYTE (^NEW.LABEL^ [NEW.LABEL.SIZE - 1]), %C) /= 0]
@BOX 3.1
IF UNIT.NO < 0 OR UNIT.NO >= NO.OF.UNITS
@BOX 4.1
SELECT ESM.VARS [UNIT.NO];
IF SYS13.CURRENT.SPN /= SPN
@BOX 5.1
FOR I < HEADER.SIZE DO
   " " => HEADER [I];
OD
DATAVEC VOL1 (LOGICAL8)
 "VOL1"
END
FOR I < 4 DO
   VOL1 [I] => HEADER [I];
OD
"1" => HEADER [79];
@BOX 6.1
NEW.NAME => NAME;
48 => SHIFT;
FOR I < 6 DO
   8 -> SHIFT;
   NEW.NAME ->> SHIFT => CH;
   IF CH = 0 THEN
      " " => CH;
   FI
   CH => HEADER [4 + I];
OD
IF NEW.LABEL.SIZE > LABEL.SIZE THEN
   LABEL.SIZE => NEW.LABEL.SIZE;
FI
FOR I < NEW.LABEL.SIZE DO
   NEW.LABEL^ [I] => VOL.LABEL [I];
OD
@BOX 7.1
FOR I < HEADER.SIZE DO
   HEADER [I] => HDR [I];
OD
SYS14.CMD.MAP (-1, BYTE (^HDR)  => TEMP ->> SYS14.SEG.SHIFT);
PW1 => T.SEG;
TEMP ->> SYS14.SEG.SHIFT <<- SYS14.SEG.SHIFT -: TEMP => T.DISP
   ->> SYS14.PAGE.SHIFT =>  T.BLOCK <<- SYS14.PAGE.SHIFT -> T.DISP;
@BOX 8.1
SYS13.ENTER.INT.LEVEL (^MT.INT.OP, UNIT.NO, REWIND);
T.SEG => SEG;
T.BLOCK => BLOCK;
T.DISP => DISP;
HEADER.SIZE => COUNT;
SYS13.ENTER.INT.LEVEL (^MT.INT.OP, UNIT.NO, WRITE);
@BOX 9.1
END
@BOX 10.1
-76 => PW0;
@BOX 11.1
-73 => PW0;
@BOX 12.1
IF UNIT.NO >= FIRST.ED.UNIT
@BOX 13.1
MAKE (LOGICAL8, SYS14.PAGE.SIZE, PW1 => BUFF.SEG
   <<- SYS14.SEG.SHIFT => BUFF.ADDR) => PTR;
FOR I < HEADER.SIZE DO
   HEADER [I] => PTR^ [I];
OD
ED.WRITE (UNIT.NO, BUFF.ADDR, 0, SECTOR.SIZE);
PW0 => TEMP;
RELEASESEGMENT (BUFF.SEG);
TEMP => PW0;
@BOX 15.1
CREATE.SEGMENT (-1, SYS14.PAGE.SIZE);
IF PW0 /= 0
@BOX 16.1
-8 => PW0;
@END
@TITLE SYSCMD05.4(2,11)

@COL 1S-2R-3R-4R-5R-6T-7R-8R-9F
@COL 10R

@ROW 7-10

@FLOW 1-2-3-4-5-6NO-7-8-9
@FLOW 6YES-10-8

@BOX 1.0
MONITOR (MESSAGE TYPE, MEDIUM, VOLUME NAME, UNIT NO.)
@BOX 2.0
COPY MESSAGE HEADER
@BOX 3.0
SET TIME
@BOX 4.0
SET USER NAME AND PROCESS
@BOX 5.0
COPY REST OF MESSAGE
@BOX 6.0
IS MESSAGE MOUNT REQUEST?
@BOX 7.0
SET UNIT NUMBER
@BOX 8.0
SEND MESSAGE
@BOX 9.0
END
@BOX 10.0
SET MEDIUM AND VOLUME NAME
@BOX 1.1
PROC MONITOR (MSG.TYPE, MEDIUM, VOL.NAME, UNIT.NO);
INTEGER I, SHIFT, CH, MSG.SIZE, TEMP;
LOGICAL32 TIME;
LOGICAL8 [80] MSG.BUF;
INTEGER [4] DEST;
DATAVEC HEADER (LOGICAL8)
41 0 0 0
"00:00:00" " USER " 0[8] " PROCESS " 0[8] ": "
END
DATAVEC MNT.REQUEST (LOGICAL8)
"MOUNT " 0[8] " " 0[8] "$L"
END
DATAVEC ASSIGNED (LOGICAL8)
"UNIT " 0[2] " ASSIGNED$L"
END
DATAVEC RELEASED (LOGICAL8)
"UNIT " 0[2] " RELEASED$L"
END
DATAVEC MSG.VEC (ADDR [LOGICAL8])
  MNT.REQUEST
  ASSIGNED
  RELEASED
END
ADDR [LOGICAL8] MSG;
@BOX 2.1
FOR I < 45 DO
HEADER [I] => MSG.BUF [I];
OD
@BOX 3.1
TIME.AND.DATE ();
PWW1 => TIME;
TIME ->> 7 / 675 * 675 <<- 7 -> TIME;
TIME / 3600 / 10 => TEMP  +> MSG.BUF [4];
TEMP * 36000 -> TIME / 3600  => TEMP +> MSG.BUF [5];
TEMP * 3600 -> TIME / 600 => TEMP +> MSG.BUF [7];
TEMP * 600 -> TIME / 60 => TEMP +> MSG.BUF [8];
TEMP * 60 -> TIME / 10 => TEMP +> MSG.BUF [10];
TEMP * 10 -> TIME +> MSG.BUF [11];
@BOX 4.1
NAMES ();
64 => SHIFT;
FOR I < 8 DO
   8 -> SHIFT;
   PWW1 ->> SHIFT => MSG.BUF [I + 18];
   PWW3 ->> SHIFT => MSG.BUF [I + 35];
OD
@BOX 5.1
SIZE (MSG.VEC [MSG.TYPE] => MSG) => MSG.SIZE;
FOR I < MSG.SIZE DO
   MSG^ [I] => MSG.BUF [I + 45];
OD
MSG.SIZE +> MSG.BUF [0];
@BOX 6.1
IF MSG.TYPE = 0
@BOX 7.1
UNIT.NO / 10 + "0" => MSG.BUF [50];
UNIT.NO + "0" => MSG.BUF [51];
@BOX 8.1
LOOK.UP.PROCESS ("OPR", 0);
PW1 => DEST [0];
PW2 => DEST [1];
8 => DEST [2];
0 => DEST [3];
SEND.MESSAGE (^MSG.BUF, ^DEST, 0, 0, 0, 0);
@BOX 9.1
END
@BOX 10.1
64 => SHIFT;
FOR I < 8 DO
   8 -> SHIFT;
   MEDIUM ->> SHIFT => MSG.BUF [I + 51];
   VOL.NAME ->> SHIFT => MSG.BUF [I + 60];
OD
@END
@TITLE SYSCMD05.5(2,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
MT SKIP (UNIT NO., DIRECTION, COUNT);
@BOX 2.0
EXECUTE SKIP OPERATION
@BOX 3.0
END
@BOX 1.1
PROC MT.SKIP (UNIT.NO, DIRN, COUNT);
@BOX 2.1
IF COUNT =< 0 THEN
   1 => COUNT;
FI
MT.OPERATION (UNIT.NO, SKIP, DIRN, 0, COUNT);
@BOX 3.1
END
@END
@TITLE SYSCMD05.6(2,11)

@COL 1S-2T-3R-4F
@COL 5R

@ROW 5-3

@FLOW 1-2OK-3-4
@FLOW 2FAIL-5-4

@BOX 1.0
MT READ (UNIT NO., BUFFER ADDRESS, DIRECTION)
@BOX 2.0
VALIDATE BUFFER ADDRESS
@BOX 3.0
EXECUTE READ OPERATION
@BOX 4.0
END
@BOX 5.0
RETURN FAULT STATUS -8
(VALIDATE FAIL)
@BOX 1.1
PROC MT.READ (UNIT.NO, BUFFER.ADDR, COUNT, DIRN);
@BOX 2.1
IF COUNT > MAX.MT.TRANSFER THEN
   MAX.MT.TRANSFER => COUNT;
FI
IF VALIDATE (BUFFER.ADDR, %4) /= 0 OR
   VALIDATE (BUFFER.ADDR + COUNT - 1, %4) /= 0
@BOX 3.1
MT.OPERATION (UNIT.NO, READ, DIRN, BUFFER.ADDR, COUNT);
@BOX 4.1
END
@BOX 5.1
-8 => PW0;
@END
@TITLE SYSCMD05.7(2,11)

@COL 1S-2T-3R-4F
@COL 5R

@ROW 5-3

@FLOW 1-2OK-3-4
@FLOW 2FAIL-5-4

@BOX 1.0
MT WRITE (UNIT NO., BUFFER ADDRESS, COUNT)
@BOX 2.0
VALIDATE DATA TO BE WRITTEN
@BOX 3.0
EXECUTE WRITE OPERATION
@BOX 4.0
END
@BOX 5.0
RETURN FAULT STATUS -8
(VALIDATE FAIL)
@BOX 1.1
PROC MT.WRITE (UNIT.NO, BUFFER.ADDR, COUNT);
@BOX 2.1
IF VALIDATE (BUFFER.ADDR, %C) /= 0 OR
   VALIDATE (BUFFER.ADDR + COUNT - 1, %C) /= 0
@BOX 3.1
MT.OPERATION (UNIT.NO, WRITE, 0, BUFFER.ADDR, COUNT);
@BOX 4.1
END
@BOX 5.1
-8 => PW0;
@END
@TITLE SYSCMD05.8(2,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
MT SKIP TM (UNIT NO., DIRECTION, COUNT)
@BOX 2.0
EXECUTE SKIP TO TAPE MARK OPERATION
@BOX 3.0
END
@BOX 1.1
PROC MT.SKIP.TM (UNIT.NO, DIRN, COUNT);
@BOX 2.1
IF COUNT =< 0 THEN
   1 => COUNT;
FI
MT.OPERATION (UNIT.NO, SKIP.TM, DIRN, 0, COUNT);
@BOX 3.1
END
@END
@TITLE SYSCMD05.9(2,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
MT WRITE TM (UNIT NO.)
@BOX 2.0
EXECUTE WRITE TAPE MARK OPERATION
@BOX 3.0
END
@BOX 1.1
PROC MT.WRITE.TM (UNIT.NO);
@BOX 2.1
MT.OPERATION (UNIT.NO, WRITE.TM, 0, 0, 0);
@BOX 3.1
END
@END
@TITLE SYSCMD05.10(2,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
MT REWIND (UNIT NO.)
@BOX 2.0
EXECUTE REWIND OPERATION
@BOX 3.0
END
@BOX 1.1
PROC MT.REWIND (UNIT.NO);
@BOX 2.1
MT.OPERATION (UNIT.NO, REWIND, 0, 0, 0);
@BOX 3.1
END
@END
@TITLE SYSCMD05.11(2,11)

@COL 1S-2T-3T-4T-5T-7T-8T-9R-15N-10F
@COL 17N-13R-11R-16R-12R-14N

@ROW 2-17
@ROW 11-4
@ROW 14-15
@ROW 16-7
@ROW 12-9

@FLOW 1-2NO-3NO-4NO-5OK-7FAILED-8NO-9-15-10
@FLOW 2YES-17-13-14
@FLOW 3YES-11-14-15
@FLOW 4YES-7
@FLOW 5FAIL-16-14
@FLOW 7OK-15
@FLOW 8YES-12-14

@BOX 1.0
MT OPERATION (UNIT NO., OPERATION, DIRECTION, BUFFER ADDRESS, TRANSFER COUNT)
@BOX 2.0
IS UNIT NUMBER INVALID?
@BOX 3.0
UNIT AVAILABLE TO THIS PROCESS?
@BOX 4.0
NON-TRANSFER OPERATION?
@BOX 5.0
SET TRANSFER INFORMATION
FOR BUFFER
@BOX 7.0
EXECUTE OPERATION
@BOX 8.0
EOT OR TAPE MARK ENCOUNTERED?
@BOX 9.0
RETURN FAULT STATUS -75
(MT OPERATION FAILED)
@BOX 10.0
END
@BOX 11.0
RETURN FAULT STATUS -76
(UNIT NOT ASSIGNED TO PROCESS)
@BOX 12.0
RETURN FAULT STATUS -74
(EOT/TM ENCOUNTERED)
@BOX 13.0
RETURN FAULT STATUS -73
(ILLEGAL UNIT NUMBER)
@BOX 16.0
RETURN FAULT STATUS -72
(MT BUFFER NON-EXISTENT OR TOO SMALL)
@BOX 1.1
PROC MT.OPERATION (UNIT.NO, OP, DIRN, BUFFER.ADDR, TRANS.COUNT);
ADDR TEMP;
@BOX 2.1
IF UNIT.NO < 0 OR UNIT.NO >= NO.OF.MT.UNITS
@BOX 3.1
SELECT ESM.VARS [UNIT.NO];
IF SYS13.CURRENT.SPN /= SPN /= 0
@BOX 4.1
IF OP & 7 /= READ /= WRITE
@BOX 5.1
MAP (-1, BUFFER.ADDR ->> SYS14.SEG.SHIFT => TEMP, 0);
PW1 => SEG;
TEMP <<- SYS14.SEG.SHIFT -: BUFFER.ADDR => DISP
   ->> SYS14.PAGE.SHIFT => BLOCK <<- SYS14.PAGE.SHIFT
   => TEMP -> DISP;
IF TEMP + DISP + TRANS.COUNT > SYS14.SEG.SIZE
@BOX 7.1
TRANS.COUNT => COUNT;
SYS13.ENTER.INT.LEVEL (^MT.INT.OP, UNIT.NO, DIRN <<- 3 ! OP);
TRANS.COUNT - COUNT => PW1;
IF STATUS & OP.FAIL.STATUS = 0
@BOX 8.1
IF STATUS & EOT.TM.STATUS /= 0
@BOX 9.1
-75 => PW0;
@BOX 10.1
END
@BOX 11.1
-76 => PW0;
@BOX 12.1
-74 => PW0;
@BOX 13.1
-73 => PW0;
@BOX 16.1
-72 => PW0;
@END
@TITLE SYSCMD05.12(2,11)

@COL 1S-2T-3T-4T-5R-6R-7F
@COL 9R-8R-10N

@ROW 8-5
@ROW 9-4

@FLOW 1-2OK-3OK-4NO-5-6-7
@FLOW 2FAIL-7
@FLOW 4YES-8-10
@FLOW 3FAIL-9-10-7

@BOX 1.0
RELABEL (UNIT NO., NEW NAME, NEW LABEL)
@BOX 2.0
CHECK PROCESS PRIVILEGED
[SYS13]
@BOX 3.0
VALIDATE LABEL
@BOX 4.0
IS UNIT NUMBER INVALID?
@BOX 5.0
SET NEW NAME AND LABEL
@BOX 6.0
INDICATE HEADER READ
@BOX 7.0
END
@BOX 8.0
SET FAULT STATUS -73
(ILLEGAL UNIT NUMBER)
@BOX 9.0
RETURN FAULT STATUS -8
(VALIDATE FAIL)
@BOX 1.1
PROC RELABEL (UNIT.NO, NEW.NAME, NEW.LABEL);
INTEGER NEW.LABEL.SIZE, I;
@BOX 2.1
SYS13.CHECK.PRIV ();
IF PW0 /= 0
@BOX 3.1
IF SIZE (NEW.LABEL) => NEW.LABEL.SIZE > 0 AND
   [VALIDATE (BYTE (^NEW.LABEL^ [0]), %C) /= 0 OR
      VALIDATE (BYTE (^NEW.LABEL^ [NEW.LABEL.SIZE - 1]), %C) /= 0]
@BOX 4.1
IF UNIT.NO < 0 OR UNIT.NO > NO.OF.UNITS
@BOX 5.1
SELECT ESM.VARS [UNIT.NO];
NEW.NAME => NAME;
FOR I < LABEL.SIZE DO
   IF I < NEW.LABEL.SIZE THEN
      NEW.LABEL^ [I] => VOL.LABEL [I];
   ELSE
      " " => VOL.LABEL [I];
   FI
OD
@BOX 6.1
RELABELED !> STATUS;
@BOX 7.1
END
@BOX 8.1
-73 => PW0;
@BOX 9.1
-8 =>PW0;
@END
@TITLE SYSCMD05.13(2,11)

@COL 1S-2T-3T-4R-5F

@FLOW 1-2PRIVILEGED-3OK-4-5
@FLOW 2UNPRIVILEGED-5
@FLOW 3FAIL-5

@BOX 1.0
CANT DO (PROCESS NAME)
@BOX 2.0
CHECK CALLING PROCESS IS
PRIVILEGED
[SYS13]
@BOX 3.0
LOOK UP PROCESS
[SYS13]
@BOX 4.0
INDICATE MOUNT REQUEST TO BE
ABANDONED
@BOX 5.0
END
@BOX 1.1
PROC CANT.DO (PROC.NAME);
@BOX 2.1
SYS13.CHECK.PRIV ();
IF PW0 /= 0
@BOX 3.1
LOOK.UP.PROCESS (PROC.NAME, 0);
IF PW0 /= 0
@BOX 4.1
1 => ABANDON.MNT [PW1 ->> 9];
@BOX 5.1
END
@END
@TITLE SYSCMD05.14(2,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
TINI ESM (PROC SPN)
@BOX 2.0
RELEASE ALL UNITS ASSIGNED
TO THE PROCESS
@BOX 3.0
END
@BOX 1.1
PROC TINI.ESM (PROC.SPN);
INTEGER UNIT.NO;
@BOX 2.1
FOR UNIT.NO < NO.OF.UNITS DO
   IF SPN OF ESM.VARS [UNIT.NO] = PROC.SPN THEN
      0 => SPN OF ESM.VARS [UNIT.NO];
      ::MONITOR (RELEASED, 0, 0, UNIT.NO);
   FI
OD
@BOX 3.1
END
@END
@TITLE SYSCMD05.15(2,11)

@COL 9R
@COL 1S-2T-3T-4T-5T-14T-6T-7R-8F
@COL 13R-10R-11R-12N

@ROW 10-4
@ROW 9-6
@ROW 11-5
@ROW 13-3

@FLOW 1-2OK-3NO-4AVAILABLE-5NO-14NO-6FAIL-7-8
@FLOW 3YES-10-12-8
@FLOW 4UNAVAILABLE-11-12
@FLOW 5YES-9-8
@FLOW 6OK-8
@FLOW 2FAIL-13-12
@FLOW 14YES-8
@BOX 1.0
ED READ (UNIT NO., BUFFER ADDRESS, DISC ADDRESS, COUNT)
@BOX 2.0
VALIDATE BUFFER
@BOX 3.0
INVALID UNIT NUMBER?
@BOX 4.0
CHECK UNIT AVAILABLE TO PROCESS
@BOX 5.0
INVALID DISC ADDRESS?
@BOX 6.0
EXECUTE TRANSFER
@BOX 7.0
RETURN FAULT STATUS -75
(TRANSFER FAILED)
@BOX 8.0
END
@BOX 9.0
RETURN FAULT STATUS -79
(INVALID DISC ADDRESS)
@BOX 10.0
RETURN FAULT STATUS -73
(INVALID UNIT NUMBER)
@BOX 11.0
RETURN FAULT STATUS -76
(UNIT NOT ASSIGNED TO PROCESS)
@BOX 13.0
RETURN FAULT STATUS -8
(VALIDATE FAIL)
@BOX 14.0
ZERO TRANSFER?
@BOX 1.1
PROC ED.READ (UNIT.NO, BUFFER.ADDR, DISC.ADDR, BYTE.COUNT);
INTEGER I, BLK.COUNT;
0 => PW0;
@BOX 2.1
BYTE.COUNT / SYS14.PAGE.SIZE => BLK.COUNT;
-1 => I;
WHILE 1 +> I < BLK.COUNT AND
   VALIDATE (I * SYS14.PAGE.SIZE + BUFFER.ADDR, %A) = 0 DO OD
IF I /= BLK.COUNT
@BOX 3.1
IF UNIT.NO < FIRST.ED.UNIT OR
   UNIT.NO >= FIRST.ED.UNIT + NO.OF.ED.UNITS
@BOX 4.1
SELECT ESM.VARS [UNIT.NO];
IF SYS13.CURRENT.SPN /= SPN
@BOX 5.1
SECTOR.SIZE /> DISC.ADDR;
IF DISC.ADDR < 0 OR DISC.ADDR >= DISC.SIZE
@BOX 6.1
BUFFER.ADDR ->> SYS14.SEG.SHIFT => SEG
   <<- SYS14.SEG.SHIFT -: BUFFER.ADDR
   ->> SYS14.PAGE.SHIFT => BLOCK;
DISC.ADDR => DISC.BLOCK;
BYTE.COUNT + SECTOR.SIZE - 1  / SECTOR.SIZE => COUNT;
SYS13.ENTER.INT.LEVEL (^ED.TRANSFER, UNIT.NO, 0);
IF STATUS & OP.FAIL.STATUS = 0
@BOX 7.1
-75 => PW0;
@BOX 8.1
END
@BOX 9.1
-79 => PW0;
@BOX 10.1
-73 => PW0;
@BOX 11.1
-76 => PW0;
@BOX 13.1
-8 => PW0;
@BOX 14.1
IF BYTE.COUNT =< 0
@END


@TITLE SYSCMD05.16(2,11)

@COL 9R
@COL 1S-2T-3T-4T-5T-14T-6T-7R-8F
@COL 13R-10R-11R-12N

@ROW 10-4
@ROW 9-6
@ROW 11-5
@ROW 13-3

@FLOW 1-2OK-3NO-4AVAILABLE-5NO-14NO-6FAIL-7-8
@FLOW 3YES-10-12-8
@FLOW 4UNAVAILABLE-11-12
@FLOW 5YES-9-8
@FLOW 6OK-8
@FLOW 2FAIL-13-12
@FLOW 14YES-8
@BOX 1.0
ED WRITE (UNIT NO., BUFFER ADDRESS, DISC ADDRESS, COUNT)
@BOX 2.0
VALIDATE BUFFER
@BOX 3.0
INVALID UNIT NUMBER?
@BOX 4.0
CHECK UNIT AVAILABLE TO PROCESS
@BOX 5.0
INVALID DISC ADDRESS?
@BOX 6.0
EXECUTE TRANSFER
@BOX 7.0
RETURN FAULT STATUS -75
(TRANSFER FAILED)
@BOX 8.0
END
@BOX 9.0
RETURN FAULT STATUS -79
(INVALID DISC ADDRESS)
@BOX 10.0
RETURN FAULT STATUS -73
(INVALID UNIT NUMBER)
@BOX 11.0
RETURN FAULT STATUS -76
(UNIT NOT ASSIGNED TO PROCESS)
@BOX 13.0
RETURN FAULT STATUS -8
(VALIDATE FAIL)
@BOX 14.0
ZERO TRANSFER?
@BOX 1.1
PROC ED.WRITE (UNIT.NO, BUFFER.ADDR, DISC.ADDR, BYTE.COUNT);
INTEGER I, BLK.COUNT;
0 => PW0;
@BOX 2.1
BYTE.COUNT / SYS14.PAGE.SIZE => BLK.COUNT;
-1 => I;
WHILE 1 +> I < BLK.COUNT AND
   VALIDATE (I * SYS14.PAGE.SIZE + BUFFER.ADDR, %C) = 0 DO OD
IF I /= BLK.COUNT
@BOX 3.1
IF UNIT.NO < FIRST.ED.UNIT OR
   UNIT.NO >= FIRST.ED.UNIT + NO.OF.ED.UNITS
@BOX 4.1
SELECT ESM.VARS [UNIT.NO];
IF SYS13.CURRENT.SPN /= SPN
@BOX 5.1
SECTOR.SIZE /> DISC.ADDR;
IF DISC.ADDR < 0 OR DISC.ADDR >= DISC.SIZE
@BOX 6.1
BUFFER.ADDR ->> SYS14.SEG.SHIFT => SEG
   <<- SYS14.SEG.SHIFT -: BUFFER.ADDR
   ->> SYS14.PAGE.SHIFT => BLOCK;
DISC.ADDR => DISC.BLOCK;
BYTE.COUNT + SECTOR.SIZE - 1  / SECTOR.SIZE => COUNT;
SYS13.ENTER.INT.LEVEL (^ED.TRANSFER, UNIT.NO, 1);
IF STATUS & OP.FAIL.STATUS = 0
@BOX 7.1
-75 => PW0;
@BOX 8.1
END
@BOX 9.1
-79 => PW0;
@BOX 10.1
-73 => PW0;
@BOX 11.1
-76 => PW0;
@BOX 13.1
-8 => PW0;
@BOX 14.1
IF BYTE.COUNT =< 0
@END



