// IfsMemoryError.bcpl -- Main memory single-error reporting (Alto-II only)
// Copyright Xerox Corporation 1981
// Last modified October 4, 1981  4:17 PM by Taft

get "Ifs.decl"
get "IfsSystemInfo.decl"
get "AltoDefs.d"

external
[
// outgoing procedures
InitMemoryError; RecordMemoryError; PrintMemoryErrors

// incoming procedures
VFileReadPage; VFileWritePage; LockCell; UnlockCell
Ws; PutTemplate; Plural; Zero

// outgoing statics

// incoming statics
infoVMD; AltoVersion; dsp
]

structure ME:  // memory errors, recorded in mePage of <System>Info
[
numErrors word
numBadSyndrome word
errors↑0,0:
   [
   location word =
      [ card byte; chip byte ]
   errorCount word
   ]
]

structure MESR:
[
hamming bit 6
parityError bit
parity bit
syndrome bit 6
bank bit 2
]

structure Bytes↑0,0 byte

manifest
[
maxErrors = (1 lshift logStdPageLength - offset ME.errors/16) /
 ((size ME.errors↑0)/16)
]

//----------------------------------------------------------------------------
let InitMemoryError() be
//----------------------------------------------------------------------------
[
let me = VFileWritePage(infoVMD, mePage)
Zero(me, (offset ME.errors↑0)/16)
@MESR = 0  // reset error latches
]

//----------------------------------------------------------------------------
and RecordMemoryError() be
//----------------------------------------------------------------------------
// Records a memory error that has occurred, and resets the error latches.
[
let syndromeMapping = table
   [
   38 lshift 8 + 37; 36 lshift 8 + 255; 35 lshift 8 + 255; 18 lshift 8 + 255
   34 lshift 8 + 29; 14 lshift 8 + 255; 7 lshift 8 + 255; 22 lshift 8 + 255
   33 lshift 8 + 27; 12 lshift 8 + 255; 5 lshift 8 + 255; 20 lshift 8 + 255
   2 lshift 8 + 31; 16 lshift 8 + 255; 9 lshift 8 + 255; 24 lshift 8 + 255
   32 lshift 8 + 26; 11 lshift 8 + 255; 4 lshift 8 + 255; 19 lshift 8 + 255
   1 lshift 8 + 30; 15 lshift 8 + 255; 8 lshift 8 + 255; 23 lshift 8 + 255
   0 lshift 8 + 28; 13 lshift 8 + 255; 6 lshift 8 + 255; 21 lshift 8 + 255
   3 lshift 8 + 255; 17 lshift 8 + 255; 10 lshift 8 + 255; 25 lshift 8 + 255
   ]

let me = VFileWritePage(infoVMD, mePage)

let mesr = not @MESR  // MESR reads out low-true
let address = @MEAR
let switch = utilIn>>UtilIn.memConfig
let xm = AltoVersion<<VERS.eng eq 3
let bank = xm? mesr<<MESR.bank, 0

let bitNum = syndromeMapping>>Bytes↑(mesr<<MESR.syndrome)
test bitNum eq 255
   ifso me>>ME.numBadSyndrome = me>>ME.numBadSyndrome+1
   ifnot
      [
      if switch ne 0 then address = address xor 100000B
      let card = (bitNum & 3) +1
      let chip = bitNum rshift 3 + 16 - ((bitNum & 4) ne 0? 5, 0) +
       10*(address rshift (xm? 15, 13)) + bank*20
      let location = card lshift 8 + chip

      let found = false
      for i = 0 to me>>ME.numErrors-1 do
         if location eq me>>ME.errors↑i.location then
            [
            me>>ME.errors↑i.errorCount = me>>ME.errors↑i.errorCount+1
            found = true
            break
            ]
      unless found % me>>ME.numErrors eq maxErrors do
         [
         let i = me>>ME.numErrors
         me>>ME.errors↑i.location = location
         me>>ME.errors↑i.errorCount = 1
         me>>ME.numErrors = i+1
         ]
      ]

@MESR = 0  // reset error latches
]

//----------------------------------------------------------------------------
and PrintMemoryErrors() be
//----------------------------------------------------------------------------
[
let me = VFileReadPage(infoVMD, mePage)
LockCell(lv me)

if me>>ME.numErrors ne 0 then
   [
   Ws("*n*nMain memory errors:*nCard  Chip  Errors")
   for i = 0 to me>>ME.numErrors-1 do
      PutTemplate(dsp, "*n$3D$6D$7UD",
       me>>ME.errors↑i.card, me>>ME.errors↑i.chip, me>>ME.errors↑i.errorCount)
   ]

if me>>ME.numBadSyndrome ne 0 then
   PutTemplate(dsp, "*n*n$UD main memory error$S with bad syndrome.",
    me>>ME.numBadSyndrome, Plural(me>>ME.numBadSyndrome))

UnlockCell(lv me)
]