-- File: MemoryErrorInfo.mesa, Last Edit: HGM March 31, 1981 3:34 PM -- See page 40 of Alto Hardware Manual, and/or [Ivy]Sources>IFSMemoryError.bcpl DIRECTORY Inline USING [BITAND, BITNOT, BITSHIFT, BITXOR], Menu USING [Handle, ItemObject, MCRType, Create, Instantiate], Process USING [Detach, SecondsToTicks, SetTimeout], Put USING [CR, Date, Line, LongDecimal, LongNumber, Number, Text], SegmentDefs USING [GetMemoryConfig, MemoryConfig], Storage USING [Node], String USING [AppendDecimal, AppendOctal, AppendString], Time USING [Current], UserInput USING [GetDefaultWindow], Window USING [Handle], GateDefs USING [typescript]; MemoryErrorInfo: MONITOR IMPORTS Inline, Menu, Process, Put, SegmentDefs, Storage, String, Time, UserInput, GateDefs = BEGIN first: ErrorInfo _ NIL; maxErrorBlocks: CARDINAL = 10; badSyndrome: LONG CARDINAL _ 0; otherErrors: LONG CARDINAL _ 0; Card: TYPE = [1..4]; Chip: TYPE = [11..90]; Syndrome: TYPE = [0..64); ErrorInfo: TYPE = POINTER TO ErrorInfoBlock; ErrorInfoBlock: TYPE = RECORD [ card: Card, chip: Chip, count: LONG CARDINAL, next: ErrorInfo]; maxErrors: LONG CARDINAL = LAST[LONG CARDINAL]; Address: TYPE = WORD; -- It's really a pointer, but we do arithametic on it mear: POINTER TO Address = LOOPHOLE[177024B]; mesr: POINTER TO UNSPECIFIED = LOOPHOLE[177025B]; -- Low TRUE MESR: TYPE = MACHINE DEPENDENT RECORD [ hamming: [0..64), parityError: BOOLEAN, parityBit: [0..1), syndrome: Syndrome, bank: [0..4) ]; WatchForMemoryErrors: ENTRY PROCEDURE = BEGIN sleep: CONDITION; info: MESR; first: BOOLEAN _ FALSE; Process.SetTimeout[@sleep,Process.SecondsToTicks[300]]; mesr^ _ 0; -- reset error latches DO WAIT sleep; info _ Inline.BITNOT[mesr^]; IF Inline.BITAND[info,1374B] = 0 THEN LOOP; IF ~first THEN BEGIN first _ TRUE; SetupMenu[]; END; RecordMemoryError[]; ENDLOOP; END; RecordMemoryError: PROCEDURE = BEGIN address: Address _ mear^; info: MESR _ Inline.BITNOT[mesr^]; PrintErrorInfo[address, info]; BEGIN card: Card; chip: Chip; [card: card, chip: chip] _ ConvertInfoToCardAndChip[address, info ! BadSyndrome => GOTO Bad]; PrintCardInfo[card: card, chip: chip]; AddToList[card: card, chip: chip]; EXITS Bad => badSyndrome _ badSyndrome+1; END; mesr^ _ 0; -- reset error latches END; BadSyndrome: SIGNAL = CODE; ConvertInfoToCardAndChip: PROCEDURE [address: Address, info: MESR] RETURNS [card: Card, chip: Chip] = BEGIN -- The memory is 39 bits wide: 32 data bits, 6 hamming bits, and a parity bit BitNumber: TYPE = [0..39]; -- 39 is used to mark an invalid syndrome syndromeMapping: PACKED ARRAY Syndrome OF BitNumber = [ 38, 37, 36, 39, 35, 39, 18, 39, 34, 29, 14, 39, 07, 39, 22, 39, 33, 27, 12, 39, 05, 39, 20, 39, 02, 31, 16, 39, 09, 39, 24, 39, 32, 26, 11, 39, 04, 39, 19, 39, 01, 30, 15, 39, 08, 39, 23, 39, 00, 28, 13, 39, 06, 39, 21, 39, 03, 39, 17, 39, 10, 39, 25, 39 ]; bit: BitNumber _ syndromeMapping[info.syndrome]; IF bit=39 THEN SIGNAL BadSyndrome; IF TheSwitch[] THEN address _ Inline.BITXOR[address,100000B]; card _ (bit MOD 4)+1; -- This could be haired up to work with 4K chips chip _ bit/8 + 16 - (IF Odd[bit/4] THEN 5 ELSE 0) + 10*Inline.BITSHIFT[address,-15] + 20*info.bank; END; TheSwitch: PROCEDURE RETURNS [BOOLEAN] = INLINE BEGIN utlin: POINTER TO PACKED ARRAY [0..16) OF BOOLEAN = LOOPHOLE[177030B]; RETURN[utlin[6]]; END; Odd: PROCEDURE [x: UNSPECIFIED] RETURNS [BOOLEAN] = INLINE BEGIN RETURN[(x MOD 2)=1]; END; AddToList: PROCEDURE [card: Card, chip: Chip] = BEGIN length: CARDINAL _ 0; FOR e: ErrorInfo _ first, e.next UNTIL e=NIL DO IF chip=e.chip AND card=e.card THEN BEGIN IF e.count 0 THEN BEGIN IF badSyndrome=1 THEN Put.Text[wh, "One main memory error"L]; IF badSyndrome>1 THEN BEGIN Put.LongDecimal[wh, badSyndrome]; Put.Text[wh, " main memory errors"L]; END; Put.Line[wh, " with bad symdrome."L]; END; IF otherErrors > 0 THEN BEGIN IF otherErrors=1 THEN Put.Text[wh, "One other main memory error"L]; IF otherErrors>1 THEN BEGIN Put.LongDecimal[wh, otherErrors]; Put.Text[wh, " other main memory errors"L]; END; Put.Line[wh, "."L]; END; END; PutHeader: PROCEDURE [wh: Window.Handle, s: STRING, cr: BOOLEAN _ TRUE] = BEGIN Put.Date[wh, Time.Current[], dateTime]; Put.Text[wh, " "L]; Put.Text[wh, s]; IF cr THEN Put.CR[wh]; END; items: ARRAY [0..1) OF Menu.ItemObject _ [["Errors", DoInfo]]; SetupMenu: PROCEDURE = BEGIN menu: Menu.Handle _ Menu.Create[DESCRIPTOR[items], "MemErr"]; Menu.Instantiate[menu, UserInput.GetDefaultWindow[]]; Menu.Instantiate[menu, GateDefs.typescript]; END; DoInfo: Menu.MCRType = BEGIN PrintMemoryErrors[NIL]; END; Init: PROCEDURE = BEGIN config: SegmentDefs.MemoryConfig _ SegmentDefs.GetMemoryConfig[]; IF config.AltoType#AltoIIXM THEN RETURN; Process.Detach[FORK WatchForMemoryErrors[]]; END; Init[]; END.