@X @~
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H            SYS073
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL~
~
~
                                                            ISSUE 11~
~V9 -1
~P
~V9 1
~YSYS073
~M~OSYS IMPLEMENTATION DESCRIPTION
~
~M~OSection 7 Version 3
~S1~OSection 7.3 Character input/output
~S1~O1. General Introduction
~BSee SYS072.~
~S1~O2.1 Hardware Interface
~BSee SYS072.~
~S1~O2.2 Software Interface
~S1See SYS072.~
~S1~O3. Implementation
~S1~O3.1 Outline of Operation
~BThe procedures used by SYS072 from this submodule are:
~S11) CHAR.INPUT.TR.COMP (DEVICE NO) STATUS~
~BThe function of this procedure is obvious from the flowchart.~
~S12) CHAR.OUTPUT.TR.COMP (DEVICE NO) STATUS~
~BThe function of this procedure is obvious from the flowchart.~
~S13) CHAR.INPUT.TASK (DEVICE NO) STATUS~
~BThe function of this procedure is obvious from the flowchart.~
~S14) CHAR.INPUT.TR.TASK (DEVICE NO) STATUS~
~BThe function of this procedure is obvious from the flowchart.~
~S1~O3.2 Data Structures
~BSee SYS072.~
~S1~O3.3 Special Notes
~BNone.
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H                SYS073
~V9 -1
~F
@TITLE SYS07(3,10)

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

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

@BOX 1.0
CHARACTER INPUT/OUTPUT MANAGEMENT
@BOX 4.0
PROCEDURES IN SUB-MODULE
   INT1 CHARACTER INPUT TRANSFER COMPLETE
   INT2 CHARACTER OUTINPUT TRANSFER COMPLETE
   TSK1 CHARACTER INPUT TASK
   TSK2 CHARACTER OUTPUT TASK
@BOX 6.0
END OF SECTION
@BOX 1.1
::CHARACTER INPUT/OUTPUT MANAGEMENT
@BOX 4.1
::PROCEDURES IN SUB-MODULE
::*INIT %6000;
*CODE 2;
::PSPEC CHAR.INPUT.TR.COMP (INTEGER) / INTEGER;
::PSPEC CHAR.OUTPUT.TR.COMP (INTEGER) / INTEGER;
   #SYSINT07.1
   #SYSINT07.2
::*INIT %7000;
*CODE 4;
::PSPEC CHAR.INPUT.TASK (INTEGER) / INTEGER;
::PSPEC CHAR.OUTPUT.TASK (INTEGER) / INTEGER;
   #SYSTSK07.1
   #SYSTSK07.2
@BOX 5.1
@BOX 6.1
**IN -1
::END OF SECTION
@END
@TITLE SYSINT07.1(3,11)
@COL 1S-2T-3T-4T-5T-6R-7R-8R-9T-10R-14R-12F
@COL 13R
@ROW 6-13
@FLOW 1-2NO-3NO-4NO-5NO-6-7-8-9NO-10-14-12
@FLOW 2YES-13-12
@FLOW 3YES-13
@FLOW 4YES-8
@FLOW 5YES-13
@FLOW 9YES-4
@BOX 1.0
CHARACTER INPUT TRANSFER COMPLETE (DEVICE NO)
@BOX 2.0
WAS THE INPUT TRANSFER NULL?
@BOX 3.0
DOES LINE START WITH ***?
@BOX 4.0
IS THERE SPACE FOR ANOTHER
CHARACTER IN CURRENT BUFFER BLOCK?
@BOX 5.0
AT END OF BUFFER SEGMENT?
@BOX 6.0
RELEASE CURRENT BUFFER BLOCK
[SYS14]
@BOX 7.0
FETCH NEXT BUFFER BLOCK TO CORE
[SYS14]
@BOX 8.0
COPY ONE CHARACTER TO BUFFER BLOCK
@BOX 9.0
ANY CHARACTERS LEFT?
@BOX 10.0
REMEMBER WHETHER END OF LINE WAS READ
@BOX 12.0
END
@BOX 13.0
SET TASK REQUEST FOR THIS DEVICE
@BOX 14.0
RESET ADDRESS AND COUNT
TO READ INTO BUFFER
@BOX 1.1
PROC CHAR.INPUT.TR.COMP (DEV.NO);
INTEGER CNT, DISP;
ADDR [LOGICAL8] HDR;
SELECT IO.VARS [DEV.NO];
SYS14.MAP.ADDRESS (BLOCK.RA, SYS14.IO.BUF.SEG) => SEG.PTR;
SYS14.MAP.ADDRESS (BUF.RA, SYS14.IO.BUF.SEG.2) => HDR;
0 => CHAR.INPUT.TR.COMP;
@BOX 2.1
IF BUF.SIZE - 4 - COUNT => CNT = 0
@BOX 3.1
3 => DISP;
IF IO.STATUS & NEWLINE /= 0 AND
   CNT >= 4 AND
   HDR^ [4] = "*" AND
   HDR^ [5] = "*" AND
   HDR^ [6] = "*"
