$CONTROL MAP,CODE,USLINIT                                               00010000
<<MEMLOGP - MODULE 11>>                                                 00012000
<< HP32002C MPE SOURCE C.00.00 >>                                       00014000
$COPYRIGHT     "(C) COPYRIGHT HEWLETT-PACKARD CO. 1980. ",            & 00016000
$     "THIS PROGRAM MAY BE USED WITH ONE COMPUTER SYSTEM AT A ",      & 00018000
$     "TIME AND SHALL NOT OTHERWISE BE RECORDED, TRANSMITTED OR ",    & 00020000
$     "STORED IN A RETRIEVAL SYSTEM.  COPYING OR OTHER REPRODUCTION ",& 00022000
$     "OF THIS PROGRAM EXCEPT FOR ARCHIVAL PURPOSES IS PROHIBITED ",  & 00024000
$     "WITHOUT THE PRIOR WRITTEN CONSENT OF HEWLETT-PACKARD COMPANY."   00026000
$CONTROL MAIN=MEMLOGP,SEGMENT=MEMLOGP                                   00028000
$CONTROL PRIVILEGED                                                     00030000
$CONTROL UNCALLABLE                                                     00032000
$TITLE "- ERROR CORRECTING MEMORY LOGGING PROCESS"                      00034000
$THIRTY                                                                 00036000
BEGIN                                                                   00038000
                                                                        00040000
<<------------------------------------------------------------          00042000
*                                                            *          00044000
*         ERROR CORRECTING MEMORY LOGGING PROCESS            *          00046000
*                                                            *          00048000
------------------------------------------------------------>>          00050000
                                                                        00052000
INTEGER X = X;                                                          00054000
                                                                        00056000
INTEGER S0 = S-0;                                                       00058000
INTEGER S1 = S-1;                                              <<TP2MB>>00060000
                                                                        00062000
LOGICAL DTIME:=3600;  <<MUST BE AT DB+0 - INITIALIZED TO 1 HOUR>>       00064000
                                                                        00066000
INTEGER ERR,FNUM,TICKCNT;                                      <<00.01>>00068000
                                                                        00070000
LOGICAL MEMREADY,FOPTIONS,SCANNING,ERRORFOUND;                 <<00.01>>00072000
                                                                        00074000
DOUBLE RECNUM,DELAYTIME;                                                00076000
                                                                        00078000
DOUBLE LOW'ADDR,HIGH'ADDR;                                     <<TP2MB>>00080000
                                                               <<TP2MB>>00082000
DOUBLE INCREMENT;                                              <<01396>>00084000
                                                               <<01396>>00086000
LOGICAL LOG'BIT;                                               <<TP2MB>>00088000
                                                               <<TP2MB>>00090000
INTEGER CPU'TYPE;                                              <<TP2MB>>00092000
                                                               <<TP2MB>>00094000
INTEGER ARRAY NEXT'CONTROLLER(1:5) := 2, 8, 8, 16, %77777;     <<03021>>00096000
                                                               <<TP2MB>>00098000
LOGICAL FIRST'TIME:=TRUE;  <<TRUE ON FIRST ACTIVATION ONLY>>   <<00684>>00100000
EQUATE RECSIZE  =  4112;  <<MEMLOG RECORD SIZE: 2048 WORDS LOG SIZE +   00102000
                            STARTIME(DBL) + LASTIME(DBL) +              00104000
                            FERRTIME(DBL) + LAERRTIME(DBL) + EXTRA >>   00106000
                                                               <<00.06>>00108000
DEFINE FILESIZE =   2D#;  <<MEMLOG FILE SIZE: 2 LOGICAL RECS>> <<00.06>>00110000
                                                               <<00.06>>00112000
ARRAY LOGREC(0:RECSIZE-1);                                              00114000
DOUBLE ARRAY LOGRECD(*) = LOGREC;                                       00116000
                                                               <<00.05>>00118000
                                                                        00120000
EQUATE                                                                  00122000
     DRT      =     2,  <<ERROR CORRECTING MEMORY DRT>>                 00124000
     SYSDB    =   512,  <<SYSTEM DB OFFSET>>                            00126000
     FSERR    =     0,  <<FILE SYSTEM ERROR>>                           00128000
     NOFILE   =    52,  <<FILE SYSTEM ERROR>>                           00130000
     FILECODE = -1234;                                                  00132000
                                                                        00134000
EQUATE << MEMORY ERROR LOGGING MESSAGE CATALOG NUMBERS >>               00136000
     MEMLOGMSG1 = 248,  <<LOGGING INITIATED>>                           00138000
     MEMLOGMSG2 = 249;  <<LOGGING ERROR MESSAGE>>                       00140000
                                                                        00142000
EQUATE << LOG RECORD LOCATIONS >>                                       00144000
     STARTIME  =  2048, <<DOUBLE LOCATION>>                    <<01396>>00146000
     LASTIME   =  2049, <<DOUBLE LOCATION>>                    <<01396>>00148000
     FERRTIME  =  2050, <<DOUBLE LOCATION>>                    <<01396>>00150000
     LERRTIME  =  2051, <<DOUBLE LOCATION>>                    <<01396>>00152000
     BANKNUMB  = 4104,                                         <<01396>>00154000
     DELAYLOC  = 4105;                                         <<01396>>00156000
                                                                        00158000
