@X @~
~V7 56 2 -5
~D10
~H                    MUSS
~
~
~D10
~H             SYS513
~D10
~MMANCHESTER UNIVERSITY  -  CONFIDENTIAL
~
~
                                                             ISSUE 11~
~V9 -1
~P
~V9 1
~YSYS513
~S~M~OSYS IMPLEMENTATION DESCRIPTION
~S~M~OSection 51 Version 3
~S~OSection 51.3 Disc Formatting and Copying
~S~O1. Gneral Description
~BThis module provides utilities for initialising a disc
and copying discs of similar characteristics.  The initialisation
involves accessing every track of the disc, writing and reading
a variety of tests patterns and building up a table oof bad blocks
on the disc.  The copy utility assumes the existance of this bad block
table on both the source and destination discs.
~S~O2. Interfaces
~BMonitor utilities for disc transfers and console input/output.
~S~O2.1 Hardware Interface
~BNone.
~S~O2.2 Software Interface
~
Utility Procedures:~
   DISC.COPY~
   INITIALISE.DISC~
~
Configuration Parameters:~
   SYS.SIZE~
   BAD.BLOCK.TABLE~
   BAD.BLOCK.TABLE.SIZE~
   BUFF.ADDR~
   BUFF.ADDR2~
   TABLE.BUFF1~
   TABLE.BUFF2~
~S~O2.2.1 DISC.COPY
~BThis procedure copies the discs from unit 0 to unit 1.  The
discs are assumed to have been initialised using INITIALISE.DISC
which places a table of defective blocks and their alternatives
on the disc.
~S~O2.2.2 INITIALISE.DISC
~BThis procedure checks the behaviour of a disc by reading and
writing test patterns to every block on the disc.  A table of
defective blocks is created and alternative blocks are assigned
for these.
~S~O2.2.3 SYS.SIZE
~BA literal gicing the size of the system area of a disc (as no.
of tracks).  This is used for the "SYS ONLY" option in the disc
copy.
~S~O2.2.4 BAD.BLOCK.TABLE
~BThe disc address (in 256 byte units) of the bad block table.
~S~O2.2.5 BAD.BLOCK.TABLE.SIZE
~BThe size of the bad block table.  This is equal to the maximum
number of defective blocks that can be accommodated plus 1.
~S~O2.2.6 BUFF.ADDR
~BThe store address of a disc buffer for use by the copy utility.
Its size is the size of a complete track on the disc.
~S~O2.2.7 BUFF.ADDR2
~BThe store address of a disc buffer for use by the copy and
initialise utilities.  Its size is the size of a complete
track on the disc.
~S~O2.2.8 TABLE.BUFF1, TABLE.BUFF2
~BBuffers for use by the copy and initialisation utilities to
hold a bad block table.
~S~O3. Implementation
~BThe last track of a disc is allocated to hold a bad block
table and substitute blocks.  This track is allocated in
PAGE.SIZE units, and the last of these blocks holds the bad
block table itself.
~BThe bad block table contains a list of blocks which are known
to be defective, and block numbers (on this final track) of
blocks which may be used as substitutes for the bad ones.  The
disc addresses in this table are in the system units of
SYS14.PAGE.SIZE.
~Y
~V9 -1
~P
~D15
~HFLOWCHARTS
~
~
~H                SYS513
~V9 -1
~F
@TITLE SYS51(3,11)
@COL 1S-2R-3R-6F
@FLOW 1-2-3-6
@BOX 1.0
DISC UTILITIES
@BOX 3.0
PROCEDURES IN MODULE
   1 DISC COPY
   2 INITIALISE DISC
@BOX6.0
END
@BOX 1.1
IMPORT LITERAL SYS14.PAGE.SIZE, SYS14.PAGE.SHIFT, SYS.SIZE, BAD.BLOCK.TABLE.SIZE
;
IMPORT LITERAL INTEGER32 BAD.BLOCK.TABLE;
LOGICAL [2] DISC.SIZE, TRACK.SIZE;
PSPEC DISC.TRAN (LOGICAL32, LOGICAL32, LOGICAL, LOGICAL, LOGICAL) / INTEGER;
PSPEC PRINT (ADDR [LOGICAL8]);
PSPEC GET.CONS () / LOGICAL;
PSPEC PUT.CONS (LOGICAL);
MODULE;
@BOX 2.1
#SYS51/1
@BOX 3.1
*CODE 6;
#SYS51.1
*CODE 7;
#SYS51.2
@BOX 6.1
*END
@END
@TITLE SYS51/1(3,11)
@COL 1S-2R-3R-4R-5F
@FLOW 1-2-3-4-5
@BOX 1.0
DECLARATIONS
@BOX 2.0
LITERALS AND VARIABLES
@BOX 3.0
PROC SPECS
@BOX 4.0
DATAVECS
@BOX 5.0
END
@BOX 1.1
::BEGIN
@BOX 2.1
*CODE 6;
TYPE BAD.PAGE.TYPE IS
   LOGICAL32 F.PAGE, S.PAGE