@BOX 4.1
IF 1 +> PTR /= SYS14.PAGE.SIZE
@BOX 5.1
IF 1 +> BLOCK.NO = MAX.TR
@BOX 6.1
SYS14.UPDATE.BLOCK (BLOCK.RA);
SYS14.REL.BLOCK (BLOCK.RA);
@BOX 7.1
SYS14.GET.BLOCK (SEG, BLOCK.NO) => BLOCK.RA;
SYS14.MAP.ADDRESS (BUF.RA, SYS14.IO.BUF.SEG.2) => HDR;
SYS14.MAP.ADDRESS (BLOCK.RA, SYS14.IO.BUF.SEG) => SEG.PTR;
0 => PTR;
@BOX 8.1
HDR^ [1 +> DISP] => SEG.PTR^ [PTR];
@BOX 9.1
IF 1 -> CNT > 0
@BOX 10.1
IF HDR^ [DISP] = "$L" OR
   HDR^ [DISP] = "$P" THEN
   NEWLINE !> IO.STATUS;
ELSE
   NEWLINE & IO.STATUS -=> IO.STATUS;
FI
@BOX 12.1
END
@BOX 13.1
1 => CHAR.INPUT.TR.COMP;
@BOX 14.1
BUF.RA + 4 => ADDRESS;
BUF.SIZE - 4 => COUNT;
@END
@TITLE SYSINT07.2(3,10)
@COL 1S-3T-4T-5R-6R-7R-9R-10F
@COL 11R
@ROW 5-11
@FLOW 1-3NO-4NO-5-6-7-9-10
@FLOW 3YES-9
@FLOW 4YES-11-10
@BOX 1.0
CHARACTER OUTPUT TRANSFER COMPLETE (DEVICE NO)
@BOX 3.0
ARE THERE MORE CHARACTERS
IN CURRENT BUFFER BLOCK?
@BOX 4.0
WAS THIS THE LAST
BLOCK OF DOCUMENT?
@BOX 5.0
RELEASE CURRENT BUFFER BLOCK
[SYS14]
@BOX 6.0
FETCH NEXT BUFFER BLOCK TO CORE
[SYS14]
@BOX 7.0
SET UP CHARACTER COUNT
AND ADDRESS FOR THIS BLOCK
@BOX 9.0
SET UP COMMAND AND CHARACTER COUNT
FOR NEXT OUTPUT TRANSFER
@BOX 10.0
END
@BOX 11.0
SET TASK REQUEST FOR THIS DEVICE
@BOX 1.1
PROC CHAR.OUTPUT.TR.COMP (DEV.NO);
SELECT IO.VARS [DEV.NO];
0 => CHAR.OUTPUT.TR.COMP;
@BOX 3.1
IF COUNT +> BLOCK.COUNT > 0
@BOX 4.1
IF DOC.SIZE =< 0
@BOX 5.1
SYS14.REL.BLOCK (BLOCK.RA);
@BOX 6.1
SYS14.GET.BLOCK (SEG, 1 +> BLOCK.NO) => BLOCK.RA => ADDRESS;
@BOX 7.1
IF SYS14.PAGE.SIZE => BLOCK.COUNT > DOC.SIZE THEN
   DOC.SIZE => BLOCK.COUNT;
FI
BLOCK.COUNT -> DOC.SIZE;
@BOX 9.1
IF MAX.TR => COUNT > BLOCK.COUNT THEN
   BLOCK.COUNT => COUNT;
FI
IF DOC.SIZE + BLOCK.COUNT = COUNT THEN
   EOM.CMD => CONTROL;