EQUATE  << SYSTEB DB LOCATIONS >>                                       00160000
     MEMBANKNUM = SYSDB+%47,   <<NUMBER  OF MEMORY BANKS>>              00162000
     SYSUP      = SYSDB+%73,   <<SYSTEM UP FLAG>>                       00164000
     PROGENPINX = SYSDB+%141,  <<PROGEN PCB INDEX>>                     00166000
     MEMLOGPINX = SYSDB+%154,  <<MEMLOGP PCB INDEX>>                    00168000
     STOPBITS   = SYSDB+%300;  <<SHUTDOWN STOP BITS>>                   00170000
                                                                        00172000
EQUATE  << DIRECT I/O TOS VALUES >>                                     00174000
     COPYLOG     = %020000,  <<COPY CONTENTS OF ELA INTO IOLA>>         00176000
     MASTERCLEAR = %100000,  <<CLEAR BOARD AFTER TIMEOUT>>     <<TP2MB>>00178000
     SCANLOG     = %010000,  <<SCAN IOLA FOR ERRORS RECORDED BY ELA>>   00180000
     CLEAR'IOLA  = %010000,  <<FILL IOLA WITH CONTENTS OF BIT 0>>       00182000
     CLEAR'ELA   = %020000;  <<COPY CONTENTS OF IOLA INTO ELA>>         00184000
                                                                        00186000
EQUATE  << MEMORY BOARDS - UPPER AND LOWER 128K>>                       00188000
     CONTROLLER'A = 0,                                         <<TP2MB>>00190000
     CONTROLLER'B = 1;                                         <<TP2MB>>00192000
                                                                        00194000
EQUATE  << SOFTWARE-TIO TIMEOUT PARAMETERS >>                  <<00.01>>00196000
     TICKMAX    =   3,  <<NUMBER OF DELAYS UNTIL TIMEOUT>>     <<00.01>>00198000
     TIMEOUTICK = 100;  <<TIMEOUT DELAY (IN MILLESECONDS)>>    <<00.01>>00200000
                                                               <<00.01>>00202000
DEFINE  << PARTIAL FIELDS >>                                            00204000
     ERRBIT   = ( 7: 1)#,                                               00206000
     SCANBIT  = ( 3: 1)#,                                               00208000
     MEMADDR  = ( 6:10)#;                                               00210000
                                                                        00212000
DEFINE  << DIRECT I/O FUNCTIONS >>                                      00214000
     TESTIO     = ASSEMBLE(TIO 0)#,                                     00216000
     READIO     = ASSEMBLE(RIO;BLE *+3;DEL;BR *-3)#,                    00218000
     WRITEIO    = ASSEMBLE(WIO 1;BLE *+3;DEL;BR *-3)#,                  00220000
     CONTROLIO  = ASSEMBLE(CIO 1)#;                                     00222000
                                                                        00224000
DEFINE << TP FUNCTIONS >>                                      <<TP2MB>>00226000
     READ'LOG     = TOS.(14:2):=0#,                            <<TP2MB>>00228000
     CLEAR'LOG    = TOS.(14:2):=2#,                            <<TP2MB>>00230000
     GET'LOG'BIT  = LOG'BIT:=TOS.(8:1)#,                       <<TP2MB>>00232000
     MCS          = ASSEMBLE(CON %020302;CON 7)#;              <<TP2MB>>00234000
                                                               <<TP2MB>>00236000
                                                               <<00.01>>00238000
DEFINE SHUTDOWN = LOGICAL(ABSOLUTE(STOPBITS).(4:1))#;          <<00.02>>00240000
DEFINE BANKNUM  = ABSOLUTE(MEMBANKNUM)#;                                00242000
                                                                        00244000
DEFINE DELETE = ASSEMBLE(DEL)#;                                         00246000
DEFINE DDELETE = ASSEMBLE(DEL,DEL)#;                                    00248000
DEFINE DUPLICATE = ASSEMBLE(DUP)#;                                      00250000
DEFINE DDUPLICATE = ASSEMBLE(DDUP)#;                                    00252000
                                                                        00254000
DEFINE CHECKFORLOGGING =                                                00256000
     BEGIN; TOS:=DRT;                                          <<RK.08>>00258000
     ASSEMBLE(TIO 0);                                                   00260000
     IF < THEN AWAKE(ABSOLUTE(PROGENPINX),2,%4000);                     00262000
     DDELETE; END#;                                            <<RK.08>>00264000
                                                                        00266000
INTRINSIC FOPEN,FCLOSE,FREAD,FREADDIR,FWRITE,FWRITEDIR,FCHECK,          00268000
          FGETINFO,FLOCK,FUNLOCK;                              <<01396>>00270000
INTRINSIC ASCII,CLOCK,CALENDAR,TERMINATE;                               00272000
                                                                        00274000
INTEGER PROCEDURE GENMSG(SETNO,MSGNO,MASK,A,B,C,D,E,           <<0U.EB>>00276000
      DEST,REPLY,BUFF,DST,IOTYPE);                             <<0U.EB>>00278000
   VALUE SETNO,MSGNO,MASK,A,B,C,D,E,DEST,REPLY,BUFF,           <<0U.EB>>00280000
      DST,IOTYPE;                                              <<0U.EB>>00282000
   LOGICAL SETNO,MSGNO,MASK,A,B,C,D,E,DEST,REPLY,BUFF,         <<0U.EB>>00284000
      DST,IOTYPE;                                              <<0U.EB>>00286000
   OPTION VARIABLE,EXTERNAL;                                   <<0U.EB>>00288000
                                                               <<0U.EB>>00290000
                                                                        00292000
