// MPEScan.bcpl -- machine-independent part of PE scan overlay
//	Last edited: 1 May 1980

get "mdecl.d"
get "mcommon.d"

external [
// OS
	Zero

// MDATA
	AddrIntersect; AddrUnion

// MASM
	Wss; @WssCSS; PutsCSS; ResetsCSS; ResetsCS1; WssCS1

// MIOC
	DWns; DataToStream

// MMENU
	CreateAction; @WsMarkA; ItemStream

// MCMD
	CmdCommentStream; CmdCS1; WnsCSSD; FormCmdMenu
	QuitCmdOverlay; DisplayError; SetAbort; CmdAbort; @CmdAbortAct

// MGO
	@CantContinue

// MINIT0
	@ACTS

// Machine-dependent resident
	@MEMNAM; @MEMCON; @MEMWID; @MEMFORMS; @NMEMS

// Machine-dependent pe-scan overlay
	ScanForPE

// Defined here
	PEScan; ReportPE; PEScanning
]

static [ PEScanning = 0 ]


let PEScan(nil,nil) = valof
[	SetAbort(lv CmdAbort,0)
	ACTS!1 = CreateAction("Scan-and-report",lv ScanMems,true)
	ACTS!2 = CreateAction("Scan-for-totals",lv ScanMems,false)
	let I = 3; ACTS!0 = 0
	for X = 0 to NMEMS-1 do
	[ if (MEMCON+X)>>MRType.HasParity ne 0 do
	  [ ACTS!I = CreateAction(MEMNAM!X,lv ScanAct,I)
	    ACTS!(I+1) = X; ACTS!(I+2) = true; I = I+3; ACTS!0 = ACTS!0+1
	  ]
	]
	PEScanning = false; resultis PEScanMenu
]


and PEScanMenu(nil,nil) be
[	ResetsCSS(); ResetsCS1()
	WsMarkA(CmdAbortAct)
//PEScanning serves here as a menu switch and may also be used by
//the machine-dependent memory read procedures, if they do something
//special during a PEscan.
	if PEScanning then return
	WssCSS("Scan for parity errors in: ")
	WsMarkA(ACTS!1); WsMarkA(ACTS!2)
	let I = 3
	for J = 1 to ACTS!0 do
	[ if ACTS!(I+2) then
	  [ Wss(ItemStream,"not-"); WssCSS(MEMNAM!(ACTS!(I+1)))
	    PutsCSS($ )
	  ]
	  WsMarkA(ACTS!I); I = I+3
	]
]


and ScanAct(I,nil,nil) be
[	ACTS!(I+2) = not ACTS!(I+2)
	FormCmdMenu()
]


and ScanMems(WaitP,nil,nil) be
[	CantContinue = CantContinue % didPEscan
	PEScanning = true
	FormCmdMenu()
	let NPETab = vec 40	//Vector to accumulate totals
	Zero(NPETab,40); NPETab!0 = 2
	AddrIntersect!0,AddrIntersect!1 = -1,-1
	AddrUnion!0,AddrUnion!1 = 0,0
	let J = 3
//The machine-dependent ScanForPE(MemX,WaitP,Vec) routine sets NPETab!1
//to true if any errors are detected.  NPETab!0 points at the next
//free table entry which should be filled out as follows for each
//error total:
//	NPETab!(NPETab!0) = error total
//	NPETab!(NPETab!0+1) = string 1 in summary
//	NPETab!(NPETab!0+2) = string 2 in summary = memory name
	for I = 1 to ACTS!0 do
	[ if ACTS!(J+2) then
	  [ ScanForPE(ACTS!(J+1),WaitP,NPETab)
	  ]
	  J = J+3
	]
	ResetsCSS(); ResetsCS1()
	test NPETab!1 eq 0
	ifso WssCSS("No errors")
	ifnot
	[ WssCSS("PE totals:"); let FirstS = " "
	  for I = 2 to NPETab!0 by 3 if NPETab!I ne 0 do
	  [ WssCSS(FirstS); WnsCSSD(NPETab!I)
	    WssCSS(NPETab!(I+1)); WssCSS(NPETab!(I+2))
	    FirstS = ", "
	  ]
	  WssCS1("(See ADDR-INTERS and ADDR-UNION)")
	]
	PEScanning = false
	QuitCmdOverlay()
]


and ReportPE(NPETab,NPEX,DVec,MemX,AVec,WaitP) be
[	if WaitP do
	[ ResetsCSS(); WssCSS("PE in ")
	  WssCSS(NPETab!(NPEX+2)); WssCSS(" at ")
	  DWns(CmdCommentStream,AVec)
	  ResetsCS1(); WssCS1("Data is: ")
	  DataToStream(CmdCS1,MEMFORMS!MemX,MEMWID!MemX,DVec)
	  PEScanning = false
	  DisplayError(0,"Continue",0,0)
	  PEScanning = true
	]
//Compute intersection and union of failure addresses
	AddrUnion!0,AddrUnion!1 = AddrUnion!0 % AVec!0,AddrUnion!1 % AVec!1
	AddrIntersect!0 = AddrIntersect!0 & AVec!0
	AddrIntersect!1 = AddrIntersect!1 & AVec!1
	NPETab!NPEX = NPETab!NPEX+1
	NPETab!1 = true
]