$CONTROL MAP,CODE,USLINIT                                               00010000
<<MEMLOGP - MODULE 11>>                                                 00015000
<< HP32002C MPE SOURCE C.00.00 >>                                       00020000
$COPYRIGHT     "(C) COPYRIGHT HEWLETT-PACKARD CO. 1980. ",            & 00025000
$     "THIS PROGRAM MAY BE USED WITH ONE COMPUTER SYSTEM AT A ",      & 00030000
$     "TIME AND SHALL NOT OTHERWISE BE RECORDED, TRANSMITTED OR ",    & 00035000
$     "STORED IN A RETRIEVAL SYSTEM.  COPYING OR OTHER REPRODUCTION ",& 00040000
$     "OF THIS PROGRAM EXCEPT FOR ARCHIVAL PURPOSES IS PROHIBITED ",  & 00045000
$     "WITHOUT THE PRIOR WRITTEN CONSENT OF HEWLETT-PACKARD COMPANY."   00050000
$CONTROL MAIN=MEMLOGP,SEGMENT=MEMLOGP                                   00055000
$CONTROL PRIVILEGED                                                     00060000
$CONTROL UNCALLABLE                                                     00065000
$TITLE "- ERROR CORRECTING MEMORY LOGGING PROCESS"                      00070000
$THIRTY                                                                 00075000
BEGIN                                                                   00080000
                                                                        00085000
<<------------------------------------------------------------          00090000
*                                                            *          00095000
*         ERROR CORRECTING MEMORY LOGGING PROCESS            *          00100000
*                                                            *          00105000
------------------------------------------------------------>>          00110000
                                                                        00115000
INTEGER X = X;                                                          00120000
                                                                        00125000
INTEGER S0 = S-0;                                                       00130000
INTEGER S1 = S-1;                                              <<TP2MB>>00135000
                                                                        00140000
LOGICAL DTIME:=3600;  <<MUST BE AT DB+0 - INITIALIZED TO 1 HOUR>>       00145000
                                                                        00150000
INTEGER ERR,FNUM,TICKCNT;                                      <<00.01>>00155000
                                                                        00160000
LOGICAL MEMREADY,FOPTIONS,SCANNING,ERRORFOUND;                 <<00.01>>00165000
                                                                        00170000
DOUBLE RECNUM,DELAYTIME;                                                00175000
                                                                        00180000
DOUBLE LOW'ADDR,HIGH'ADDR;                                     <<TP2MB>>00185000
                                                               <<TP2MB>>00190000
DOUBLE INCREMENT;                                              <<01396>>00195000
                                                               <<01396>>00200000
LOGICAL LOG'BIT;                                               <<TP2MB>>00205000
                                                               <<TP2MB>>00210000
INTEGER CPU'TYPE;                                              <<TP2MB>>00215000
                                                               <<TP2MB>>00220000
INTEGER ARRAY NEXT'CONTROLLER(1:6) := 2, 8, 8, 16, %77777, 4;  <<M8089>>00225000
                                                               <<TP2MB>>00230000
LOGICAL FIRST'TIME:=TRUE;  <<TRUE ON FIRST ACTIVATION ONLY>>   <<00684>>00235000
EQUATE RECSIZE  =  4112;  <<MEMLOG RECORD SIZE: 2048 WORDS LOG SIZE +   00240000
                            STARTIME(DBL) + LASTIME(DBL) +              00245000
                            FERRTIME(DBL) + LAERRTIME(DBL) + EXTRA >>   00250000
                                                               <<00.06>>00255000
DEFINE FILESIZE =   2D#;  <<MEMLOG FILE SIZE: 2 LOGICAL RECS>> <<00.06>>00260000
                                                               <<00.06>>00265000
ARRAY LOGREC(0:RECSIZE-1);                                              00270000
DOUBLE ARRAY LOGRECD(*) = LOGREC;                                       00275000
                                                               <<00.05>>00280000
                                                                        00285000
EQUATE                                                                  00290000
     DRT      =     2,  <<ERROR CORRECTING MEMORY DRT>>                 00295000
     SYSDB    =   512,  <<SYSTEM DB OFFSET>>                            00300000
     FSERR    =     0,  <<FILE SYSTEM ERROR>>                           00305000
     NOFILE   =    52,  <<FILE SYSTEM ERROR>>                           00310000
     FILECODE = -1234;                                                  00315000
                                                                        00320000
EQUATE << MEMORY ERROR LOGGING MESSAGE CATALOG NUMBERS >>               00325000
     MEMLOGMSG1 = 248,  <<LOGGING INITIATED>>                           00330000
     MEMLOGMSG2 = 249;  <<LOGGING ERROR MESSAGE>>                       00335000
                                                                        00340000
EQUATE << LOG RECORD LOCATIONS >>                                       00345000
     STARTIME  =  2048, <<DOUBLE LOCATION>>                    <<01396>>00350000
     LASTIME   =  2049, <<DOUBLE LOCATION>>                    <<01396>>00355000
     FERRTIME  =  2050, <<DOUBLE LOCATION>>                    <<01396>>00360000
     LERRTIME  =  2051, <<DOUBLE LOCATION>>                    <<01396>>00365000
     BANKNUMB  = 4104,                                         <<01396>>00370000
     DELAYLOC  = 4105;                                         <<01396>>00375000
                                                                        00380000
EQUATE  << SYSTEB DB LOCATIONS >>                                       00385000
     MEMBANKNUM = SYSDB+%47,   <<NUMBER  OF MEMORY BANKS>>              00390000
     SYSUP      = SYSDB+%73,   <<SYSTEM UP FLAG>>                       00395000
     PROGENPINX = SYSDB+%141,  <<PROGEN PCB INDEX>>                     00400000
     MEMLOGPINX = SYSDB+%154,  <<MEMLOGP PCB INDEX>>                    00405000
     STOPBITS   = SYSDB+%300;  <<SHUTDOWN STOP BITS>>                   00410000
                                                                        00415000
EQUATE  << DIRECT I/O TOS VALUES >>                                     00420000
     COPYLOG     = %020000,  <<COPY CONTENTS OF ELA INTO IOLA>>         00425000
     MASTERCLEAR = %100000,  <<CLEAR BOARD AFTER TIMEOUT>>     <<TP2MB>>00430000
     SCANLOG     = %010000,  <<SCAN IOLA FOR ERRORS RECORDED BY ELA>>   00435000
     CLEAR'IOLA  = %010000,  <<FILL IOLA WITH CONTENTS OF BIT 0>>       00440000
     CLEAR'ELA   = %020000;  <<COPY CONTENTS OF IOLA INTO ELA>>         00445000
                                                                        00450000