OR
   LOGICAL32 TABLE.ENTRY;
LITERAL / LOGICAL SP = %20, LF = 10, CR = 13;
*GLOBAL 20;
INTEGER SSIZE, FCOUNT, NO.OF.S.PAGES, PAGE.SIZE, PAGE.SHIFT;
INTEGER32 BAD.BLOCK.ADDR;
ADDR [BAD.PAGE.TYPE] OLD.TABLE, NEW.TABLE;
@BOX 3.1
PSPEC DISC.COPY ();
PSPEC INITIALISE.DISC ();
@BOX 4.1
*GLOBAL 1;
DATAVEC M3 (LOGICAL8);
"DO YOU WISH TO COPY" %A %D
" A-ALL THE DISC" %A %D
" B SYS ONLY" %A %D
" C FILES ONLY" %A %D
END
DATAVEC M4 (LOGICAL8);
"CONFIRM (Y)"
END
DATAVEC M5 (LOGICAL8);
"COPY COMPLETED" %A %D
END
DATAVEC M6 (LOGICAL8);
"READ ERROR: TABLE 0" %A %D
END
DATAVEC M7 (LOGICAL8);
"READ ERROR: TABLE 1" %A %D
END
DATAVEC M8 (LOGICAL8);
"WRITE ERROR: TABLE 1" %A %D
END
DATAVEC M1 (LOGICAL8);
" *** DISC INITIALISATION COMPLETED" %D %A
END
DATAVEC P.TABLE (LOGICAL32);
%00000000 %FFFFFFFF
END
DATAVEC EM4 (LOGICAL8);
"*** MATCHING ERROR" %A %D
END
DATAVEC EM3 (LOGICAL8);
"*** READ ERROR" %A %D
END
DATAVEC EM2 (LOGICAL8);
"*** WRITE ERROR" %A %D
END
DATAVEC EM1 (LOGICAL8);
"*** NO MORE SUBSTITUTE PAGES" %A %D
END
*GLOBAL 0;
@BOX 5.1
::END
@END

@TITLE SYS51.1(3,11)
@COL 1S-10R-2R-3R-4T-5R-6R-7F
@FLOW 1-10-2-3-4Y-5-6-7
@FLOW 4N-2
@BOX 1.0
DISC COPY
@BOX 2.0
ASK WHAT KIND OF
COPY IS REQUIRED
@BOX 3.0
READ CHARACTER
@BOX 4.0
VALID?
@BOX 5.0
COPY DISC AS REQUIRED
 [SYS51.1.1]
@BOX 6.0
OUTPUT 'COPY COMPLETED'
TEST IF SUBSTITUTE BLOCKS BLOCK
CAN BE READ
@BOX 7.0
END
@BOX 10.0
INITIALISE GLOBAL VARIABLES
@BOX 1.1
PROC DISC.COPY;
INTEGER CH, COUNT, TRSIZE;
INTEGER32 TRACK, TEMP;
PSPEC READ.SINGLE.PAGES (INTEGER32);
PSPEC WRITE.SINGLE.PAGES (INTEGER32);
PSPEC NEW.BAD.TABLE (ADDR [BAD.PAGE.TYPE]);
#SYS51.1.2
#SYS51.1.3
#SYS51.3
@BOX 10.1
SYS14.PAGE.SIZE / 256 => PAGE.SIZE;
SYS14.PAGE.SHIFT - 8 => PAGE.SHIFT;
BAD.BLOCK.TABLE + (BAD.BLOCK.TABLE.SIZE - 1 <<- PAGE.SHIFT) => BAD.BLOCK.ADDR;
@BOX 2.1
PRINT (^M3);
@BOX3.1
GETCONS () => CH;
@BOX 4.1
IF CH < 'A OR CH > 'C
@BOX 5.1
#SYS51.1.1
@BOX 6.1
PRINT (^M5);
IF DISC.TRAN (BAD.BLOCK.ADDR, TABLE.BUFF2, 1, PAGE.SIZE, 0) /= 0 THEN
   PRINT (^M7);