PROCEDURE AWAKE(P,A,W);                                                 00294000
 VALUE P,A,W;                                                           00296000
 INTEGER P,A,W;                                                         00298000
 OPTION EXTERNAL;                                                       00300000
                                                                        00302000
PROCEDURE DELAY(T);                                                     00304000
 VALUE T;                                                               00306000
 DOUBLE T;                                                              00308000
 OPTION EXTERNAL;                                                       00310000
                                                                        00312000
PROCEDURE WAIT(W,D);                                           <<00.01>>00314000
 VALUE W,D;                                                    <<00.01>>00316000
 INTEGER W,D;                                                  <<00.01>>00318000
 OPTION EXTERNAL;                                              <<00.01>>00320000
                                                               <<00.01>>00322000
INTEGER PROCEDURE THISCPU;                                     <<TP2MB>>00324000
OPTION EXTERNAL;                                               <<TP2MB>>00326000
                                                               <<TP2MB>>00328000
PROCEDURE HELP;                                                         00330000
 OPTION EXTERNAL;                                                       00332000
                                                                        00334000
PROCEDURE ERRMESSAGE(ERRNUMB);                                          00336000
VALUE ERRNUMB;                                                          00338000
INTEGER ERRNUMB;                                                        00340000
BEGIN                                                                   00342000
     INTEGER ERROR;                                                     00344000
                                                                        00346000
     IF ERRNUMB = FSERR THEN FCHECK(FNUM,ERROR) ELSE ERROR:=ERRNUMB;;   00348000
     GENMSG(1,249,%10000,ERROR,,,,,0);                         <<0U.EB>>00350000
     FUNLOCK(FNUM);  <<MAKE SURE MEMLOGAN WILL RUN>>           <<00.07>>00352000
     IF ABSOLUTE(SYSUP) THEN                                   <<00.01>>00354000
        WAIT(%4000,0)                                          <<00.01>>00356000
     ELSE                                                      <<00.01>>00358000
        AWAKE(ABSOLUTE(PROGENPINX),2,%4000);                   <<00.01>>00360000
END <<ERRMESSAGE>>;                                                     00362000
                                                                        00364000
PROCEDURE CLEAR'LOG'BOARD(MEMBOARD);                                    00366000
VALUE MEMBOARD; INTEGER MEMBOARD;                                       00368000
BEGIN                                                                   00370000
     TOS:=DRT;                                                          00372000
     TOS:=CLEAR'IOLA;                                                   00374000
     WRITEIO;                                                           00376000
     TOS:=CLEAR'ELA CAT MEMBOARD(5:15:1);                               00378000
     WRITEIO;                                                           00380000
END << CLEAR'LOG'BOARD >>;                                              00382000
                                                                        00384000
