// 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 [ ] //----------------------------------------------------------------------------