// SwatParityErrors.bcpl - Parity error diagnosis code.
// Copyright Xerox Corporation 1979, 1982
// Last modified April 22, 1982 3:39 PM by Boggs
get "Swat.decl"
get "AltoDefs.d"
external
[
// outgoing procedures
ParityError
// incoming procedures from Swat
VMStore; VMFetch; EventReport
Ws; PutTemplate; SetFailPt; UnSetFailPt
// incoming procedures from OS
Zero; MyFrame; Usc; FrameSize
DisableInterrupts; EnableInterrupts
// incoming statics
dsp
]
static errorBits
manifest
[
AltoIIMemEnable = 177773b
SingleInterruptNoCorrect = 177765b
DoubleInterrupt = 177773b
]
structure ESR: //Alto II Error Status Register
[ //All signals low true
hamming bit 6
parityError bit
memParity bit
syndrome bit 6
spare bit
switch bit //Not really here, but we put it there...
]
structure SERParity: // Parity error report = type 1
[
@SERHead
errLoc word // Location in error
errCon word // Contents
status word // AltoII status + (bit 15) switch position
DCBR word
KNMAR word
DWA word
CBA word
PC word
SAD word
PCcontents word
bangResults word 3 = // Results of banging on the location
[
spare bit 10
moreErrors bit
which bit 5
error1 byte
error0 byte
tried1 byte
tried0 byte
]
]
manifest lenSERParity = size SERParity/16
//----------------------------------------------------------------------------
let ParityError(p, fetch) be
//----------------------------------------------------------------------------
// Parity error diagnosis code. This is complicated a bit by the
// differences between Alto I and Alto II. In addition, the "bug"
// in the Alto II memory interface that loses parity error information
// requires some special treatment.
//
// Interrupts are disabled
// p!0 = 77401b
// p!1 = JMP ...
// 2 = Address of bad word or 0
// 3 = PC at time of interrupt
// 4 = AC0 at time of interrupt
// 5 = carry at time of interrupt
// 6 = Display list at time of interrupt
// 7 = Active interrupts at time of interrupt
// 10b-15b (OsVersion 8 or greater) are DCBR,KNMAR, etc.
// fetch may use virtual memory
[
let errv = vec size SERParity/16
errv>>SERHead.type = serTypeParity
errv>>SERHead.AltoVersion = (table [ 61014B; 1401B ])()
errv>>SERHead.OsVersion = VMFetch(VMFetch(176777B)+23B) // 23rd top OS static
let AltoII = (table [ 61014B; 1401B ])()<<VERS.eng gr 1
// Gather status
let memEAR = @MEAR
let stat = AltoII? @MESR, 0 //May reset the memory interface
stat<<ESR.switch = @utilIn rshift 9
errv>>SERParity.status = stat
// Following boolean is true if the Alto II memory interface
// "saw" the error and retained the memory of it.
let AltoIIMemSaw = stat<<ESR.syndrome ne 77b % stat<<ESR.parityError eq 0
// Error location and contents
let errLoc = 0
let printLoc = true
test AltoII
ifnot
[
errLoc = fetch(p+2) //Get sweep error address
printLoc = errLoc ne 0 //Indication sweep found an error
]
ifso
[
errLoc = memEAR //Error address register
unless AltoIIMemSaw then [ errLoc = 0; printLoc = false ]
]
errv>>SERParity.errLoc = errLoc
let errCon = fetch(errLoc)
errv>>SERParity.errCon = errCon
errv>>SERParity.DCBR = fetch(p+10) //DCBR
errv>>SERParity.KNMAR = fetch(p+11) //KNMAR
errv>>SERParity.DWA = fetch(p+12) //DWA
errv>>SERParity.CBA = fetch(p+13) //CBA
errv>>SERParity.PC = fetch(p+14) //PC
errv>>SERParity.SAD = fetch(p+15) //SAD
errv>>SERParity.PCcontents = fetch(errv>>SERParity.PC)
// DiagnoseParityError (cont'd)
// Now try to decide if an error really happened.
// 0 = probably not; 1 = for sure; 2 = suggestive
let happened = 2
// On OS 11 and greater, we set the parity task locations (614 to 621)
// to a magic number (52525b) every time a subsystem is run.
// If these locations have been changed, this is evidence that the
// parity task has indeed run.
for i = 0 to 5 do if fetch(p+10b+i) ne 52525b then happened = 1
// On Alto II, memory interface is positive indication.
if AltoII ne 0 & AltoIIMemSaw ne 0 then happened = 1
// On Alto I, if sweep found an error, that is positive.
if errLoc ne 0 then happened = 1
Ws(selecton happened into
[
case 0: "A parity interrupt has occurred, but there is no evidence of*nbad parity in the memory.*n"
case 1: "A parity error has occurred.*n"
case 2: "A parity interrupt has occurred, but there is only suggestive*nevidence that a parity error actually occurred.*n"
])
if AltoII ne 0 & AltoIIMemSaw eq 0 then
Ws("The memory interface has lost the exact error information.*n")
// If we really believe there is a bad location, print it out.
// If we don't, it makes sense to tell Alto I users about
// the phantom. But there is no way a scan of Alto II memory
// means much, because the parity task turned off the parity
// error detection logic when the first error occurred.
test printLoc
ifso PutTemplate(dsp, "Location $UO exhibits bad parity. Contents=$UO*N",
errLoc, errCon)
ifnot unless AltoII do Ws("A scan of memory found no bad locations.*n")
PutTemplate(dsp, "DCBR=$UO KNMAR=$UO DWA=$UO CBA=$UO PC=$UO SAD=$UO*N",
errv>>SERParity.DCBR, errv>>SERParity.KNMAR, errv>>SERParity.DWA,
errv>>SERParity.CBA, errv>>SERParity.PC, errv>>SERParity.SAD)
if AltoII then PutTemplate(dsp, "Alto II: status=$UO*N", stat)
// Now go bang on the bad location
let br = lv errv>>SERParity.bangResults
Zero(br, size SERParity.bangResults/16)
br!0 = 31
if printLoc then
[
BangOn(errLoc, fetch, AltoII, br)
if br!1 ne 0 then
PutTemplate(dsp, "Results of testing bad location: $UO $UO $UO*N",
br!0, br!1, br!2)
]
// Now try to log the error:
let ok = false
Ws("Logging error...")
SetFailPt(notLogged)
ok = EventReport(errv, lenSERParity)
UnSetFailPt()
notLogged: Ws(ok? "OK.*N", "failed.*N")
// Re-enable the various interfaces, and reset parity task posting
// locations to magic number.
@MECR = AltoIIMemEnable
@MESR = 0
for i = 614b to 621b do [ @i = 52525B; VMStore(i, 52525B) ]
]
//----------------------------------------------------------------------------
and BangOn(loc, fetch, AltoII, resultVec) be
//----------------------------------------------------------------------------
// Routine to bang on a memory location suspected of being bad,
// and return some results.
// ResultVec is structure
// [
// spare bit 10
// more bit -- on if more than 1 bit seems bad
// which bit 5 --
// 0-15 number the data bits in the word
// 16 is the parity bit
// 17-22 number the Hamming code bits (Alto II only)
// 30 means queer results from memory interface (Alto II)
// 31 means no error was detected
// error1 byte -- number of times a 1 bit was returned as 0
// error0 byte -- number of times a 0 bit was returned as 1
// tried1 byte -- number of times 1 value was tried
// tried0 byte -- number of times 0 value was tried
// ]
[
Zero(resultVec, 3)
let f = MyFrame()
if Usc(loc, f) ge 0 & Usc(loc, f+FrameSize(BangOn)) le 0 then return
if Usc(loc, BangOn) ge 0 & Usc(loc, BangOnEnd+100) le 0 then return
if Usc(loc, 400b) ge 0 & Usc(loc, 777b) le 0 then return
let queer = 0
let v1 = vec 60
Zero(v1, 60)
errorBits = v1
let oldContents = fetch(loc)
let otherLoc = loc xor 1
let otherContents = fetch(otherLoc)
for j = 0 to 4 do
[
let m = 100000b
for i = 0 to 15 do
[
let val = m
val = val xor selecton j into
[
case 0: 0
case 1: 1
case 2: -1
case 3: -2
case 4: oldContents
]
DisableInterrupts()
let old = @loc
let oldOther = @otherLoc
let newval = nil
let wws = nil
@wakeupsWaiting = 0; @MESR = 0; @MECR = SingleInterruptNoCorrect
// Here begins the window during which we have changed memory:
for cnt = 0 to 500 do
[
@otherLoc = otherContents
@loc = val
newval = @loc
wws = @wakeupsWaiting
if (wws&1) ne 0 break //Error
]
let mems = @MESR; let memEAR = @MEAR
@loc = old
@otherLoc = oldOther
// Here ends the window
@wakeupsWaiting = 0; @MECR = DoubleInterrupt; @MESR = 0
EnableInterrupts()
// Compute parity -- a la Alto I
let parity = 0
for i = 0 to 15 do
if ((val rshift i)&1) ne 0 then
parity = parity xor -1
// Record what we tried, and what failed
let error = (wws & 1) ne 0
for i = 0 to 15 do RecordE(val, newval, i, 15-i)
test AltoII
ifso
[
// Here compute goodMems, the "good" status in the syndrome
// and parity bits. -- Dummy computation for now:
let hc = 0; let m = 100000b
let evenW = ((loc & 1) eq 0)? val,otherContents
let oddW = evenW xor val xor otherContents
for i = 0 to 15 do
[
if (evenW & m) ne 0 then hc = hc xor (table [
60b; 50b; 30b; 70b; 44b; 24b; 64b; 14b;
54b; 34b; 74b; 42b; 22b; 62b; 02b; 52b ])!i
if (oddW & m) ne 0 then hc = hc xor (table [
32b; 72b; 06b; 46b; 26b; 66b; 16b; 56b;
36b; 76b; 41b; 21b; 61b; 11b; 51b; 31b ])!i
m = m rshift 1
]
let t = otherContents xor hc
for i = 0 to 15 do
if ((t rshift i)&1) ne 0 then
parity = parity xor -1
let goodMems = (hc lshift 10)
goodMems<<ESR.memParity = parity //Odd parity, but 0 true
if mems<<ESR.syndrome eq 77b % memEAR ne loc then
[
if error then queer = true
mems = goodMems //No way to tell, assume good
]
for i = 17 to 22 do RecordE(goodMems, mems, i, 32-i)
RecordE(goodMems, mems, 16, 8)
]
ifnot RecordE(parity, parity xor (error&(val eq newval)), 16)
m = m rshift 1
]
]
// Now look for the best error to report.
let best = 31
let bdiff = 0
let tot = 0
for i = 0 to 22 do if errorBits!i then
[
let d = errorBits!i
tot = tot+1
d = (d rshift 8)+(d&377b)
if d gr bdiff then [ best = i; bdiff = d ]
]
if best eq 31 & queer ne 0 then best = 30
resultVec!0 = best+((tot gr 1)? 40b, 0)
if best le 22 then
[
resultVec!1 = errorBits!best
resultVec!2 = errorBits!(30+best)
]
]
//----------------------------------------------------------------------------
and RecordE(goodVal, badVal, i, shamt; numargs na) be
//----------------------------------------------------------------------------
[
if na eq 4 then
[
goodVal = goodVal rshift shamt
badVal = badVal rshift shamt
]
let goodBit = goodVal&1
if ((goodVal xor badVal) & 1) ne 0 then
errorBits!i = errorBits!i+(goodBit? 400B, 1)
i = i+30
errorBits!i = errorBits!i+(goodBit? 400B, 1)
]
//----------------------------------------------------------------------------
and BangOnEnd() be [ ]
//----------------------------------------------------------------------------