FI
@BOX 7.1
END
@END
@TITLE SYS51.1.1(3,11)
@COL 15R-16R
@COL 1S-2R-3R-4R-5R-6T-30T-9T-20N-21T-31T-11T-17N-12T-13F
@ROW 15-20
@ROW 16-17
@FLOW 1-2-3-4-5-6N-30-9N-20-21-31-11N-17-12-13
@FLOW 30-6
@FLOW 31-21
@FLOW 6Y-15-16-12
@FLOW 9Y-15
@FLOW 11Y-16
@FLOW 12Y-5
@FLOW 21-16
@BOX 1.0
::COPY
@BOX 2.0
GET COPY PARAMETERS
@BOX 3.0
READ LIST OF SUBSTITUTE
PAGES INTO STORE
@BOX 4.0
INITIALISE NEW TABLE OR READ
FROM DESTINATION DISC IN THE
CASE OF A PARTIAL COPY
@BOX 5.0
CALCULATE TRACK ADDRESS
@BOX 6.0
IS BLOCK OF READ TRACK IN
A SUBSTITUTE PAGE
@BOX 30.0
ANYMORE BLOCKS IN THE TRACK?
@BOX 9.0
ANY ERROR IN READING
TRACK TO BUFFER?
@BOX 21.0
IS BLOCK ON TRACK TO BE WRITTEN
ON A SUBSTITUTE PAGE?
@BOX 31.0
SELECT NEXT BLOCK ON TRACK
@BOX 11.0
ANY ERROR IN WRITING THE TRACK?
@BOX 12.0
ANYMORE TRACKS?
@BOX 13.0
WRITE LIST OF FAULTY PAGES
@BOX 15.0
READ TRACK A PAGE AT A TIME
@BOX 16.0
WRITE TRACK A PAGE AT A TIME
@BOX 1.1
::COPY
@BOX 2.1
ALTERNATIVE CH - "A" FROM
   DISC.SIZE [0] - 1 => TRSIZE * TRACK.SIZE [0] => TRACK;
      ::COPY ALL IGNORES LAST TRACK WITH BAD BLOCK TABLE
   SYSSIZE => TRSIZE * TRACK.SIZE [0] => TRACK;
   BEGIN
      DISC.SIZE [0] - SYSSIZE => TRSIZE;
      DISC.SIZE [0] * TRACK.SIZE [0] => TRACK;
   END
END
@BOX 3.1
MAKE (BAD.PAGE.TYPE, BAD.BLOCK.TABLE.SIZE, TABLE.BUFF1) => OLD.TABLE;
IF DISC.TRAN (BAD.BLOCK.ADDR, TABLE.BUFF1, 0, PAGE.SIZE, 0) /= 0 THEN
   PRINT (^M6);
   NEW.BAD.TABLE (OLD.TABLE);
FI
TABLE.ENTRY OF OLD.TABLE^ [BAD.BLOCK.TABLE.SIZE - 1] => SSIZE;
@BOX 4.1
MAKE (BAD.PAGE.TYPE, BAD.BLOCK.TABLE.SIZE, TABLE.BUFF2) => NEW.TABLE;
IF DISC.TRAN (BAD.BLOCK.ADDR, TABLE.BUFF2, 1, PAGE.SIZE, 0) /= 0 THEN
   PRINT (^M7);
   NEW.BAD.TABLE (NEW.TABLE);
FI
TABLE.ENTRY OF NEW.TABLE^ [BAD.BLOCK.TABLE.SIZE - 1] => FCOUNT => NO.OF.S.PAGES;
@BOX 5.1
TRACK - PAGE.SIZE => TEMP;
TRACK.SIZE [0] -> TRACK;
@BOX 6.1
-1 => COUNT;
WHILE 1 +> COUNT < SSIZE AND
   TEMP ->> PAGE.SHIFT /= F.PAGE OF OLD.TABLE^ [COUNT] DO OD