FI
COUNT -> BLOCK.COUNT;
@BOX 10.1
END
@BOX 11.1
1 => CHAR.OUTPUT.TR.COMP;
@END
@TITLE SYSTSK07.1(3,11)
@COL 1S-2T-3T-4R-5T-6T-7T-8T-9N-10R-21R-25T-11T-12R-27T-28T-13R-14R-15F
@COL 22N-23R-16T-17R-18N-19R-20R-24N
@ROW 2-22
@ROW 9-16
@ROW 11-18
@FLOW 1-2NO-3BREAKIN-4-13
@FLOW 2YES-22-23-24-15
@FLOW 3OTHER-5TR COMP-6NO-7OK-8NO-9-10-21-25FAULTY-11INTERACTIVE-12-27NO-28NO-13
-14-15
@FLOW 7CLASS CHANGE-15
@FLOW 5OTHER-28
@FLOW 6YES-16NO-17-21
@FLOW 16YES-9
@FLOW 8YES-28
@FLOW 25OK-28
@FLOW 11BATCH-18-19-20-14
@FLOW 27YES-20-14
@FLOW 28YES-15
@BOX 1.0
CHARACTER INPUT TASK (DEVICE NO)
@BOX 2.0
IS THE DEVICE DISENGAGED?
@BOX 3.0
BREAKIN INTERRUPT?
@BOX 4.0
RESET DEVICE MODE AND
FORCE INTERRUPT FOR
LOGGED IN PROCESS
@BOX 5.0
TRANSFER COMPLETE INTERRUPT?
@BOX 6.0
READING BUFFERED INPUT?
@BOX 7.0
CHECK FOR COMMAND LINE?
[SYSTSK07.2]
@BOX 8.0
START OF BUFFERED
DOCUMENT (***A)?
@BOX 10.0
SEND THE MESSAGE
[SYSTSK07.3]
@BOX 11.0
BATCH OR INTERACTIVE DEVICE?
@BOX 12.0
REQUEST USER TO LOG-IN
[SYSTSK07.4]
@BOX 13.0
SET COMMAND TO
READ NEXT LINE
@BOX 14.0
SET SOFTWARE INTERRUPT
@BOX 15.0
END
@BOX 16.0
CORRECTLY TERMINATED WITH ***Z?
@BOX 17.0
NOTE UNTERMINATED
DOCUMENT
@BOX 19.0
MONITOR THE ERROR
[SYSTSK07.4]
@BOX 20.0
SET COMMAND TO
DISENGAGE DEVICE
@BOX 21.0
DISCARD DOCUMENT
@BOX 23.0
CLEAR 'TRANSFER COMPLETE'
@BOX 25.0
WAS MESSAGE ACCEPTED?
@BOX 27.0
USER LOGGED OUT?
@BOX 28.0
DIRECT I/O?
@BOX 1.1
PROC CHAR.INPUT.TASK (DEV.NO);
INTEGER ERROR;
SELECT IO.VARS [DEV.NO];
0 => CHAR.INPUT.TASK;
@BOX 2.1
IF INT.STATUS & DISENGAGED /= 0
@BOX 3.1
IF INT.STATUS & BREAKIN = 0
@BOX 4.1
CHANGE.P.MODE (DEV.NO, OLD.P.DEV.MODE);
IF PAIR.NO > 0 THEN
   CHANGE.P.MODE (PAIR.NO, OLD.P.DEV.MODE OF
      IO.VARS [PAIR.NO]);
FI
::NOTE-INTERRUPT DOES NOT WORK ACROSS MACHINES
IF IO.STATUS & LOGGED.IN /= 0 THEN
   FORCE.INT (DEST [0], DEST [1], 0);
FI
@BOX 5.1
IF INT.STATUS & TR.COMP = 0
@BOX 6.1
IF IO.STATUS & BUFFERED /= 0
@BOX 7.1
76 - COUNT => HEADER^ [0];
0 => HEADER^ [1] => HEADER^ [2]
   => HEADER^ [3];
IF COMMAND.LINE (DEV.NO, HEADER)
   => CHAR.INPUT.TASK < 0
@BOX 8.1
IF IO.STATUS & BUFFERED /= 0
@BOX 10.1
SEND.MESS (DEV.NO) => ERROR;
@BOX 11.1
IF IO.STATUS & INTERACTIVE = 0
@BOX 12.1
MONITOR (DEV.NO, 0);
@BOX 13.1
START.TR.CMD => CONTROL;
BUF.RA + 4 => ADDRESS;
IF IO.STATUS & BUFFERED /= 0 THEN
   BUF.SIZE - 4 => COUNT;
ELSE
   76 => COUNT;
FI
@BOX 14.1
1 => CHAR.INPUT.TASK;
@BOX 15.1
END
@BOX 16.1
IF HEADER^ [4] = "*" AND
   HEADER^ [5] = "*" AND
   HEADER^ [6] = "*" AND
   HEADER^ [7] = "Z"