EQUATE  << MEMORY BOARDS - UPPER AND LOWER 128K>>                       00455000
     CONTROLLER'A = 0,                                         <<TP2MB>>00460000
     CONTROLLER'B = 1;                                         <<TP2MB>>00465000
                                                                        00470000
EQUATE  << SOFTWARE-TIO TIMEOUT PARAMETERS >>                  <<00.01>>00475000
     TICKMAX    =   3,  <<NUMBER OF DELAYS UNTIL TIMEOUT>>     <<00.01>>00480000
     TIMEOUTICK = 100;  <<TIMEOUT DELAY (IN MILLESECONDS)>>    <<00.01>>00485000
                                                               <<00.01>>00490000
DEFINE  << PARTIAL FIELDS >>                                            00495000
     ERRBIT   = ( 7: 1)#,                                               00500000
     SCANBIT  = ( 3: 1)#,                                               00505000
     MEMADDR  = ( 6:10)#;                                               00510000
                                                                        00515000
DEFINE  << DIRECT I/O FUNCTIONS >>                                      00520000
     TESTIO     = ASSEMBLE(TIO 0)#,                                     00525000
     READIO     = ASSEMBLE(RIO;BLE *+3;DEL;BR *-3)#,                    00530000
     WRITEIO    = ASSEMBLE(WIO 1;BLE *+3;DEL;BR *-3)#,                  00535000
     CONTROLIO  = ASSEMBLE(CIO 1)#;                                     00540000
                                                                        00545000
DEFINE << TP FUNCTIONS >>                                      <<TP2MB>>00550000
     READ'LOG     = TOS.(14:2):=0#,                            <<TP2MB>>00555000
     CLEAR'LOG    = TOS.(14:2):=2#,                            <<TP2MB>>00560000
     GET'LOG'BIT  = LOG'BIT:=TOS.(8:1)#,                       <<TP2MB>>00565000
     MCS          = ASSEMBLE(CON %020302;CON 7)#;              <<TP2MB>>00570000
                                                               <<TP2MB>>00575000
                                                               <<00.01>>00580000
DEFINE SHUTDOWN = LOGICAL(ABSOLUTE(STOPBITS).(4:1))#;          <<00.02>>00585000
DEFINE BANKNUM  = ABSOLUTE(MEMBANKNUM)#;                                00590000
                                                                        00595000
DEFINE DELETE = ASSEMBLE(DEL)#;                                         00600000
DEFINE DDELETE = ASSEMBLE(DEL,DEL)#;                                    00605000
DEFINE DUPLICATE = ASSEMBLE(DUP)#;                                      00610000
DEFINE DDUPLICATE = ASSEMBLE(DDUP)#;                                    00615000
                                                                        00620000
DEFINE CHECKFORLOGGING =                                                00625000
     BEGIN; TOS:=DRT;                                          <<RK.08>>00630000
     ASSEMBLE(TIO 0);                                                   00635000
     IF < THEN AWAKE(ABSOLUTE(PROGENPINX),2,%4000);                     00640000
     DDELETE; END#;                                            <<RK.08>>00645000
                                                                        00650000
INTRINSIC FOPEN,FCLOSE,FREAD,FREADDIR,FWRITE,FWRITEDIR,FCHECK,          00655000
          FGETINFO,FLOCK,FUNLOCK;                              <<01396>>00660000
INTRINSIC ASCII,CLOCK,CALENDAR,TERMINATE;                               00665000
                                                                        00670000
INTEGER PROCEDURE GENMSG(SETNO,MSGNO,MASK,A,B,C,D,E,           <<0U.EB>>00675000
      DEST,REPLY,BUFF,DST,IOTYPE);                             <<0U.EB>>00680000
   VALUE SETNO,MSGNO,MASK,A,B,C,D,E,DEST,REPLY,BUFF,           <<0U.EB>>00685000
      DST,IOTYPE;                                              <<0U.EB>>00690000
   LOGICAL SETNO,MSGNO,MASK,A,B,C,D,E,DEST,REPLY,BUFF,         <<0U.EB>>00695000
      DST,IOTYPE;                                              <<0U.EB>>00700000
   OPTION VARIABLE,EXTERNAL;                                   <<0U.EB>>00705000
                                                               <<0U.EB>>00710000
                                                                        00715000
PROCEDURE AWAKE(P,A,W);                                                 00720000
 VALUE P,A,W;                                                           00725000
 INTEGER P,A,W;                                                         00730000
 OPTION EXTERNAL;                                                       00735000
                                                                        00740000
PROCEDURE DELAY(T);                                                     00745000
 VALUE T;                                                               00750000
 DOUBLE T;                                                              00755000
 OPTION EXTERNAL;                                                       00760000
                                                                        00765000
PROCEDURE WAIT(W,D);                                           <<00.01>>00770000
 VALUE W,D;                                                    <<00.01>>00775000
 INTEGER W,D;                                                  <<00.01>>00780000
 OPTION EXTERNAL;                                              <<00.01>>00785000
                                                               <<00.01>>00790000
INTEGER PROCEDURE THISCPU;                                     <<TP2MB>>00795000
OPTION EXTERNAL;                                               <<TP2MB>>00800000
                                                               <<TP2MB>>00805000
PROCEDURE HELP;                                                         00810000
 OPTION EXTERNAL;                                                       00815000
                                                                        00820000
PROCEDURE ERRMESSAGE(ERRNUMB);                                          00825000
VALUE ERRNUMB;                                                          00830000
INTEGER ERRNUMB;                                                        00835000
BEGIN                                                                   00840000
     INTEGER ERROR;                                                     00845000
                                                                        00850000
     IF ERRNUMB = FSERR THEN FCHECK(FNUM,ERROR) ELSE ERROR:=ERRNUMB;;   00855000
     GENMSG(1,249,%10000,ERROR,,,,,0);                         <<0U.EB>>00860000
     FUNLOCK(FNUM);  <<MAKE SURE MEMLOGAN WILL RUN>>           <<00.07>>00865000
     IF ABSOLUTE(SYSUP) THEN                                   <<00.01>>00870000
        WAIT(%4000,0)                                          <<00.01>>00875000
     ELSE                                                      <<00.01>>00880000
        AWAKE(ABSOLUTE(PROGENPINX),2,%4000);                   <<00.01>>00885000