IF COUNT < SSIZE
@BOX 9.1
TRACK + TRACK.SIZE [0] - PAGE.SIZE => TEMP;
IF DISC.TRAN (TRACK, BUFF.ADDR, 0, TRACK.SIZE [0], 0) /= 0
@BOX 11.1
IF DISC.TRAN (TRACK, BUFF.ADDR, 1, TRACK.SIZE [1], 1) /= 0
@BOX 12.1
IF 1 -> TRSIZE > 0
@BOX 13.1
NO.OF.S.PAGES => TABLE.ENTRY OF NEW.TABLE^ [BAD.BLOCK.TABLE.SIZE - 1];
IF DISC.TRAN (BAD.BLOCK.ADDR, TABLE.BUFF2, 1, PAGE.SIZE, 1) /= 0 THEN
   PRINT (^M8);
   HALT1: -> HALT1;
FI
@BOX 15.1
READ.SINGLE.PAGES (TRACK);
@BOX 16.1
WRITE.SINGLE.PAGES (TRACK);
@BOX 21.1
-1 => COUNT;
WHILE 1 +> COUNT < NO.OF.S.PAGES AND
   TEMP ->> PAGE.SHIFT /= F.PAGE OF NEW.TABLE^ [COUNT] DO OD
IF COUNT < NO.OF.S.PAGES
@BOX 30.1
IF PAGE.SIZE -> TEMP >= TRACK
@BOX 31.1
IF PAGE.SIZE -> TEMP >= TRACK
@END
@TITLE SYS51.1.2(3,11)
@COL 1S-2R-3R-5T-6R-7T-8F
@FLOW 1-2-3-5N-6-7N-8
@FLOW 5Y-7
@FLOW 7Y-3

@BOX 1.0
READ SINGLE PAGES (T.ADDR)
@BOX 2.0
INITIALISE VARIABLES
@BOX 3.0
GET DISC ADDRESS OF BLOCK
@BOX 4.0
READ BLOCK
@BOX 5.0
READ OK?
@BOX 6.0
PRINT ERROR MESSAGE
@BOX 7.0
ANYMORE BLOCKS TO READ?
@BOX 8.0
END
@BOX 1.1
PROC READ.SINGLE.PAGES (T.ADDR);
INTEGER COUNT, PAGE.COUNT, B.ADDR, NO.OF.PAGES;
INTEGER32 DISC.ADDR, D.ADDR;
@BOX 2.1
BUFF.ADDR => B.ADDR;
T.ADDR => D.ADDR;
TRACK.SIZE [0] ->> PAGE.SHIFT => NO.OF.PAGES;
0 => PAGE.COUNT;
@BOX 3.1
FOR COUNT < SSIZE DO
   IF D.ADDR ->> PAGE.SHIFT = F.PAGE OF OLD.TABLE^ [COUNT] THEN
      S.PAGE OF OLD.TABLE^ [COUNT] <<- PAGE.SHIFT => DISC.ADDR;
      -> OUT;
   FI
OD
D.ADDR => DISC.ADDR;
OUT:
@BOX 5.1
IF DISC.TRAN (DISC.ADDR, B.ADDR, 0, PAGE.SIZE, 0) = 0
@BOX 6.1
PRINT (^EM3);
@BOX 7.1
PAGE.SIZE * 256 +> B.ADDR;
PAGE.SIZE +> D.ADDR;
IF 1 +> PAGE.COUNT < NO.OF.PAGES
@BOX 8.1
END
@END
@TITLE SYS51.1.3(3,11)
@COL 11N-8R-12N
@COL 1S-2R-13N-10R-4T-5T-6R-7F
@COL 14N-9T
@ROW 8-6
@ROW 5-9
@ROW 11-13-14
@FLOW 1-2-13-10-4N-5N-6-7
@FLOW 4Y-9N-7
@FLOW 9Y-14-13
@FLOW 5Y-8-12-11-14

@BOX 1.0
WRITE SINGLE PAGES (TRACK ADDR)
@BOX 2.0
INITIALISE VARIABLES
@BOX 3.0
WRITE PAGE
@BOX 4.0
WRITE OK?
@BOX 5.0
ANYMORE SUBSTITUTE PAGES?
@BOX 6.0
PRINT ERROR MESSAGE
AND HALT
@BOX 7.0
END
@BOX 8.0
ALLOCATE SUBSTITUTE PAGE
@BOX 9.0
ANYMORE PAGES TO WRITE?
@BOX 10.0
GET DISC ADDRESS OF BLOCK
@BOX 1.1
PROC WRITE.SINGLE.PAGES (T.ADDR);
INTEGER PAGE.COUNT, COUNT, B.ADDR, LAST.SUB, NO.OF.PAGES;
INTEGER32 DISC.ADDR;
@BOX 2.1
T.ADDR => DISC.ADDR;
BUFF.ADDR => B.ADDR;
TRACK.SIZE [1] ->> PAGE.SHIFT => NO.OF.PAGES;
0 => PAGE.COUNT;
@BOX 4.1
IF DISC.TRAN (DISC.ADDR, B.ADDR, 1, PAGE.SIZE, 1) = 0
@BOX 5.1
IF DISC.ADDR /= T.ADDR THEN
   -1 => TABLE.ENTRY OF NEW.TABLE^ [LAST.SUB];
   T.ADDR => DISC.ADDR;
