$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