END <<ERRMESSAGE>>;                                                     00890000
                                                                        00895000
PROCEDURE CLEAR'LOG'BOARD(MEMBOARD);                                    00900000
VALUE MEMBOARD; INTEGER MEMBOARD;                                       00905000
BEGIN                                                                   00910000
     TOS:=DRT;                                                          00915000
     TOS:=CLEAR'IOLA;                                                   00920000
     WRITEIO;                                                           00925000
     TOS:=CLEAR'ELA CAT MEMBOARD(5:15:1);                               00930000
     WRITEIO;                                                           00935000
END << CLEAR'LOG'BOARD >>;                                              00940000
                                                                        00945000
PROCEDURE OPEN'MEMLOG;                                                  00950000
BEGIN                                                                   00955000
     INTEGER REC;                                              <<00.03>>00960000
     INTEGER FG'RSIZE;     << REC SIZE FROM FGETINFO >>        <<01396>>00965000
     BYTE ARRAY FNAME (0:15);                                  <<03021>>00970000
                                                               <<00.05>>00975000
     FNUM:=0;  <<ASSUME NO MEMLOG FILE FOUND>>                          00980000
     FOPTIONS:=%2001;                                                   00985000
     MOVE FNAME := "MEMLOG.PUB.SYS ";                          <<03021>>00990000
     WHILE FNUM = 0 DO                                                  00995000
     BEGIN                                                              01000000
          FNUM:=FOPEN(FNAME,FOPTIONS,%744,RECSIZE,,,,,,        <<00.06>>01005000
                      FILESIZE,,,FILECODE);                    <<00.06>>01010000
          IF <> THEN  <<FOPEN ERROR>>                                   01015000
          BEGIN                                                         01020000
               FCHECK(FNUM,ERR);                                        01025000
               IF ERR <> NOFILE THEN ERRMESSAGE(ERR);                   01030000
          END ELSE                                             <<03021>>01035000
          BEGIN                                                <<03021>>01040000
          FGETINFO(FNUM,,,,FG'RSIZE);                          <<01396>>01045000
          IF FG'RSIZE <> RECSIZE                               <<01396>>01050000
            THEN                                               <<01396>>01055000
            BEGIN                                              <<01396>>01060000
            FCLOSE(FNUM,4,0);                                  <<01396>>01065000
            FNUM := 0;                                         <<01396>>01070000
            END;                                               <<01396>>01075000
          END;                                                 <<03021>>01080000
          IF NOT FOPTIONS THEN  <<JUST FOPEN-ED NEW>>                   01085000
          BEGIN                                                         01090000
               LOGREC:=0; MOVE LOGREC(1):=LOGREC,(RECSIZE-1);  <<00.03>>01095000
               FOR REC:=0 UNTIL INTEGER (FILESIZE-1D) DO       <<03070>>01100000
               BEGIN   << Initialize log file.              >> <<03021>>01105000
                    FWRITEDIR(FNUM,LOGREC,RECSIZE,DOUBLE(REC));<<00.03>>01110000
                    IF <> THEN ERRMESSAGE(FSERR);              <<00.03>>01115000
               END;                                            <<00.03>>01120000
               FCLOSE(FNUM,1,0);                               <<01396>>01125000
               IF < THEN ERRMESSAGE(FSERR);                             01130000
               FNUM:=0; <<WILL CAUSE FINAL OPEN ATTEMPT>>               01135000
          END;                                                          01140000
          FOPTIONS.(15:1):=(FOPTIONS.(15:1)+1);                         01145000
     END;                                                               01150000
END << OPEN'MEMLOG >>;                                                  01155000
$PAGE                                                          <<03021>>01160000
PROCEDURE FILLTIME(TIMELOC);                                   <<03021>>01165000
VALUE TIMELOC; INTEGER TIMELOC;                                <<03021>>01170000
BEGIN                                                          <<03021>>01175000
     TOS:=CALENDAR;                                            <<03021>>01180000
     TOS:=CLOCK;                                               <<03021>>01185000
     DELETE;  <<DELETE SECONDS INFO.>>                         <<03021>>01190000
     IF LOGRECD(STARTIME) = 0D THEN                            <<03021>>01195000
     BEGIN                                                     <<03021>>01200000
          DDUPLICATE;                                          <<03021>>01205000
          LOGRECD(STARTIME):=TOS;  <<RECORD START TIME>>       <<03021>>01210000
          LOGRECD(FERRTIME):=0D;                               <<03021>>01215000
          LOGRECD(LERRTIME):=0D;                               <<03021>>01220000
          LOGREC(BANKNUMB):=BANKNUM;  <<NO. OF MEM BANKS>>     <<03021>>01225000
          LOGREC:=0; MOVE LOGREC(1):=LOGREC,(4095);            <<03021>>01230000
     END;                                                      <<03021>>01235000
     LOGRECD(TIMELOC):=TOS;  <<RECORD TIME>>                   <<03021>>01240000
END <<FILLTIME>>;                                              <<03021>>01245000
$PAGE                                                          <<03021>>01250000
PROCEDURE FILLOGREC'ICF55;                                     <<03021>>01255000
                                                               <<03021>>01260000
BEGIN COMMENT                                                  <<03021>>01265000
  This procedure reads the ICF/55 memory error logging RAM and <<03021>>01270000
updates the error counters in the LOGREC array for later  pro- <<03021>>01275000
cessing by MEMLOGAN. The first 4096 locations in LOGREC repre- <<03021>>01280000
sent 1248 possible chip addresses (156 chips on each of up  to <<03021>>01285000
8  memory array boards) (see below).  The unused locations are <<03021>>01290000
set to 0 and are not examined.  The 1248 addresses  which  are <<03021>>01295000
used  (not  necessarily the first 1248 in LOGREC) each contain <<03021>>01300000
an error count, or a count of the number of times an error has <<03021>>01305000
been recorded for that particular chip.  Note that the  counts <<03021>>01310000
are  increased  at  most by 1, even though more than one error <<03021>>01315000
may have occurred since the last time MEMLOGP  was  activated. <<03021>>01320000
This  is  because the logging RAM only knows that at least one <<03021>>01325000
error occurred.                                                <<03021>>01330000
  The ICF/55 (CPU'TYPE = 5) memory is the first to use a  1024 <<03021>>01335000
x 4 error logging RAM.  Previous memories have all used a 4096 <<03021>>01340000
x 1 RAM.  The mapping of the error logging RAM to  the  LOGREC <<03021>>01345000
array is shown below:                                          <<03021>>01350000
                                                               <<03021>>01355000
               LOGREC ADDRESS (12 BITS) (0:4095)               <<03021>>01360000
                                                               <<03021>>01365000
  ERROR LOGGING RAM ADDRESS (10 BITS)  |                       <<03021>>01370000
                                       |                       <<03021>>01375000
  ARRAY   |MEMORY  |       OTHER       |     ERROR LOGGING     <<03021>>01380000
 (BOARD)  | WORD   |      ADDRESS      |       RAM DATA        <<03021>>01385000
 ADDRESS  |ADDRESS |       BITS        | (4 INDEPENDENT BITS)  <<03021>>01390000
 ---------+--------+-------------------+---------------------  <<03021>>01395000
 | 0  1  2|  3   4 |  5   6   7   8   9| 10  11|               <<03021>>01400000
                                                               <<03021>>01405000
  Each time the RAM is accessed (using the  leftmost  10  bits <<03021>>01410000
above  as its address), it returns the 4 data bits at that ad- <<03021>>01415000
dress. These are independent (non-encoded) bits, that is, they <<03021>>01420000
individually represent the error state of  a  memory  data  or <<03021>>01425000
check  bit.  A "1" represents one or more errors since the RAM <<03021>>01430000
was last read and cleared, a "0" means no errors have occurred <<03021>>01435000
during that interval.                                          <<03021>>01440000
  ICF/55 memory is organized as one  to  eight  array  boards, <<03021>>01445000
each containing 4 "words". Each word consists of 39 RAMS, each <<03021>>01450000
either 1 x 16K or 1 x 64K.  A cross-sectional slice of 39 bits <<03021>>01455000
represents one 32-bit data word and seven  check  bits.  Since <<03021>>01460000
the  rest of the machine understands 16-bit words, each 32-bit <<03021>>01465000
word must be unpacked when read and re-packed when written. In <<03021>>01470000
addition, any memory write must actually consist  of  a  read- <<03021>>01475000
modify-write  cycle to protect the 16 bits which are not being <<03021>>01480000
changed.  The seven check bits are used to detect  all  memory <<03021>>01485000
errors,  and additionally correct all single-bit errors.  Thus <<03021>>01490000
one memory array board contains either 256K bytes  (16K  RAMS) <<03021>>01495000
or  1M byte (64K RAMS).  Since MEMLOGP and MEMLOGAN only iden- <<03021>>01500000
tify errors to the chip level, we don't  really  care  whether <<03021>>01505000
the chips have 16K or 64K bits.                                <<03021>>01510000
  A closer examination shows that 2 word bits +  5  other  ad- <<03021>>01515000
dress bits + 2 bits representing the encoded data bits can en- <<03021>>01520000
code 2**9 = 512 chip addresses per board. Since there are only <<03021>>01525000
4 x 39 = 156 chips per board, there will be a  lot  of  unused <<03021>>01530000
area in the logging RAM.  This is called expandability.        <<03021>>01535000
  Now that we've covered organization we'll examine  ways  and <<03021>>01540000
means.  FILLOGREC'ICF55  first  asks  if there's been an error <<03021>>01545000
since the last time we looked.  If so, the response also tells <<03021>>01550000
us how many array boards the system has, so we read and  clear <<03021>>01555000
the  logging  RAM  for  that many boards, updating the data in <<03021>>01560000
LOGREC as we go.                                               <<03021>>01565000
  The machine instruction used to perform all this useful work <<03021>>01570000
is the ICF/55 Message CoMmanD (MCMD) instruction, a doubleword <<03021>>01575000
instruction (%20104, 4).  It expects to find a doubleword mes- <<03021>>01580000
sage at S-2, S-1 and the message command word itself  on  TOS. <<03021>>01585000
During  execution,  the three stack items are deleted.  If the <<03021>>01590000
message requires a reply, MCMD pushes the doubleword reply on- <<03021>>01595000
to the stack.  If the reply is not received within 256 machine <<03021>>01600000
clocks, the instruction sets CCL and terminates.  The MCMD in- <<03021>>01605000
struction can be used to send and receive messages to or  from <<03021>>01610000
any of the hardware modules in the computer system.  We use it <<03021>>01615000
only to talk to the memory module.                             <<03021>>01620000
;                                                              <<03021>>01625000
INTEGER                                                        <<03021>>01630000
  ADDRESS,         << 7 LSB's of logging RAM address.       >> <<03021>>01635000
  BOARD'NUMBER,    << Array board number, also 3 MSB's of   >> <<03021>>01640000
                   <<   RAM address.                        >> <<03021>>01645000
  DATA'BIT;        << Loop var., controls exam of RAM data. >> <<03021>>01650000
                                                               <<03021>>01655000
LOGICAL                                                        <<03021>>01660000
  LOGGING'WORD,    << Hold logging RAM data (4 LSB's).      >> <<03021>>01665000
  MEM'STATUS;      << # array boards, single or multi-error >> <<03021>>01670000
                                                               <<03021>>01675000
DEFINE                                                         <<03021>>01680000
  MCMD           =ASSEMBLE (CON %20104; CON 4)#,               <<03021>>01685000
  MULTIPLE'ERROR =MEM'STATUS.(8:1)#,                           <<03021>>01690000
  SINGLE'ERROR   =MEM'STATUS.(9:1)#;                           <<03021>>01695000
                                                               <<03021>>01700000
<< See if any error, if so, how many boards do we have.     >> <<03021>>01705000
                                                               <<03021>>01710000
TOS := [7/0,                                                   <<03021>>01715000
        1/1,       << Read Status memory message.           >> <<03021>>01720000
        24/0] D;                                               <<03021>>01725000
TOS := [6/0,                                                   <<03021>>01730000
        4/%12,     << CSB bus op:  Send Word.               >> <<03021>>01735000
        3/7,       << CSB bus address of memory module.     >> <<03021>>01740000
        1/0,       << Ignore Busy bit -- clear.             >> <<03021>>01745000
        1/1,       << Busy Flag, must be set if Reply Expct >> <<03021>>01750000
        1/1];      << Reply Expected from memory.           >> <<03021>>01755000
MCMD;                                                          <<03021>>01760000
DELB;              << What we want is in least signif. word >> <<03021>>01765000
MEM'STATUS := TOS;                                             <<03021>>01770000
                                                               <<03021>>01775000
COMMENT -- The logging RAM is not cleared when the ICF/55  (or <<03021>>01780000
any  other model) is turned on.  To prevent the RAM's power-on <<03021>>01785000
contents from affecting the error counts, the RAM is read  and <<03021>>01790000
cleared when PROGEN launches us at system startup.  The global <<03021>>01795000
flag FIRST'TIME: 1) ensures that we execute the read-and-clear <<03021>>01800000
code even if MULTIPLE'ERROR and SINGLE'ERROR are clear, and 2) <<03021>>01805000
(externally) prevents the results from being  updated  to  the <<03021>>01810000
disc file (MEMLOG.PUB.SYS).                                    <<03021>>01815000
;                                                              <<03021>>01820000
IF MULTIPLE'ERROR OR SINGLE'ERROR OR FIRST'TIME THEN           <<03021>>01825000
   BEGIN   << Clear these flags but preserve others in ...  >> <<03021>>01830000
   TOS := MEM'STATUS LAND %77;     << ... (10:6).           >> <<03021>>01835000
   TOS := [10/0,                                               <<03021>>01840000
            1/1,     << Write Status memory message.        >> <<03021>>01845000
            5/0];                                              <<03021>>01850000
   ASSEMBLE (XCH);   << This completes doubleword message.  >> <<03021>>01855000
   TOS := [6/0,                                                <<03021>>01860000
           4/%12,  << CSB bus op:  Send Word.               >> <<03021>>01865000
           3/7,    << CSB bus address of memory module.     >> <<03021>>01870000
           3/0];   << All flags clear, no reply expected.   >> <<03021>>01875000
   MCMD;                                                       <<03021>>01880000
   IF LOGRECD (FERRTIME) = 0D THEN                             <<03021>>01885000
     FILLTIME (FERRTIME);   << Time when 1st error logged.  >> <<03021>>01890000
   FILLTIME (LERRTIME);   << Time most recent error logged. >> <<03021>>01895000
   FOR BOARD'NUMBER := 0 UNTIL INTEGER (MEM'STATUS.(5:3)) DO   <<03021>>01900000
     FOR ADDRESS := 0 UNTIL 127 DO                             <<03021>>01905000
      BEGIN   << Read and clear logging RAM.                >> <<03021>>01910000
      TOS := LOGICAL (BOARD'NUMBER) & LSL(11) LOR              <<03021>>01915000
        LOGICAL (ADDRESS) & LSL(4);                            <<03021>>01920000
      X := S0 & LSR(2);   << Address of LOGREC 4-tuple.     >> <<03021>>01925000
      ASSEMBLE (DUP);   << Here we go again.                >> <<03021>>01930000
      S1 :=  [8/0,                                             <<03021>>01935000
              1/1,    << Read Check memory message.         >> <<03021>>01940000
              2/0,                                             <<03021>>01945000
              1/1,    << Write Logging RAM memory message.  >> <<03021>>01950000
              4/0];                                            <<03021>>01955000
      TOS := [6/0,                                             <<03021>>01960000
              4/%12,  << CSB bus op:  Send Word.            >> <<03021>>01965000
              3/7,    << CSB bus address of memory module.  >> <<03021>>01970000
              1/0,    << Ignore Busy bit -- clear.          >> <<03021>>01975000
              1/1,    << Busy Flag, must be set if Rep Exp. >> <<03021>>01980000
              1/1];   << Reply Expected from memory.        >> <<03021>>01985000
      MCMD;                                                    <<03021>>01990000
      DELB;                                                    <<03021>>01995000
      IF (LOGGING'WORD := TOS).(12:4) <> 0 THEN                <<03021>>02000000
                                                               <<03021>>02005000
<< Error in this RAM word, update four assoc LOGREC entries >> <<03021>>02010000
                                                               <<03021>>02015000
        FOR DATA'BIT := 0 UNTIL 3 DO                           <<03021>>02020000
         BEGIN                                                 <<03021>>02025000
         IF LOGGING'WORD THEN LOGREC(X) := LOGREC(X) + 1;      <<03021>>02030000
         X := X + 1;                                           <<03021>>02035000
         LOGGING'WORD := LOGGING'WORD & LSR(1);                <<03021>>02040000
         END;   << of splitting logging RAM word.           >> <<03021>>02045000
      END;      << of one logging RAM address.              >> <<03021>>02050000
   END;         << of memory error logging.                 >> <<03021>>02055000
END;            << of FILLOGREC'ICF55.                      >> <<03021>>02060000
PROCEDURE FILLOGREC'MM(MEMBOARD);                              <<M8089>>02065000
VALUE MEMBOARD; INTEGER MEMBOARD;                              <<M8089>>02070000
BEGIN                                                          <<M8089>>02075000
INTEGER                                                        <<M8089>>02080000
  BIT'NUMBER,      BLOCK,          INDEX,                      <<M8089>>02085000
  SYNDROME;                                                    <<M8089>>02090000
                                                               <<M8089>>02095000
LOGICAL                                                        <<M8089>>02100000
  ERR'LATCH;                                                   <<M8089>>02105000
                                                               <<M8089>>02110000
EQUATE                                                         <<M8089>>02115000
  TABLE'SIZE = 39,                                             <<M8089>>02120000
  MULTIPLE'ERR = 39;                                           <<M8089>>02125000
                                                               <<M8089>>02130000
INTEGER ARRAY FAULT'TABLE(0:TABLE'SIZE-1)=PB :=                <<M8089>>02135000
  %014,          << DATA BIT 0   >>                            <<M8089>>02140000
  %254,          << DATA BIT 1   >>                            <<M8089>>02145000
  %264,          << DATA BIT 2   >>                            <<M8089>>02150000
  %324,          << DATA BIT 3   >>                            <<M8089>>02155000
  %024,          << DATA BIT 4   >>                            <<M8089>>02160000
  %344,          << DATA BIT 5   >>                            <<M8089>>02165000
  %44,           << DATA BIT 6   >>                            <<M8089>>02170000
  %104,          << DATA BIT 7   >>                            <<M8089>>02175000
  %72,           << DATA BIT 8   >>                            <<M8089>>02180000
  %132,          << DATA BIT 9   >>                            <<M8089>>02185000
  %232,          << DATA BIT 10  >>                            <<M8089>>02190000
  %152,          << DATA BIT 11  >>                            <<M8089>>02195000
  %252,          << DATA BIT 12  >>                            <<M8089>>02200000
  %312,          << DATA BIT 13  >>                            <<M8089>>02205000
  %162,          << DATA BIT 14  >>                            <<M8089>>02210000
  %322,          << DATA BIT 15  >>                            <<M8089>>02215000
  %216,          << DATA BIT 16  >>                            <<M8089>>02220000
  %56,           << DATA BIT 17  >>                            <<M8089>>02225000
  %66,           << DATA BIT 18  >>                            <<M8089>>02230000
  %126,          << DATA BIT 19  >>                            <<M8089>>02235000
  %226,          << DATA BIT 20  >>                            <<M8089>>02240000
  %146,          << DATA BIT 21  >>                            <<M8089>>02245000
  %246,          << DATA BIT 22  >>                            <<M8089>>02250000
  %306,          << DATA BIT 23  >>                            <<M8089>>02255000
  %270,          << DATA BIT 24  >>                            <<M8089>>02260000
  %330,          << DATA BIT 25  >>                            <<M8089>>02265000
  %30,           << DATA BIT 26  >>                            <<M8089>>02270000
  %350,          << DATA BIT 27  >>                            <<M8089>>02275000
  %50,           << DATA BIT 28  >>                            <<M8089>>02280000
  %110,          << DATA BIT 29  >>                            <<M8089>>02285000
  %360,          << DATA BIT 30  >>                            <<M8089>>02290000
  %120,          << DATA BIT 31  >>                            <<M8089>>02295000
  %176,          << CHECK BIT 0  >>                            <<M8089>>02300000
  %276,          << CHECK BIT 1  >>                            <<M8089>>02305000
  %336,          << CHECK BIT 2  >>                            <<M8089>>02310000
  %356,          << CHECK BIT 3  >>                            <<M8089>>02315000
  %366,          << CHECK BIT 4  >>                            <<M8089>>02320000
  %372,          << CHECK BIT 5  >>                            <<M8089>>02325000
  %374;          << CHECK BIT 6  >>                            <<M8089>>02330000
                                                               <<M8089>>02335000
  IF MEMBOARD = CONTROLLER'A THEN  TOS := %20000000001D  <<MOUSE>>      02340000
                             ELSE  TOS := %20000000003D; <<MOUSE>>      02345000
  MCS;                                                         <<M8089>>02350000
  ERR'LATCH := TOS;                                            <<M8089>>02355000
  IF ERR'LATCH THEN BLOCK := 0                                 <<M8089>>02360000
               ELSE BLOCK := 1;                                <<M8089>>02365000
  ERR'LATCH := ERR'LATCH LAND %376;                            <<M8089>>02370000
  SYNDROME := INTEGER(ERR'LATCH);                              <<M8089>>02375000
  IF SYNDROME <> %376 THEN                                     <<M8089>>02380000
    BEGIN                                                      <<M8089>>02385000
      IF LOGRECD(FERRTIME) = 0D THEN                           <<M8089>>02390000
        FILLTIME(FERRTIME);                                    <<M8089>>02395000
      FILLTIME(LERRTIME);                                      <<M8089>>02400000
      BIT'NUMBER := MULTIPLE'ERR;                              <<M8089>>02405000
      INDEX := 0;                                              <<M8089>>02410000
      WHILE INDEX <= TABLE'SIZE - 1 DO                         <<M8089>>02415000
        BEGIN                                                  <<M8089>>02420000
          IF FAULT'TABLE(INDEX) <> SYNDROME THEN               <<M8089>>02425000
            INDEX:= INDEX + 1                                  <<M8089>>02430000
          ELSE BEGIN                                           <<M8089>>02435000
                 BIT'NUMBER := INDEX;                          <<M8089>>02440000
                 INDEX := TABLE'SIZE;                          <<M8089>>02445000
               END;                                            <<M8089>>02450000
        END; << WHILE >>                                       <<M8089>>02455000
      IF BLOCK = 1 THEN                                        <<M8089>>02460000
        BIT'NUMBER := BIT'NUMBER + 40;                         <<M8089>>02465000
      LOGREC(BIT'NUMBER) := LOGREC(BIT'NUMBER) + 1;            <<M8089>>02470000
    END;                                                       <<M8089>>02475000
END; << FILLLOGREC'MM >>                                       <<M8089>>02480000
$PAGE                                                          <<03021>>02485000
                                                                        02490000
PROCEDURE UPDATE'MEMLOG(MEMBOARD);                                      02495000
VALUE MEMBOARD; INTEGER MEMBOARD;                                       02500000
BEGIN                                                                   02505000
                                                                        02510000
     SUBROUTINE FILLOGREC;                                              02515000
     BEGIN                                                              02520000
          TOS:=DRT;  <<WILL BE USED AS THE DRT FOR ALL I/O OPERATIONS>> 02525000
          TICKCNT:=0;  <<SOFTWARE TIMEOUT COUNT>>              <<00.01>>02530000
          DO   <<MAKE SURE LOGGING HARDWARE IS UP AND READY>>           02535000
          BEGIN                                                         02540000
               TESTIO;                                                  02545000
               IF < THEN ERRMESSAGE(3);  <<LOGGING WENT AWAY>>          02550000
               IF NOT (MEMREADY:=TOS.(1:1)) THEN               <<00.01>>02555000
               DELAY(DOUBLE(TIMEOUTICK));                      <<00.01>>02560000
          END UNTIL MEMREADY OR (TICKCNT:=TICKCNT+1) > TICKMAX;<<00.01>>02565000
          IF TICKCNT > TICKMAX THEN ERRMESSAGE(6);             <<00.01>>02570000
          TICKCNT:=0;  <<SOFTWARE TIMEOUT COUNT>>              <<00.01>>02575000
          TOS:=COPYLOG CAT MEMBOARD(5:15:1);                            02580000
          CONTROLIO;                                                    02585000
          IF < THEN ERRMESSAGE(4);                                      02590000
          DO   <<WAIT FOR READCOPY TO COMPLETE; CHECK FOR ERROR FLAG>>  02595000
          BEGIN                                                         02600000
               TESTIO;                                                  02605000
               IF < THEN ERRMESSAGE(3);                        <<00.01>>02610000
               ERRORFOUND:=S0.ERRBIT;                                   02615000
               IF NOT (MEMREADY:=TOS.(1:1)) THEN               <<00.01>>02620000
               DELAY(DOUBLE(TIMEOUTICK));                      <<00.01>>02625000
          END UNTIL MEMREADY OR (TICKCNT:=TICKCNT+1) > TICKMAX;<<00.01>>02630000
          IF TICKCNT > TICKMAX THEN ERRMESSAGE(6+MEMBOARD);    <<00.01>>02635000
          IF ERRORFOUND THEN  <<AT LEAST ONE MEMORY ERROR LOGGED>>      02640000
          BEGIN                                                         02645000
               IF LOGRECD(FERRTIME) = 0D THEN FILLTIME(FERRTIME);       02650000
               FILLTIME(LERRTIME);  <<TIME LAST ERROR LOGGED>>          02655000
               TOS:=SCANLOG CAT MEMBOARD(5:15:1);                       02660000
               CONTROLIO;                                               02665000
               SCANNING:=TRUE;                                          02670000
               WHILE SCANNING DO                                        02675000
               BEGIN                                                    02680000
                    READIO;                                             02685000
                    IF < THEN ERRMESSAGE(5);                            02690000
                    IF (SCANNING:=S0.SCANBIT) THEN  <<STILL SCANNING>>  02695000
                    LOGREC(X):=LOGREC(TOS.MEMADDR)+1 ELSE               02700000
                    DELETE;                                             02705000
               END;                                                     02710000
               CLEAR'LOG'BOARD(MEMBOARD);                               02715000
          END;                                                          02720000
          DELETE;  <<DELETE STACKED DRT>>                               02725000
     END <<FILLOGREC>>;                                                 02730000
                                                                        02735000
                                                               <<TP2MB>>02740000
     SUBROUTINE FILLOGREC'TP;                                  <<TP2MB>>02745000
     BEGIN                                                     <<TP2MB>>02750000
          LOW'ADDR := IF MEMBOARD=CONTROLLER'A THEN 0D         <<TP2MB>>02755000
                      ELSE %2000000D;                          <<TP2MB>>02760000
          HIGH'ADDR:= IF MEMBOARD=CONTROLLER'A THEN %1777777D  <<TP2MB>>02765000
                      ELSE %3777777D;                          <<TP2MB>>02770000
          ERRORFOUND := FALSE;                                 <<TP2MB>>02775000
          TOS := LOW'ADDR - %1000D;                            <<TP2MB>>02780000
          WHILE (TOS := TOS + %1000D) < HIGH'ADDR DO           <<TP2MB>>02785000
              BEGIN                                            <<TP2MB>>02790000
                   READ'LOG;       <<TOS.(14:2):=0>>           <<TP2MB>>02795000
                   MCS;                                        <<TP2MB>>02800000
                   GET'LOG'BIT;    <<LOG'BIT:=TOS.(8:1)>>      <<TP2MB>>02805000
                   CLEAR'LOG;      <<TOS.(14:2):=2>>           <<TP2MB>>02810000
                   MCS;                                        <<TP2MB>>02815000
                   DEL;            <<GET RID OF STATUS RETURN>><<RK.08>>02820000
                   IF LOG'BIT THEN                             <<TP2MB>>02825000
                   BEGIN                                       <<TP2MB>>02830000
                        ERRORFOUND := TRUE;                    <<TP2MB>>02835000
                        X := S1.(13:3)&LSL(7);                 <<TP2MB>>02840000
                        X := X + S0.(0:7);                     <<TP2MB>>02845000
                        LOGREC(X) := LOGREC(X) + 1;            <<TP2MB>>02850000
                   END;                                        <<TP2MB>>02855000
              END; <<END OF WHILE LOOP>>                       <<TP2MB>>02860000
          DDEL; <<GET RID OF LOOP VARIABLE>>                   <<TP2MB>>02865000
          IF ERRORFOUND THEN                                   <<TP2MB>>02870000
             BEGIN                                             <<TP2MB>>02875000
                  IF LOGRECD(FERRTIME) = 0D THEN               <<TP2MB>>02880000
                     FILLTIME(FERRTIME);                       <<TP2MB>>02885000
                  FILLTIME(LERRTIME); <<TIME LAST LOGGED>>     <<TP2MB>>02890000
             END;                                              <<TP2MB>>02895000
     END;  << OF FILLOGREC'TP>>                                <<TP2MB>>02900000
                                                               <<TP2MB>>02905000
                                                               <<01396>>02910000
     SUBROUTINE FILLOGREC'PRONTO;                              <<01396>>02915000
     BEGIN                                                     <<01396>>02920000
          LOW'ADDR := IF MEMBOARD=CONTROLLER'A THEN 0D         <<01396>>02925000
                      ELSE %4000000D;                          <<01396>>02930000
          HIGH'ADDR:= IF MEMBOARD=CONTROLLER'A THEN %3777777D  <<01396>>02935000
                      ELSE %7777777D;                          <<01396>>02940000
          ERRORFOUND := FALSE;                                 <<01396>>02945000
          TOS := LOW'ADDR - %400D;                             <<01487>>02950000
          WHILE (TOS := TOS + %400D) < HIGH'ADDR DO            <<01396>>02955000
              BEGIN                                            <<01396>>02960000
                   READ'LOG;       <<TOS.(14:2):=0>>           <<01396>>02965000
                   MCS;                                        <<01396>>02970000
                   GET'LOG'BIT;    <<LOG'BIT:=TOS.(8:1)>>      <<01396>>02975000
                   CLEAR'LOG;      <<TOS.(14:2):=2>>           <<01396>>02980000
                   MCS;                                        <<01396>>02985000
                   DEL;            <<GET RID OF STATUS RETURN>><<01396>>02990000
                   IF LOG'BIT THEN                             <<01396>>02995000
                   BEGIN                                       <<01396>>03000000
                        ERRORFOUND := TRUE;                    <<01396>>03005000
                        X := S1.(12:4)&LSL(7);                 <<01396>>03010000
                        X := X + S0.(0:7);                     <<01396>>03015000
                        X := X+X+S0.(7:1);                              03020000
                        LOGREC(X) := LOGREC(X) + 1;            <<01396>>03025000
                   END;                                        <<01396>>03030000
              END; <<END OF WHILE LOOP>>                       <<01396>>03035000
          DDEL; <<GET RID OF LOOP VARIABLE>>                   <<01396>>03040000
          IF ERRORFOUND THEN                                   <<01396>>03045000
             BEGIN                                             <<01396>>03050000
                  IF LOGRECD(FERRTIME) = 0D THEN               <<01396>>03055000
                     FILLTIME(FERRTIME);                       <<01396>>03060000
                  FILLTIME(LERRTIME); <<TIME LAST LOGGED>>     <<01396>>03065000
             END;                                              <<01396>>03070000
     END;  << OF FILLOGREC'PRONTO>>                            <<03021>>03075000
                                                               <<01396>>03080000
     RECNUM:=DOUBLE(MEMBOARD);                                          03085000
     FREADDIR(FNUM,LOGREC,RECSIZE,RECNUM);                              03090000
     IF < THEN ERRMESSAGE(FSERR);                                       03095000
     FILLTIME(LASTIME);  <<INSERT START AND UPDATE TIMES INTO RECORD>>  03100000
     LOGREC(DELAYLOC):=DTIME;                                           03105000
                                                               <<03021>>03110000
<< Following FWRITEDIR posts initial DTIME (3600)  to  disc >> <<03021>>03115000
<< in  case  it  was changed by MEMTIMER during last run of >> <<03021>>03120000
<< system. This insures that MEMLOGAN reports proper DTIME. >> <<03021>>03125000
                                                               <<03021>>03130000
     IF FIRST'TIME THEN                                        <<03021>>03135000
       FWRITEDIR (FNUM, LOGREC, RECSIZE, RECNUM);              <<03021>>03140000
     CASE  CPU'TYPE  OF                                                 03145000
      BEGIN                                                             03150000
       FILLOGREC;                                                       03155000
       FILLOGREC;                                                       03160000
       FILLOGREC'TP;                                                    03165000
       FILLOGREC;                                                       03170000
       FILLOGREC'PRONTO;                                                03175000
       FILLOGREC'ICF55;                                        <<03021>>03180000
       FILLOGREC'MM(MEMBOARD);                                 <<M8089>>03185000
      END;                                                              03190000
     IF NOT FIRST'TIME THEN  <<IGNORE FIRST TIME ERRORS>>      <<00684>>03195000
       BEGIN                                                   <<00684>>03200000
         FWRITEDIR(FNUM,LOGREC,RECSIZE,RECNUM);                <<00684>>03205000
         IF <> THEN ERRMESSAGE(FSERR);                         <<00684>>03210000
       END;                                                    <<00684>>03215000
END << UPDATE'MEMLOG >>;                                                03220000
                                                                        03225000
     CPU'TYPE:=THISCPU;                                        <<TP2MB>>03230000
     IF CPU'TYPE=2 <<TP>> OR CPU'TYPE=4 <<GRIZLY>>             <<01396>>03235000
      THEN                                                     <<01396>>03240000
       BEGIN                                                            03245000
                                                                        03250000
        IF BANKNUM >= NEXT'CONTROLLER(4)                       <<01487>>03255000
         THEN TOS := %4000000D                                 <<01487>>03260000
         ELSE TOS := %0D;                                      <<01487>>03265000
        MCS;                                                   <<01396>>03270000
        IF 8<=S0.(12:4)<=9 THEN CPU'TYPE := 4 << PRONTO MEM >> <<01418>>03275000
         ELSE CPU'TYPE := 2;  << AMIGO MEMORY >>               <<01418>>03280000
        IF TOS.(15:1)= 0 THEN NEXT'CONTROLLER(4):="NO";        <<01396>>03285000
           << ELSE NEXT'CNTLR(4) := 16 >>                      <<01487>>03290000
        DDELETE;                                               <<01396>>03295000
       END;                                                    <<01396>>03300000
     IF CPU'TYPE=1 OR CPU'TYPE=3 THEN <<SERIES II OR 2MB>>     <<TP2MB>>03305000
     CHECKFORLOGGING;                                                   03310000
     IF CPU'TYPE=6 THEN                                        <<M8089>>03315000
       BEGIN                                                   <<M8089>>03320000
         DTIME := 600;                                         <<M8089>>03325000
         IF BANKNUM >= 8 THEN NEXT'CONTROLLER(6) := 16;        <<M8089>>03330000
       END;                                                    <<M8089>>03335000
     OPEN'MEMLOG;                                                       03340000
     WHILE TRUE DO                                                      03345000
     BEGIN                                                              03350000
          FLOCK(FNUM,1);                                                03355000
          IF < THEN ERRMESSAGE(1);                                      03360000
          UPDATE'MEMLOG(CONTROLLER'A);                         <<TP2MB>>03365000
          IF BANKNUM >= NEXT'CONTROLLER(CPU'TYPE) THEN         <<TP2MB>>03370000
          UPDATE'MEMLOG(CONTROLLER'B);                         <<TP2MB>>03375000
          FUNLOCK(FNUM);                                                03380000
          IF < THEN ERRMESSAGE(2);                                      03385000
          FIRST'TIME:=FALSE;                                   <<00684>>03390000
          IF SHUTDOWN THEN                                              03395000
          BEGIN                                                         03400000
               FCLOSE(FNUM,1,0);                                        03405000
               IF < THEN ERRMESSAGE(FSERR);                             03410000
               AWAKE(ABSOLUTE(PROGENPINX),2,%4000);                     03415000
          END ELSE                                                      03420000
          BEGIN                                                         03425000
               IF NOT ABSOLUTE(SYSUP) THEN  <<PROGEN WAITING>>          03430000
               AWAKE(ABSOLUTE(PROGENPINX),2,0);                         03435000
               DELAYTIME:=DOUBLE(INTEGER(DTIME)) * 1000D;      <<00.02>>03440000
               DELAY(DELAYTIME);                                        03445000
          END;                                                          03450000
     END;                                                               03455000
END.                                                                    03460000