FI
IF FCOUNT < BAD.BLOCK.TABLE.SIZE - 1
@BOX 6.1
PRINT (^EM1);
HALT:->HALT;
@BOX 7.1
END
@BOX 8.1
PRINT (^EM2);
1 +> NO.OF.S.PAGES;
DISC.ADDR ->> PAGE.SHIFT => F.PAGE OF NEW.TABLE^ [FCOUNT];
S.PAGE OF NEW.TABLE^ [FCOUNT] => DISC.ADDR;
FCOUNT => LAST.SUB;
1 +> FCOUNT;
@BOX 9.1
PAGE.SIZE * 256 +> B.ADDR;
PAGE.SIZE +> T.ADDR => DISC.ADDR;
IF 1 +> PAGE.COUNT < NO.OF.PAGES
@BOX 10.1
FOR COUNT < NO.OF.S.PAGES DO
   IF DISC.ADDR ->> PAGE.SHIFT = F.PAGE OF NEW.TABLE^ [COUNT] THEN
      S.PAGE OF NEW.TABLE^ [COUNT] <<- PAGE.SHIFT => DISC.ADDR;
      COUNT => LAST.SUB;
   FI
OD
@END
@TITLE SYS51.2(3,11)
@COL 1S-6T-5R-2R-3R-4F
@FLOW 1-6-5-2-3-4
@FLOW 6ABANDONED-4
@BOX 1.0
INITIALISE DISC
@BOX 5.0
INITIALISE GLOBAL VARIABLES
@BOX 2.0
INITIALISE SUBSTITUTE BLOCK TABLES
@BOX 3.0
FIND SUBSTITUTE BLOCKS BY TRANSFERRING
DIFFERENT BIT PATTERNS
@BOX 4.0
END
@BOX 6.0
CONFIRM INITIALISATION REQUIRED
@BOX 1.1
PROC INITIALISE.DISC;
INTEGER COUNT, NO.OF.PATTERNS, I, TRSIZE, NO.OF.PAGES;
INTEGER32 TRACK, TEMP;
LOGICAL32 PATTERN;
ADDR [BAD.PAGE.TYPE] NEW.TABLE;
ADDR [LOGICAL32] BUFFER1;
PSPEC TRANSFER.SINGLE.PAGES (LOGICAL32, LOGICAL, LOGICAL);
PSPEC FIND.SUB.PAGE (LOGICAL, LOGICAL);
PSPEC COMPARE.BUFFERS (LOGICAL32, LOGICAL, LOGICAL);
PSPEC WORD.OUT ();
PSPEC NEW.BAD.TABLE (ADDR [BAD.PAGE.TYPE]);
#SYS51.2.2
#SYS51.2.3
#SYS51.2.4
#SYS51.2.5
#SYS51.3
@BOX 2.1
2 => NO.OF.PATTERNS;
MAKE (BAD.PAGE.TYPE, BAD.BLOCK.TABLE.SIZE, TABLE.BUFF2) => NEW.TABLE;
NEW.BAD.TABLE (NEW.TABLE);
0 => NO.OF.S.PAGES;
-1 => FCOUNT;
@BOX 3.1
FOR I < NO.OF.PATTERNS DO
   DISC.SIZE [1] => TRSIZE;
   BAD.BLOCK.TABLE => TRACK + TRACK.SIZE [1] => TEMP;
   P.TABLE [I] => PATTERN;
   #SYS51.2.1