@BOX 17.1
2 => ERROR;
@BOX 19.1
MONITOR (DEV.NO, ERROR);
@BOX 20.1
DISENGAGE.CMD => CONTROL;
@BOX 21.1
IF IO.STATUS & LONG.MESS /= 0 OR ERROR /= 0 THEN
   LONG.MESS ! BUFFERED ! LOGGED.IN & IO.STATUS -=> IO.STATUS;
   IF PAIR.NO > 0 AND
      IO.STATUS OF IO.VARS [PAIR.NO] & DEDICATED /= 0 THEN
      SYS15.SET.PERI.CH.STATUS (CH.NO, 1, 0, 0);
   FI
   IF ERROR /= 0 AND SEG /= 0 THEN
      RELEASE.SEGMENT (SEG);
   FI
   0 => SEG;
FI
@BOX 23.1
TR.COMP & INT.STATUS -=> INT.STATUS;
@BOX 25.1
IF ERROR = 0
@BOX 27.1
IF INT.STATUS & TR.COMP /= 0
   AND IO.STATUS & LOGGED.IN = 0
@BOX 28.1
IF IO.STATUS & DIRECT.IO /= 0
@END

@TITLE SYSTSK07.2(3,10)
@COL 1S-2T-3T-4T-5T-6R-8R-9F
@COL 10N-11T-12R-13R
@ROW 5-10
@FLOW 1-2NO-3NO-4NO-5NO-6-8-9
@FLOW 2YES-9
@FLOW 3YES-8
@FLOW 4YES-6
@FLOW 5YES-10-11NO-12-13-9
@FLOW 11YES-13
@BOX 1.0
CHAR OUTPUT TASK (DEVICE NO)
@BOX 2.0
IS THE DEVICE DISENGAGED?
@BOX 3.0
IS IT WAITING FOR A
DOCUMENT TO OUTPUT?
@BOX 4.0
IS THE CURRENT DOCUMENT
TO BE ABANDONED?
@BOX 5.0
IS THERE MORE OF THE CURRENT
DOCUMENT STILL TO BE OUTPUT?
@BOX 6.0
DISCARD THE CURRENT DOCUMENT
NOTE DEVICE WAITING FOR DOC.
@BOX 8.0
SET UP TO OUTPUT THE
NEXT DOCUMENT, IF ANY
#SYSTSK07.2.1
@BOX 9.0
END
@BOX 11.0
HEADER NOT YET COMPLETED OR
ALREADY OUTPUTTING SEGMENT?
@BOX 12.0
SWITCH TO OUTPUTTING SEGMENT
#SYSTSK07.2.2
@BOX 13.0
SET SOFTWARE INTERRUPT
@BOX 1.1
PROC CHAR.OUTPUT.TASK (DEV.NO);
ADDR [LOGICAL8] SEG.BYTE;
INTEGER BYTE.NO;
INTEGER32 SPN.PID, SEG.START, SEG.COUNT;
SELECT IO.VARS [DEV.NO];
0 => CHAR.OUTPUT.TASK;
@BOX 2.1
IF INT.STATUS & DISENGAGED /= 0
@BOX 3.1
IF IO.STATUS & WAITING /= 0
@BOX 4.1
IF INT.STATUS & ABANDON /= 0
@BOX 5.1
IF DOC.SIZE + BLOCK.COUNT + COUNT > 0
@BOX 6.1
IF IO.STATUS & LONG.MESS /= 0 THEN
   RELEASE.SEGMENT (SEG);
   LONG.MESS ! BUFFERED & IO.STATUS -=> IO.STATUS;
FI
WAITING !> IO.STATUS;
IF DEST[2] & %18 /= 0 THEN
   CH.NO <<- 9 ! %100 ! V.MC.NO => SPN.PID;
   SYS15.SET.ID (SPN.PID, SPN.PID, 0);
   SEND.MESSAGE (^NUL.MESS, ^DEST, 0, 0, 0, 0);
FI
@BOX 8.1
:: READ NEXT DOCUMENT
#SYSTSK07.2.1
@BOX 9.1
END
@BOX 11.1
IF IO.STATUS & LONG.MESS = 0 OR
   IO.STATUS & BUFFERED /= 0 OR
   COUNT > 0