PROCEDURE OPEN'MEMLOG;                                                  00386000
BEGIN                                                                   00388000
     INTEGER REC;                                              <<00.03>>00390000
     INTEGER FG'RSIZE;     << REC SIZE FROM FGETINFO >>        <<01396>>00392000
     BYTE ARRAY FNAME (0:15);                                  <<03021>>00394000
                                                               <<00.05>>00396000
     FNUM:=0;  <<ASSUME NO MEMLOG FILE FOUND>>                          00398000
     FOPTIONS:=%2001;                                                   00400000
     MOVE FNAME := "MEMLOG.PUB.SYS ";                          <<03021>>00402000
     WHILE FNUM = 0 DO                                                  00404000
     BEGIN                                                              00406000
          FNUM:=FOPEN(FNAME,FOPTIONS,%744,RECSIZE,,,,,,        <<00.06>>00408000
                      FILESIZE,,,FILECODE);                    <<00.06>>00410000
          IF <> THEN  <<FOPEN ERROR>>                                   00412000
          BEGIN                                                         00414000
               FCHECK(FNUM,ERR);                                        00416000
               IF ERR <> NOFILE THEN ERRMESSAGE(ERR);                   00418000
          END ELSE                                             <<03021>>00420000
          BEGIN                                                <<03021>>00422000
          FGETINFO(FNUM,,,,FG'RSIZE);                          <<01396>>00424000
          IF FG'RSIZE <> RECSIZE                               <<01396>>00426000
            THEN                                               <<01396>>00428000
            BEGIN                                              <<01396>>00430000
            FCLOSE(FNUM,4,0);                                  <<01396>>00432000
            FNUM := 0;                                         <<01396>>00434000
            END;                                               <<01396>>00436000
          END;                                                 <<03021>>00438000
          IF NOT FOPTIONS THEN  <<JUST FOPEN-ED NEW>>                   00440000
          BEGIN                                                         00442000
               LOGREC:=0; MOVE LOGREC(1):=LOGREC,(RECSIZE-1);  <<00.03>>00444000
               FOR REC:=0 UNTIL INTEGER (FILESIZE-1D) DO       <<03070>>00446000
               BEGIN   << Initialize log file.              >> <<03021>>00448000
                    FWRITEDIR(FNUM,LOGREC,RECSIZE,DOUBLE(REC));<<00.03>>00450000
                    IF <> THEN ERRMESSAGE(FSERR);              <<00.03>>00452000
               END;                                            <<00.03>>00454000
               FCLOSE(FNUM,1,0);                               <<01396>>00456000
               IF < THEN ERRMESSAGE(FSERR);                             00458000
               FNUM:=0; <<WILL CAUSE FINAL OPEN ATTEMPT>>               00460000
          END;                                                          00462000
          FOPTIONS.(15:1):=(FOPTIONS.(15:1)+1);                         00464000
     END;                                                               00466000
END << OPEN'MEMLOG >>;                                                  00468000
$PAGE                                                          <<03021>>00470000
PROCEDURE FILLTIME(TIMELOC);                                   <<03021>>00472000
VALUE TIMELOC; INTEGER TIMELOC;                                <<03021>>00474000
BEGIN                                                          <<03021>>00476000
     TOS:=CALENDAR;                                            <<03021>>00478000
     TOS:=CLOCK;                                               <<03021>>00480000
     DELETE;  <<DELETE SECONDS INFO.>>                         <<03021>>00482000
     IF LOGRECD(STARTIME) = 0D THEN                            <<03021>>00484000
     BEGIN                                                     <<03021>>00486000
          DDUPLICATE;                                          <<03021>>00488000
          LOGRECD(STARTIME):=TOS;  <<RECORD START TIME>>       <<03021>>00490000
          LOGRECD(FERRTIME):=0D;                               <<03021>>00492000
          LOGRECD(LERRTIME):=0D;                               <<03021>>00494000
          LOGREC(BANKNUMB):=BANKNUM;  <<NO. OF MEM BANKS>>     <<03021>>00496000
          LOGREC:=0; MOVE LOGREC(1):=LOGREC,(4095);            <<03021>>00498000
     END;                                                      <<03021>>00500000
     LOGRECD(TIMELOC):=TOS;  <<RECORD TIME>>                   <<03021>>00502000
END <<FILLTIME>>;                                              <<03021>>00504000
$PAGE                                                          <<03021>>00506000
PROCEDURE FILLOGREC'ICF55;                                     <<03021>>00508000
                                                               <<03021>>00510000
BEGIN COMMENT                                                  <<03021>>00512000
  This procedure reads the ICF/55 memory error logging RAM and <<03021>>00514000
updates the error counters in the LOGREC array for later  pro- <<03021>>00516000
cessing by MEMLOGAN. The first 4096 locations in LOGREC repre- <<03021>>00518000
sent 1248 possible chip addresses (156 chips on each of up  to <<03021>>00520000
8  memory array boards) (see below).  The unused locations are <<03021>>00522000
set to 0 and are not examined.  The 1248 addresses  which  are <<03021>>00524000
used  (not  necessarily the first 1248 in LOGREC) each contain <<03021>>00526000
an error count, or a count of the number of times an error has <<03021>>00528000
been recorded for that particular chip.  Note that the  counts <<03021>>00530000
are  increased  at  most by 1, even though more than one error <<03021>>00532000
may have occurred since the last time MEMLOGP  was  activated. <<03021>>00534000
This  is  because the logging RAM only knows that at least one <<03021>>00536000
error occurred.                                                <<03021>>00538000
  The ICF/55 (CPU'TYPE = 5) memory is the first to use a  1024 <<03021>>00540000
x 4 error logging RAM.  Previous memories have all used a 4096 <<03021>>00542000
x 1 RAM.  The mapping of the error logging RAM to  the  LOGREC <<03021>>00544000
array is shown below:                                          <<03021>>00546000
                                                               <<03021>>00548000
               LOGREC ADDRESS (12 BITS) (0:4095)               <<03021>>00550000
                                                               <<03021>>00552000
  ERROR LOGGING RAM ADDRESS (10 BITS)  |                       <<03021>>00554000
                                       |                       <<03021>>00556000
  ARRAY   |MEMORY  |       OTHER       |     ERROR LOGGING     <<03021>>00558000
 (BOARD)  | WORD   |      ADDRESS      |       RAM DATA        <<03021>>00560000
 ADDRESS  |ADDRESS |       BITS        | (4 INDEPENDENT BITS)  <<03021>>00562000
 ---------+--------+-------------------+---------------------  <<03021>>00564000
 | 0  1  2|  3   4 |  5   6   7   8   9| 10  11|               <<03021>>00566000
                                                               <<03021>>00568000
  Each time the RAM is accessed (using the  leftmost  10  bits <<03021>>00570000
above  as its address), it returns the 4 data bits at that ad- <<03021>>00572000
dress. These are independent (non-encoded) bits, that is, they <<03021>>00574000
individually represent the error state of  a  memory  data  or <<03021>>00576000
check  bit.  A "1" represents one or more errors since the RAM <<03021>>00578000
was last read and cleared, a "0" means no errors have occurred <<03021>>00580000
during that interval.                                          <<03021>>00582000
  ICF/55 memory is organized as one  to  eight  array  boards, <<03021>>00584000
each containing 4 "words". Each word consists of 39 RAMS, each <<03021>>00586000
either 1 x 16K or 1 x 64K.  A cross-sectional slice of 39 bits <<03021>>00588000
represents one 32-bit data word and seven  check  bits.  Since <<03021>>00590000
the  rest of the machine understands 16-bit words, each 32-bit <<03021>>00592000
word must be unpacked when read and re-packed when written. In <<03021>>00594000
addition, any memory write must actually consist  of  a  read- <<03021>>00596000
modify-write  cycle to protect the 16 bits which are not being <<03021>>00598000
changed.  The seven check bits are used to detect  all  memory <<03021>>00600000
errors,  and additionally correct all single-bit errors.  Thus <<03021>>00602000
one memory array board contains either 256K bytes  (16K  RAMS) <<03021>>00604000
or  1M byte (64K RAMS).  Since MEMLOGP and MEMLOGAN only iden- <<03021>>00606000
tify errors to the chip level, we don't  really  care  whether <<03021>>00608000
the chips have 16K or 64K bits.                                <<03021>>00610000
  A closer examination shows that 2 word bits +  5  other  ad- <<03021>>00612000
dress bits + 2 bits representing the encoded data bits can en- <<03021>>00614000
code 2**9 = 512 chip addresses per board. Since there are only <<03021>>00616000
4 x 39 = 156 chips per board, there will be a  lot  of  unused <<03021>>00618000
area in the logging RAM.  This is called expandability.        <<03021>>00620000
  Now that we've covered organization we'll examine  ways  and <<03021>>00622000
means.  FILLOGREC'ICF55  first  asks  if there's been an error <<03021>>00624000
since the last time we looked.  If so, the response also tells <<03021>>00626000
us how many array boards the system has, so we read and  clear <<03021>>00628000
the  logging  RAM  for  that many boards, updating the data in <<03021>>00630000
LOGREC as we go.                                               <<03021>>00632000
  The machine instruction used to perform all this useful work <<03021>>00634000
is the ICF/55 Message CoMmanD (MCMD) instruction, a doubleword <<03021>>00636000
instruction (%20104, 4).  It expects to find a doubleword mes- <<03021>>00638000
sage at S-2, S-1 and the message command word itself  on  TOS. <<03021>>00640000
During  execution,  the three stack items are deleted.  If the <<03021>>00642000
message requires a reply, MCMD pushes the doubleword reply on- <<03021>>00644000
to the stack.  If the reply is not received within 256 machine <<03021>>00646000
clocks, the instruction sets CCL and terminates.  The MCMD in- <<03021>>00648000
struction can be used to send and receive messages to or  from <<03021>>00650000
any of the hardware modules in the computer system.  We use it <<03021>>00652000
only to talk to the memory module.                             <<03021>>00654000
;                                                              <<03021>>00656000
INTEGER                                                        <<03021>>00658000
  ADDRESS,         << 7 LSB's of logging RAM address.       >> <<03021>>00660000
  BOARD'NUMBER,    << Array board number, also 3 MSB's of   >> <<03021>>00662000
                   <<   RAM address.                        >> <<03021>>00664000
  DATA'BIT;        << Loop var., controls exam of RAM data. >> <<03021>>00666000
                                                               <<03021>>00668000
LOGICAL                                                        <<03021>>00670000
  LOGGING'WORD,    << Hold logging RAM data (4 LSB's).      >> <<03021>>00672000
  MEM'STATUS;      << # array boards, single or multi-error >> <<03021>>00674000
                                                               <<03021>>00676000
DEFINE                                                         <<03021>>00678000
  MCMD           =ASSEMBLE (CON %20104; CON 4)#,               <<03021>>00680000
  MULTIPLE'ERROR =MEM'STATUS.(8:1)#,                           <<03021>>00682000
  SINGLE'ERROR   =MEM'STATUS.(9:1)#;                           <<03021>>00684000
                                                               <<03021>>00686000
<< See if any error, if so, how many boards do we have.     >> <<03021>>00688000
                                                               <<03021>>00690000
TOS := [7/0,                                                   <<03021>>00692000
        1/1,       << Read Status memory message.           >> <<03021>>00694000
        24/0] D;                                               <<03021>>00696000
TOS := [6/0,                                                   <<03021>>00698000
        4/%12,     << CSB bus op:  Send Word.               >> <<03021>>00700000
        3/7,       << CSB bus address of memory module.     >> <<03021>>00702000
        1/0,       << Ignore Busy bit -- clear.             >> <<03021>>00704000
        1/1,       << Busy Flag, must be set if Reply Expct >> <<03021>>00706000
        1/1];      << Reply Expected from memory.           >> <<03021>>00708000
MCMD;                                                          <<03021>>00710000
DELB;              << What we want is in least signif. word >> <<03021>>00712000
MEM'STATUS := TOS;                                             <<03021>>00714000
                                                               <<03021>>00716000
COMMENT -- The logging RAM is not cleared when the ICF/55  (or <<03021>>00718000
any  other model) is turned on.  To prevent the RAM's power-on <<03021>>00720000
contents from affecting the error counts, the RAM is read  and <<03021>>00722000
cleared when PROGEN launches us at system startup.  The global <<03021>>00724000
flag FIRST'TIME: 1) ensures that we execute the read-and-clear <<03021>>00726000
code even if MULTIPLE'ERROR and SINGLE'ERROR are clear, and 2) <<03021>>00728000
(externally) prevents the results from being  updated  to  the <<03021>>00730000
disc file (MEMLOG.PUB.SYS).                                    <<03021>>00732000
;                                                              <<03021>>00734000
IF MULTIPLE'ERROR OR SINGLE'ERROR OR FIRST'TIME THEN           <<03021>>00736000
   BEGIN   << Clear these flags but preserve others in ...  >> <<03021>>00738000
   TOS := MEM'STATUS LAND %77;     << ... (10:6).           >> <<03021>>00740000
   TOS := [10/0,                                               <<03021>>00742000
            1/1,     << Write Status memory message.        >> <<03021>>00744000
            5/0];                                              <<03021>>00746000
   ASSEMBLE (XCH);   << This completes doubleword message.  >> <<03021>>00748000
   TOS := [6/0,                                                <<03021>>00750000
           4/%12,  << CSB bus op:  Send Word.               >> <<03021>>00752000
           3/7,    << CSB bus address of memory module.     >> <<03021>>00754000
           3/0];   << All flags clear, no reply expected.   >> <<03021>>00756000
   MCMD;                                                       <<03021>>00758000
   IF LOGRECD (FERRTIME) = 0D THEN                             <<03021>>00760000
     FILLTIME (FERRTIME);   << Time when 1st error logged.  >> <<03021>>00762000
   FILLTIME (LERRTIME);   << Time most recent error logged. >> <<03021>>00764000
   FOR BOARD'NUMBER := 0 UNTIL INTEGER (MEM'STATUS.(5:3)) DO   <<03021>>00766000
     FOR ADDRESS := 0 UNTIL 127 DO                             <<03021>>00768000
      BEGIN   << Read and clear logging RAM.                >> <<03021>>00770000
      TOS := LOGICAL (BOARD'NUMBER) & LSL(11) LOR              <<03021>>00772000
        LOGICAL (ADDRESS) & LSL(4);                            <<03021>>00774000
      X := S0 & LSR(2);   << Address of LOGREC 4-tuple.     >> <<03021>>00776000
      ASSEMBLE (DUP);   << Here we go again.                >> <<03021>>00778000
      S1 :=  [8/0,                                             <<03021>>00780000
              1/1,    << Read Check memory message.         >> <<03021>>00782000
              2/0,                                             <<03021>>00784000
              1/1,    << Write Logging RAM memory message.  >> <<03021>>00786000
              4/0];                                            <<03021>>00788000
      TOS := [6/0,                                             <<03021>>00790000
              4/%12,  << CSB bus op:  Send Word.            >> <<03021>>00792000
              3/7,    << CSB bus address of memory module.  >> <<03021>>00794000
              1/0,    << Ignore Busy bit -- clear.          >> <<03021>>00796000
              1/1,    << Busy Flag, must be set if Rep Exp. >> <<03021>>00798000
              1/1];   << Reply Expected from memory.        >> <<03021>>00800000
      MCMD;                                                    <<03021>>00802000
      DELB;                                                    <<03021>>00804000
      IF (LOGGING'WORD := TOS).(12:4) <> 0 THEN                <<03021>>00806000
                                                               <<03021>>00808000
<< Error in this RAM word, update four assoc LOGREC entries >> <<03021>>00810000
                                                               <<03021>>00812000
        FOR DATA'BIT := 0 UNTIL 3 DO                           <<03021>>00814000
         BEGIN                                                 <<03021>>00816000
         IF LOGGING'WORD THEN LOGREC(X) := LOGREC(X) + 1;      <<03021>>00818000
         X := X + 1;                                           <<03021>>00820000
         LOGGING'WORD := LOGGING'WORD & LSR(1);                <<03021>>00822000
         END;   << of splitting logging RAM word.           >> <<03021>>00824000
      END;      << of one logging RAM address.              >> <<03021>>00826000
   END;         << of memory error logging.                 >> <<03021>>00828000
END;            << of FILLOGREC'ICF55.                      >> <<03021>>00830000
$PAGE                                                          <<03021>>00832000
                                                                        00834000
PROCEDURE UPDATE'MEMLOG(MEMBOARD);                                      00836000
VALUE MEMBOARD; INTEGER MEMBOARD;                                       00838000
BEGIN                                                                   00840000
                                                                        00844000
     SUBROUTINE FILLOGREC;                                              00846000
     BEGIN                                                              00848000
          TOS:=DRT;  <<WILL BE USED AS THE DRT FOR ALL I/O OPERATIONS>> 00850000
          TICKCNT:=0;  <<SOFTWARE TIMEOUT COUNT>>              <<00.01>>00852000
          DO   <<MAKE SURE LOGGING HARDWARE IS UP AND READY>>           00854000
          BEGIN                                                         00856000
               TESTIO;                                                  00858000
               IF < THEN ERRMESSAGE(3);  <<LOGGING WENT AWAY>>          00860000
               IF NOT (MEMREADY:=TOS.(1:1)) THEN               <<00.01>>00862000
               DELAY(DOUBLE(TIMEOUTICK));                      <<00.01>>00864000
          END UNTIL MEMREADY OR (TICKCNT:=TICKCNT+1) > TICKMAX;<<00.01>>00866000
          IF TICKCNT > TICKMAX THEN ERRMESSAGE(6);             <<00.01>>00868000
          TICKCNT:=0;  <<SOFTWARE TIMEOUT COUNT>>              <<00.01>>00870000
          TOS:=COPYLOG CAT MEMBOARD(5:15:1);                            00872000
          CONTROLIO;                                                    00874000
          IF < THEN ERRMESSAGE(4);                                      00876000
          DO   <<WAIT FOR READCOPY TO COMPLETE; CHECK FOR ERROR FLAG>>  00878000
          BEGIN                                                         00880000
               TESTIO;                                                  00882000
               IF < THEN ERRMESSAGE(3);                        <<00.01>>00884000
               ERRORFOUND:=S0.ERRBIT;                                   00886000
               IF NOT (MEMREADY:=TOS.(1:1)) THEN               <<00.01>>00888000
               DELAY(DOUBLE(TIMEOUTICK));                      <<00.01>>00890000
          END UNTIL MEMREADY OR (TICKCNT:=TICKCNT+1) > TICKMAX;<<00.01>>00892000
          IF TICKCNT > TICKMAX THEN ERRMESSAGE(6+MEMBOARD);    <<00.01>>00894000
          IF ERRORFOUND THEN  <<AT LEAST ONE MEMORY ERROR LOGGED>>      00896000
          BEGIN                                                         00898000
               IF LOGRECD(FERRTIME) = 0D THEN FILLTIME(FERRTIME);       00900000
               FILLTIME(LERRTIME);  <<TIME LAST ERROR LOGGED>>          00902000
               TOS:=SCANLOG CAT MEMBOARD(5:15:1);                       00904000
               CONTROLIO;                                               00906000
               SCANNING:=TRUE;                                          00908000
               WHILE SCANNING DO                                        00910000
               BEGIN                                                    00912000
                    READIO;                                             00914000
                    IF < THEN ERRMESSAGE(5);                            00916000
                    IF (SCANNING:=S0.SCANBIT) THEN  <<STILL SCANNING>>  00918000
                    LOGREC(X):=LOGREC(TOS.MEMADDR)+1 ELSE               00920000
                    DELETE;                                             00922000
               END;                                                     00924000
               CLEAR'LOG'BOARD(MEMBOARD);                               00926000
          END;                                                          00928000
          DELETE;  <<DELETE STACKED DRT>>                               00930000
     END <<FILLOGREC>>;                                                 00932000
                                                                        00934000
                                                               <<TP2MB>>00936000
     SUBROUTINE FILLOGREC'TP;                                  <<TP2MB>>00938000
     BEGIN                                                     <<TP2MB>>00940000
          LOW'ADDR := IF MEMBOARD=CONTROLLER'A THEN 0D         <<TP2MB>>00942000
                      ELSE %2000000D;                          <<TP2MB>>00944000
          HIGH'ADDR:= IF MEMBOARD=CONTROLLER'A THEN %1777777D  <<TP2MB>>00946000
                      ELSE %3777777D;                          <<TP2MB>>00948000
          ERRORFOUND := FALSE;                                 <<TP2MB>>00950000
          TOS := LOW'ADDR - %1000D;                            <<TP2MB>>00952000
          WHILE (TOS := TOS + %1000D) < HIGH'ADDR DO           <<TP2MB>>00954000
              BEGIN                                            <<TP2MB>>00956000
                   READ'LOG;       <<TOS.(14:2):=0>>           <<TP2MB>>00958000
                   MCS;                                        <<TP2MB>>00960000
                   GET'LOG'BIT;    <<LOG'BIT:=TOS.(8:1)>>      <<TP2MB>>00962000
                   CLEAR'LOG;      <<TOS.(14:2):=2>>           <<TP2MB>>00964000
                   MCS;                                        <<TP2MB>>00966000
                   DEL;            <<GET RID OF STATUS RETURN>><<RK.08>>00968000
                   IF LOG'BIT THEN                             <<TP2MB>>00970000
                   BEGIN                                       <<TP2MB>>00972000
                        ERRORFOUND := TRUE;                    <<TP2MB>>00974000
                        X := S1.(13:3)&LSL(7);                 <<TP2MB>>00976000
                        X := X + S0.(0:7);                     <<TP2MB>>00978000
                        LOGREC(X) := LOGREC(X) + 1;            <<TP2MB>>00980000
                   END;                                        <<TP2MB>>00982000
              END; <<END OF WHILE LOOP>>                       <<TP2MB>>00984000
          DDEL; <<GET RID OF LOOP VARIABLE>>                   <<TP2MB>>00986000
          IF ERRORFOUND THEN                                   <<TP2MB>>00988000
             BEGIN                                             <<TP2MB>>00990000
                  IF LOGRECD(FERRTIME) = 0D THEN               <<TP2MB>>00992000
                     FILLTIME(FERRTIME);                       <<TP2MB>>00994000
                  FILLTIME(LERRTIME); <<TIME LAST LOGGED>>     <<TP2MB>>00996000
             END;                                              <<TP2MB>>00998000
     END;  << OF FILLOGREC'TP>>                                <<TP2MB>>01000000
                                                               <<TP2MB>>01002000
                                                               <<01396>>01004000
     SUBROUTINE FILLOGREC'PRONTO;                              <<01396>>01006000
     BEGIN                                                     <<01396>>01008000
          LOW'ADDR := IF MEMBOARD=CONTROLLER'A THEN 0D         <<01396>>01010000
                      ELSE %4000000D;                          <<01396>>01012000
          HIGH'ADDR:= IF MEMBOARD=CONTROLLER'A THEN %3777777D  <<01396>>01014000
                      ELSE %7777777D;                          <<01396>>01016000
          ERRORFOUND := FALSE;                                 <<01396>>01018000
          TOS := LOW'ADDR - %400D;                             <<01487>>01020000
          WHILE (TOS := TOS + %400D) < HIGH'ADDR DO            <<01396>>01022000
              BEGIN                                            <<01396>>01024000
                   READ'LOG;       <<TOS.(14:2):=0>>           <<01396>>01026000
                   MCS;                                        <<01396>>01028000
                   GET'LOG'BIT;    <<LOG'BIT:=TOS.(8:1)>>      <<01396>>01030000
                   CLEAR'LOG;      <<TOS.(14:2):=2>>           <<01396>>01032000
                   MCS;                                        <<01396>>01034000
                   DEL;            <<GET RID OF STATUS RETURN>><<01396>>01036000
                   IF LOG'BIT THEN                             <<01396>>01038000
                   BEGIN                                       <<01396>>01040000
                        ERRORFOUND := TRUE;                    <<01396>>01042000
                        X := S1.(12:4)&LSL(7);                 <<01396>>01044000
                        X := X + S0.(0:7);                     <<01396>>01046000
                        X := X+X+S0.(7:1);                              01048000
                        LOGREC(X) := LOGREC(X) + 1;            <<01396>>01050000
                   END;                                        <<01396>>01052000
              END; <<END OF WHILE LOOP>>                       <<01396>>01054000
          DDEL; <<GET RID OF LOOP VARIABLE>>                   <<01396>>01056000
          IF ERRORFOUND THEN                                   <<01396>>01058000
             BEGIN                                             <<01396>>01060000
                  IF LOGRECD(FERRTIME) = 0D THEN               <<01396>>01062000
                     FILLTIME(FERRTIME);                       <<01396>>01064000
                  FILLTIME(LERRTIME); <<TIME LAST LOGGED>>     <<01396>>01066000
             END;                                              <<01396>>01068000
     END;  << OF FILLOGREC'PRONTO>>                            <<03021>>01070000
                                                               <<01396>>01072000
     RECNUM:=DOUBLE(MEMBOARD);                                          01074000
     FREADDIR(FNUM,LOGREC,RECSIZE,RECNUM);                              01076000
     IF < THEN ERRMESSAGE(FSERR);                                       01078000
     FILLTIME(LASTIME);  <<INSERT START AND UPDATE TIMES INTO RECORD>>  01080000
     LOGREC(DELAYLOC):=DTIME;                                           01082000
                                                               <<03021>>01084000
<< Following FWRITEDIR posts initial DTIME (3600)  to  disc >> <<03021>>01086000
<< in  case  it  was changed by MEMTIMER during last run of >> <<03021>>01088000
<< system. This insures that MEMLOGAN reports proper DTIME. >> <<03021>>01090000
                                                               <<03021>>01092000
     IF FIRST'TIME THEN                                        <<03021>>01094000
       FWRITEDIR (FNUM, LOGREC, RECSIZE, RECNUM);              <<03021>>01096000
     CASE  CPU'TYPE  OF                                                 01098000
      BEGIN                                                             01100000
       FILLOGREC;                                                       01102000
       FILLOGREC;                                                       01104000
       FILLOGREC'TP;                                                    01106000
       FILLOGREC;                                                       01108000
       FILLOGREC'PRONTO;                                                01110000
       FILLOGREC'ICF55;                                        <<03021>>01112000
      END;                                                              01114000
     IF NOT FIRST'TIME THEN  <<IGNORE FIRST TIME ERRORS>>      <<00684>>01116000
       BEGIN                                                   <<00684>>01118000
         FWRITEDIR(FNUM,LOGREC,RECSIZE,RECNUM);                <<00684>>01120000
         IF <> THEN ERRMESSAGE(FSERR);                         <<00684>>01122000
       END;                                                    <<00684>>01124000
END << UPDATE'MEMLOG >>;                                                01126000
                                                                        01128000
     CPU'TYPE:=THISCPU;                                        <<TP2MB>>01130000
     IF CPU'TYPE=2 <<TP>> OR CPU'TYPE=4 <<GRIZLY>>             <<01396>>01132000
      THEN                                                     <<01396>>01134000
       BEGIN                                                            01136000
                                                                        01138000
        IF BANKNUM >= NEXT'CONTROLLER(4)                       <<01487>>01140000
         THEN TOS := %4000000D                                 <<01487>>01142000
         ELSE TOS := %0D;                                      <<01487>>01144000
        MCS;                                                   <<01396>>01146000
        IF 8<=S0.(12:4)<=9 THEN CPU'TYPE := 4 << PRONTO MEM >> <<01418>>01148000
         ELSE CPU'TYPE := 2;  << AMIGO MEMORY >>               <<01418>>01150000
        IF TOS.(15:1)= 0 THEN NEXT'CONTROLLER(4):="NO";        <<01396>>01152000
           << ELSE NEXT'CNTLR(4) := 16 >>                      <<01487>>01154000
        DDELETE;                                               <<01396>>01156000
       END;                                                    <<01396>>01158000
     IF CPU'TYPE=1 OR CPU'TYPE=3 THEN <<SERIES II OR 2MB>>     <<TP2MB>>01160000
     CHECKFORLOGGING;                                                   01162000
     OPEN'MEMLOG;                                                       01164000
     WHILE TRUE DO                                                      01166000
     BEGIN                                                              01168000
          FLOCK(FNUM,1);                                                01170000
          IF < THEN ERRMESSAGE(1);                                      01172000
          UPDATE'MEMLOG(CONTROLLER'A);                         <<TP2MB>>01174000
          IF BANKNUM >= NEXT'CONTROLLER(CPU'TYPE) THEN         <<TP2MB>>01176000
          UPDATE'MEMLOG(CONTROLLER'B);                         <<TP2MB>>01178000
          FUNLOCK(FNUM);                                                01180000
          IF < THEN ERRMESSAGE(2);                                      01182000
          FIRST'TIME:=FALSE;                                   <<00684>>01184000
          IF SHUTDOWN THEN                                              01186000
          BEGIN                                                         01188000
               FCLOSE(FNUM,1,0);                                        01190000
               IF < THEN ERRMESSAGE(FSERR);                             01192000
               AWAKE(ABSOLUTE(PROGENPINX),2,%4000);                     01194000
          END ELSE                                                      01196000
          BEGIN                                                         01198000
               IF NOT ABSOLUTE(SYSUP) THEN  <<PROGEN WAITING>>          01200000
               AWAKE(ABSOLUTE(PROGENPINX),2,0);                         01202000
               DELAYTIME:=DOUBLE(INTEGER(DTIME)) * 1000D;      <<00.02>>01204000
               DELAY(DELAYTIME);                                        01206000
          END;                                                          01208000
     END;                                                               01210000
END.                                                                    01212000