OD
NO.OF.S.PAGES => F.PAGE OF NEW.TABLE^ [BAD.BLOCK.TABLE.SIZE - 1];
DISC.TRAN (BAD.BLOCK.ADDR, TABLE.BUFF2, 1, PAGE.SIZE, 1);
WORD.OUT ();
PRINT (^M1);
@BOX 4.1
END
@BOX 5.1
SYS14.PAGE.SIZE / 256 => PAGE.SIZE;
SYS14.PAGE.SHIFT - 8 => PAGE.SHIFT;
BAD.BLOCK.TABLE + (BAD.BLOCK.TABLE.SIZE - 1 <<- PAGE.SHIFT) => BAD.BLOCK.ADDR;
TRACK.SIZE [1] ->> PAGE.SHIFT => NO.OF.PAGES;
@BOX 6.1
PRINT (^M4);
IF GETCONS () /= "Y"
@END
@TITLE SYS51.2.1(3,11)
@COL 15R-16R
@COL 1S-3R-4T-9T-20N-11T-17N-18R-12T-13F
@ROW 15-20
@ROW 16-17
@FLOW 1-3-4-9N-20-11N-17-18-12-13
@FLOW 4Y-15
@FLOW 9Y-15-16-18
@FLOW 11Y-16
@FLOW 12Y-4
@BOX 1.0
BEGIN :: NEW BLOCK
@BOX 3.0
INITIALISE TEST PATTERN
IN BUFFER
@BOX 4.0
TRACK INCLUDES A SUBSTITUTE BLOCK?
@BOX 9.0
ANY ERRORS IN WRITING
TRACK FROM BUFFER?
@BOX 11.0
ANY ERRORS IN READING
TRACK TO BUFFER?
@BOX 18.0
COMPARE BUFFERS
[SYS51.2.4]
@BOX 12.0
ANYMORE TRACKS?
@BOX 13.0
END
@BOX 15.0
WRITE TRACK A PAGE AT A TIME
@BOX 16.0
READ TRACK A PAGE AT A TIME
@BOX 1.1
BEGIN :: NEW.BLOCK
@BOX 3.1
MAKE (LOGICAL32, TRACK.SIZE [1] * 64, BUFF.ADDR) => BUFFER1;
FOR COUNT < TRACK.SIZE [1] * 64 DO
   PATTERN => BUFFER1^ [COUNT];
OD
@BOX 4.1
-1 => COUNT;
WHILE 1 +> COUNT < NO.OF.S.PAGES AND
   [F.PAGE OF NEW.TABLE^ [COUNT] <<- PAGE.SHIFT < TRACK OR
   F.PAGE OF NEW.TABLE^ [COUNT] <<- PAGE.SHIFT >= TEMP] DO OD
IF COUNT < NO.OF.S.PAGES
@BOX 9.1
IF DISC.TRAN (TRACK, BUFF.ADDR, 1, TRACK.SIZE [1], 1) /= 0
@BOX 11.1
IF DISC.TRAN (TRACK, BUFF.ADDR2, 1, TRACK.SIZE [1], 0) /= 0
@BOX 12.1
TRACK => TEMP;
TRACK.SIZE [1] -> TRACK;
IF 1 -> TRSIZE > 0
@BOX 13.1
END
@BOX 15.1
TRANSFER.SINGLE.PAGES (TRACK, BUFF.ADDR, 1);
@BOX 16.1
TRANSFER.SINGLE.PAGES (TRACK, BUFF.ADDR2, 0);
@BOX 18.1
COMPARE.BUFFERS (TRACK, 0, NO.OF.PAGES);
@END
@TITLE SYS51.2.2(3,11)
@COL 1S-2R-10R-4T-5T-6T-7F
@FLOW 1-2-10-4N-5N-6-7
@FLOW 6-10
@FLOW 4-6

@BOX 1.0
TRANSFER SINGLE PAGES (TRACK ADDR, CORE ADDR, TRAN DIRN)
@BOX 2.0
INITIALISE VARIABLES
@BOX 3.0
TRANSFER PAGE
@BOX 4.0
TRANSFER OK?
@BOX 5.0
PRINT ERROR MESSAGE
ANYMORE SUBSTITUTE PAGES?
@BOX 6.0
ANY MORE BLOCKS ON TRACK?
@BOX 7.0
END
@BOX 8.0
ALLOCATE SUBSTITUTE PAGE
@BOX 9.0
ANYMORE PAGES TO WRITE?
@BOX 10.0
GET DISC ADDRESS OF BLOCK
@BOX 1.1
PROC TRANSFER.SINGLE.PAGES (T.ADDR, C.ADDR, TRAN.TYPE);
INTEGER PAGE.COUNT, COUNT, LAST.SUB, NO.OF.PAGES;
INTEGER32 DISC.ADDR;
ADDR [BAD.PAGE.TYPE] NEW.TABLE;
@BOX 2.1
T.ADDR => DISC.ADDR;
0 => PAGE.COUNT;
TRACK.SIZE [1] ->> PAGE.SHIFT => NO.OF.PAGES;
MAKE (BAD.PAGE.TYPE, BAD.BLOCK.TABLE.SIZE, TABLE.BUFF2) => NEW.TABLE;
@BOX 4.1
IF DISC.TRAN (DISC.ADDR, C.ADDR, 1, PAGE.SIZE, TRAN.TYPE) = 0
@BOX 5.1
ALTERNATIVE TRAN.TYPE FROM
PRINT (^EM3);
PRINT (^EM2);
END
IF DISC.ADDR /= T.ADDR THEN
   -1 => F.PAGE OF NEW.TABLE^ [LAST.SUB];