@BOX 12.1
:: OUTPUT SEGMENT
#SYSTSK07.2.2
@BOX 13.1
1 => CHAR.OUTPUT.TASK;
@END
@TITLE SYSTSK07.2.1(3,11)
@COL 1S-2T-3R-4R-5R-6R-7R-8F
@FLOW 1-2OK-3-4-5-6-7-8
@FLOW 2NONE-8
@BOX 1.0
READ NEXT DOCUMENT
@BOX 2.0
READ MESSAGE FROM
PERIPHERAL CHANNEL
@BOX 3.0
NOTE THAT THE DEVICE IS
NOT WAITING FOR A DOCUMENT
@BOX 4.0
CHECK FOR *** COMMAND
[SYSTSK07.2]
@BOX 5.0
COMPUTE SIZE OF DOCUMENT
@BOX 6.0
SET UP POINTERS
TO OUTPUT HEADER
@BOX 7.0
SET SOFTWARE INTERRUPT
@BOX 8.0
END
@BOX 1.1
READ.NEXT.DOCUMENT: BEGIN
LOGICAL ACCESS;
INTEGER HEADER0;
:: IO.VARS [DEV.NO] SELECTED
@BOX 2.1
SYS15.READ.PERI.MESSAGE (HEADER, ^DEST, CH.NO, -1);
PW1 => SEG;
PW3 => ACCESS;
IF PW0 /= 0
@BOX 3.1
PW4 => UID;
WAITING -=> IO.STATUS;
@BOX 4.1
HEADER^ [0] => HEADER0;
COMMAND.LINE (DEV.NO, PART (HEADER, HEADER0, HEADER0 + HEADER^ [1]));
@BOX 5.1
IF SEG /= 0 AND ACCESS & %C = %C THEN
   MAKE (LOGICAL8, 12, MAP.SEG (SEG)) => SEG.BYTE;
   4 => SEG.START;
   FOR BYTE.NO < 4 DO
      SEG.COUNT <<- 8 ! SEG.BYTE^ [3 - BYTE.NO] =>  SEG.COUNT;
   OD
   IF SEG.COUNT >= 0 AND
      SEG.START + SEG.COUNT - 1 ->> SYS14.PAGE.SHIFT < PW1 THEN
      SEG.COUNT => DOC.SIZE;
   ELSE
      0 => DOC.SIZE;
   FI
   SOM.CMD => CONTROL;
   LONG.MESS !> IO.STATUS;
ELSE
   0 => DOC.SIZE;
   SOM.EOM.CMD => CONTROL;
FI
@BOX 6.1
0 => BLOCK.COUNT;
IF HEADER^ [HEADER0] => COUNT =< HEADER^ [1] THEN
   BUF.RA + HEADER0 + 4 => ADDRESS;
ELSE
   BUF.RA => ADDRESS;
   0 => COUNT;
FI
@BOX 7.1
1 => CHAR.OUTPUT.TASK;
@BOX 8.1
END
@END
@TITLE SYSTSK07.2.2(3,11)
@COL 1S-2R-3R-4R-5R-6F
@FLOW 1-2-3-4-5-6
@BOX 1.0
OUTPUT SEGMENT
@BOX 2.0
SET DEVICE STATUS TO "BUFFERED"
@BOX 3.0
COMPUTE STARTING ADDRESS
AND SIZE OF FIRST BLOCK
@BOX 4.0
COMPUTE COUNT FOR FIRST TRANSFER
@BOX 5.0
SELECT APPROPRIATE TRANSFER COMMAND
@BOX 6.0
END
@BOX 1.1
OUTPUT.SEGMENT: BEGIN
:: IO.VARS [DEV.NO] SELECTED
@BOX 2.1
BUFFERED !> IO.STATUS;
@BOX 3.1
MAKE (LOGICAL8, 12, MAP.SEG (SEG)) => SEG.BYTE;
4 => SEG.START;
SEG.START ->> SYS14.PAGE.SHIFT => BLOCK.NO
   <<- SYS14.PAGE.SHIFT -: SEG.START => ADDRESS
   -: SYS14.PAGE.SIZE => COUNT;
IF COUNT > DOC.SIZE THEN
   DOC.SIZE => COUNT;
FI
@BOX 4.1
IF COUNT > MAX.TR THEN
   COUNT - MAX.TR => BLOCK.COUNT;
   MAX.TR => COUNT;
ELSE
   0 => BLOCK.COUNT;
FI
@BOX 5.1
BLOCK.COUNT + COUNT -> DOC.SIZE;
IF DOC.SIZE + BLOCK.COUNT = 0 THEN
   EOM.CMD => CONTROL;
ELSE
   START.TR.CMD => CONTROL;
FI
@BOX 6.1
END
@END