FI
FIND.SUB.PAGE (T.ADDR, PAGE.COUNT <<- SYS14.PAGE.SHIFT);
@BOX 6.1
PAGE.SIZE * 256 +> C.ADDR;
PAGE.SIZE +> T.ADDR => DISC.ADDR;
IF 1 +> PAGE.COUNT < NO.OF.PAGES
@BOX 7.1
END
@BOX 10.1
-1 => LAST.SUB;
WHILE 1 +> LAST.SUB < NO.OF.S.PAGES DO
   IF DISC.ADDR ->> PAGE.SHIFT = F.PAGE OF NEW.TABLE^ [LAST.SUB] THEN
      S.PAGE OF NEW.TABLE^ [LAST.SUB] <<- PAGE.SHIFT=> DISC.ADDR;
   FI
OD
@END
@TITLE SYS51.2.3(3,11)

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

@ROW 7-13

@FLOW 1-8NO-9
@FLOW 8YES-3-4-5OK-7OK-11-10
@FLOW 4YES-8
@FLOW 5FAIL-13-8
@FLOW 7FAIL-12-8

@BOX 1.0
FIND SUBSTITUTE PAGE
@BOX 2.0
@BOX 3.0
SELECT NEXT ENTRY IN
SUBSTITUTE BLOCK TABLE
@BOX 4.0
SUBSTITUTE BLOCK A FAULTY BLOCK?
@BOX 5.0
WRITE TO SUBSTITUTE BLOCK
@BOX 7.0
READ SUBSTITUTE BLOCK BACK
@BOX 12.0
MONITOR - READ ERROR
@BOX 8.0
ANY MORE SUBSTITUTE PAGES?
@BOX 9.0
MONITOR - NO MORE SUBSTITUTE PAGES
@BOX 10.0
END
@BOX 11.0
STORE ORIGINAL TRACK ADDR
IN SUBSTITUTE BLOCK TABLE
@BOX 13.0
MONITOR - WRITE ERROR
@BOX 1.1
PROC FIND.SUB.PAGE (T.ADDR, BUFF.DISP);
INTEGER COUNT, DISC.ADDR;
ADDR [BAD.PAGE.TYPE] NEW.TABLE;
MAKE (BAD.PAGE.TYPE, BAD.BLOCK.TABLE.SIZE, TABLE.BUFF2) => NEW.TABLE;
@BOX 3.1
1 +> FCOUNT;
@BOX 4.1
-1 => COUNT;
WHILE 1 +> COUNT < NO.OF.S.PAGES AND
   S.PAGE OF NEW.TABLE^ [FCOUNT] /= F.PAGE OF NEW.TABLE^ [COUNT] DO OD
IF COUNT < NO.OF.S.PAGES
@BOX 5.1
S.PAGE OF NEW.TABLE^ [FCOUNT] <<- PAGE.SHIFT => DISC.ADDR;
IF DISC.TRAN (DISC.ADDR, BUFF.ADDR + BUFF.DISP, 1, PAGE.SIZE, 1) /= 0
@BOX 7.1
IF DISC.TRAN (DISC.ADDR, BUFF.ADDR2 + BUFF.DISP, 1, PAGE.SIZE, 0) /= 0
@BOX 8.1
IF FCOUNT < BAD.BLOCK.TABLE.SIZE - 2
@BOX 9.1
PRINT (^EM1);
HALT: -> HALT;
@BOX 10.1
END
@BOX 11.1
FCOUNT + 1 => NO.OF.S.PAGES;
T.ADDR ->> PAGE.SHIFT => F.PAGE OF NEW.TABLE^ [FCOUNT];
@BOX 12.1
PRINT (^EM3);
@BOX 13.1
PRINT (^EM2);
@END
@TITLE SYS51.2.4(3,11)
@COL 1S-2R-3R-4F
@FLOW 1-2-3-4
@BOX 1.0
COMPARE BUFFERS
@BOX 2.0
INITIALISE BUFFER POINTERS
@BOX 3.0
FIND SUBSTITUTE PAGES FOR ALL
DIFFERRING BUFFER PAGES
@BOX 4.0
END
@BOX 1.1
PROC COMPARE.BUFFERS (D.ADDR, BUFF.DISP, PAGE.COUNT);
INTEGER I, PAGE, P.SIZE, COUNT;
INTEGER32 DISC.ADDR;
ADDR [LOGICAL32] BUFFER1, BUFFER2;
ADDR [BAD.PAGE.TYPE] NEW.TABLE;
@BOX 2.1
PAGE.COUNT <<- SYS14.PAGE.SHIFT ->> 2 => P.SIZE;
MAKE (LOGICAL32, P.SIZE, BUFF.ADDR + BUFF.DISP) => BUFFER1;
MAKE (LOGICAL32, P.SIZE, BUFF.ADDR2 + BUFF.DISP) => BUFFER2;
MAKE (BAD.PAGE.TYPE, BAD.BLOCK.TABLE.SIZE, TABLE.BUFF2) => NEW.TABLE;
@BOX 3.1
FOR PAGE < PAGE.COUNT DO
   PAGE <<- SYS14.PAGE.SHIFT ->> 2 - 1 => I;
   FOR PAGE.SIZE * 64 DO
      IF BUFFER1^ [1 +> I] /= BUFFER2^ [I] THEN
         PRINT (^EM4);
         -1 => COUNT;
         PAGE <<- PAGE.SHIFT + D.ADDR => DISC.ADDR;
         WHILE 1 +> COUNT < NO.OF.S.PAGES AND DISC.ADDR ->> PAGE.SHIFT
             /= F.PAGE OF NEW.TABLE^ [COUNT] DO OD;
         IF COUNT < NO.OF.S.PAGES THEN
            -1 => F.PAGE OF NEW.TABLE^ [COUNT];
         FI
         IF BUFF.DISP = 0 THEN
            PAGE <<- SYS14.PAGE.SHIFT => BUFF.DISP;
         FI
         FIND.SUB.PAGE (DISC.ADDR, BUFF.DISP);
         COMPARE.BUFFERS (DISC.ADDR, BUFF.DISP, 1);
         -> OUT;
      FI
   OD
   OUT:
OD
@BOX 4.1
END
@END
@TITLE SYS51.2.5(3,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
WORD OUT
@BOX 2.0
PRINT BLOCK TABLE
@BOX 3.0
END
@BOX 1.1
PROC WORD.OUT;
INTEGER I;
LOGICAL32 TEMP, WORD;
ADDR [LOGICAL32] V.WORD;
MAKE (LOGICAL32, BAD.BLOCK.TABLE.SIZE * 2, TABLE.BUFF2) => V.WORD;
@BOX 2.1
-1 => I;
FOR NO.OF.S.PAGES DO
   FOR 2 DO
      V.WORD^ [1 +> I] => WORD;
      FOR 8 DO
         WORD ->> 28 & %F => TEMP;
         IF TEMP < 10 THEN
            PUT.CONS (TEMP + "0");
         ELSE
            PUT.CONS (TEMP - 10 + "A");
         FI
         WORD <<- 4 => WORD;
      OD
      PUT.CONS (SP); PUT.CONS (SP);
   OD
   PUT.CONS (LF);
OD
@BOX 3.1
END
@END
@TITLE SYS51.3(3,11)

@COL 1S-2R-3F

@FLOW 1-2-3

@BOX 1.0
NEW BAD TABLE (TABLE)
@BOX 2.0
CREATE NEW BAD BLOCK TABLE
@BOX 3.0
END
@BOX 1.1
PROC NEW.BAD.TABLE (TABLE);
INTEGER COUNT;
ADDR [LOGICAL8] PTR;
MAKE (LOGICAL8, SYS14.PAGE.SIZE, BYTE (TABLE)) => PTR;
@BOX 2.1
FOR COUNT < SYS14.PAGE.SIZE DO
   0 => PTR^ [COUNT];
OD
FOR COUNT < BAD.BLOCK.TABLE.SIZE DO
   SELECT TABLE^ [COUNT];
   -1 => F.PAGE;
   BAD.BLOCK.TABLE ->> PAGE.SHIFT + COUNT => S.PAGE;
OD
0 => TABLE.ENTRY;
@BOX 3.1
END
@END



