//MXPOW.BCPL
//Microprocessor power on/off overlay
get "mx.d"
//Power on/off is carried out by MicGo and MicStop. Each of these creates
//a subsidiary menu with the items "processor", "memory", "both",
//"test-port-&-processor", and "test-memory-module."
//Port power is turned on when either memory or processor is turned on
//because neither one is operable with port power off. If the memory was
//on or is turned on, a two or four quadrant configuration maximizing
//available memory is setup. A string describing its actions is displayed.
//CONFIG in LDR controls memory configuration. The right-most four
//nine-bit bytes in CONFIG represent quadrants 0-3 with the right-most eight
//bits of each byte representing the 8 possible 32-K memory modules in
//that quadrant. A one in the bit enables that cabinet in that quadrant.
//The right-most bit is for module 0. This arrangement of CONFIG was chosen
//so that the configuration is apparent when CONFIG is examined with Midas.
//MicGo and MicStop begin by creating actions for each of the four menu
//items and an abort item, and they destroy the actions before returning.
static [ ProcA; MemA; BothA; TestPA; TestMA; Module; PPVal
ErrCA; SingleFA; ParityFA; DisFERA; DisZC; MemOnA
ZCDisabled=0; SingleFatal=0; ParityFatal=0; ErrC=0
FERDisabled=4000B
]
let MicGo(Flag) = valof
[ ProcA = CreateAction("Processor",lv ProcOn,0)
MemA = CreateAction("Memory",lv MemOn,2)
BothA = CreateAction("Both",lv MemOn,3)
SingleFA = CreateAction("Make-SE-fatal",lv SinFatal,0)
ParityFA = CreateAction("Make-PE-fatal",lv ParFatal,0)
DisFERA = CreateAction("Disable-FER",lv DisFER,0)
DisZC = CreateAction("No-core-zeroing",lv DisZeroCore,0)
ErrCA = CreateAction("Disable-correction",lv ErrCOff,0)
MemOnA = CreateAction("Do-it",lv MemOnNow,0)
QuitF = -2
resultis PowerTestActs(17B)
]
and MicStop() = valof
[ ProcA = CreateAction("Processor",lv PowOff,2)
MemA = CreateAction("Memory",lv PowOff,3)
BothA = CreateAction("Both",lv PowOff,0)
QuitF = -1
resultis PowerTestActs(0)
]
and PowerTestActs(Val) = valof
[ TestPA = CreateAction("Test-port-&-processor",lv PPowerTest,Val)
TestMA = CreateAction("Test-memory-module",lv MPowerTest,Val)
QUITact = CreateAction("Abort",lv PowAbort,0,0,$C-100B)
resultis PowerMenu
]
and PowerMenu(S,Nix,MarkS) be
[ WsMarkA(QUITact)
if (QuitF < 0) & (QuitF ge -2) do
[ WsMarkA(ProcA); WsMarkA(MemA); WsMarkA(BothA)
WsMarkA(TestPA); WsMarkA(TestMA)
]
if QuitF eq -3 do
[ WsMarkA(SingleFA); WsMarkA(ParityFA); WsMarkA(DisZC)
WsMarkA(DisFERA); WsMarkA(ErrCA); WsMarkA(MemOnA)
]
]
and PowerExit(str) be
[ ReadAllRegs(); WssCSS(str)
QuitCmdOverlay()
]
and PowAbort(S,garb,Buttons,arg) be
[ Resets(CmdCommentStream)
test QuitF ge 0
ifso [ RemoveFromEveryTimeList(QuitF); PowerExit("End of power test") ]
ifnot [ PowerExit("XXX") ]
]
//Clear interrupt enables, dismiss interrupt in progress (if any), and
//clear F-register. Used after power up.
and ResetM() be
[ XctMic(CLRARM); XctMic(INTRETN)
XctL36(LDQ,table [ -1; -1; 170000B ] ); XctMic(LDSMF)
XctL36(CLRFLQ,SMFORF); XctMic(LDSMF); XctL36(LDQ,Q)
]
and ZeroMem(MemX) be
[ let AVec = vec 1; AVec!0 = 0
for I = 0 to MEMLEN!MemX do
[ AVec!1 = I; PutMemData(MemX,AVec,table [ 0; 0; 0; 0; 0 ] ) ]
]
and ZeroLM() be
[ Wait(1); for I = 2 to 5 do ZeroMem(I) //Zero IM, SM, DM, MP
ZeroMem(10); ZeroMem(11) //DM1 and DM2
]
//Delay is the maximum wait in multiple of 4 msec
and PPStatus(Delay) = valof
[ let StartTime = vec 2; Timer(StartTime); DoubleNeg(StartTime)
while true do
[ let TimedOut = (GetTime(StartTime)-Delay) ge 0
@ADREG = PPSTAT; let Status = @INREG & 3
if Status eq 3 then resultis 1
if TimedOut then switchon Status into
[
case 0: WssCSS("Port and processor both off"); resultis 0
case 1: WssCSS("Port power off"); resultis 0
case 2: WssCSS("Port on, processor off "); resultis -1
]
]
]
//Turn on processor and port only (Port must be on to use processor)
and ProcOn(S,garb,Buttons,arg) be
[ @ADREG = PPPWR; @OUTREG = 3
test PPStatus(2500) le 0
ifso PowerExit("")
ifnot [ ResetM(); ZeroLM(); PowerExit("Port & processor on AOK") ]
]
//Turn on power supplies and configure memory. PP is 3 for "both", 2 for
//"memory"
and MemOn(S,garb,Buttons,PP) be
[ PPVal = PP
SingleFatal = 0 //Normal: single errors not fatal
ParityFatal = 0 //Normal: parity errors not fatal
ErrC = 0 //Normal: error correction enabled
FERDisabled = 4000B //Normal: FER given for fatal errors
ZCDisabled = false //Normal: Zero core
QuitF = -3
FormMenu(CmdMDFS,FormCmdmenuText)
]
and SinFatal(S,garb,Buttons,Zot) be SingleFatal = 252B
and ParFatal(S,garb,Buttons,Zot) be ParityFatal = 125B
and ErrCOff(S,garb,Buttons,Zot) be ErrC = 400B
and DisFER(S,garb,Buttons,Zot) be FERDisabled = 0
and DisZeroCore(S,garb,Buttons,Zot) be ZCDisabled = true
and MemOnNow(S,garb,Buttons,Zot) be
[ let LPC,CABSINUSE,Configuration = nil,0,0
//Unpack the memory configuration stuff from CONFIG into TMP
//Since CONFIG is an 80-bit memory word, have to work on the right 36 bits
TMP!0 = (MEMCFG!2 lshift 5)+(MEMCFG!3 rshift 11) //CONFIG[0,8] = J
TMP!1 = MEMCFG!3 rshift 2 //CONFIG[9,17] = K
TMP!2 = (MEMCFG!3 lshift 7)+(MEMCFG!4 rshift 9) //CONFIG[18,26] = L
TMP!3 = MEMCFG!4 //CONFIG[27,35] = M
//Setup the vector TMP1 with a count of the number of cabinets available
//in each quadrant in r.h. and the quadrant number in l.h.
for I = 0 to 3 do
[ LPC = (TMP!I)<<rh; CABSINUSE = CABSINUSE % LPC
TMP1!I = Countbits(LPC) + (I lshift 8)
]
//Get largest number of good modules in TMP1!3 smallest in TMP1!0
for I = 0 to 2 do
[ for J = 0 to 2 do
[ if (TMP1!J)<<rh gr (TMP1!(J+1))<<rh do
[ LPC = TMP1!(J+1); TMP1!(J+1) = TMP1!J; TMP1!J = LPC ]
]
]
//Turn on the port, leaving the processor on if it's already on
@ADREG = PPSTAT; LPC = @INREG
@ADREG = PPPWR; @OUTREG = PPVal % LPC
//Turn on the memory cabinets in the configuration--first turn on the
//+5, -5, and +20 supplies. Then when these are on turn on the +16 supply.
//CabinetsOn leaves everything off if anything goes wrong.
//Below 5000*4 msec = 20 sec max. wait for power up
Resets(CmdCommentStream)
//Had trouble with relying on status to be correct so added this double
//check code.
let PowOn = CabinetsOn(CABSINUSE,15B,17B,5000)
if PowOn then
[ Wait(1); PowOn = CabinetsOn(CABSINUSE,15B,17B,1000) ]
if PowOn then PowOn = CabinetsOn(CABSINUSE,17B,17B,5000)
if PowOn then
[ Wait(1); PowOn = CabinetsOn(CABSINUSE,17B,17B,1000) ]
if (not PowOn) % (PPStatus(2000) eq 0) then PowerExit("")
@ADREG = RESR; @OUTREG = 0 //Catastrophic reset
//MAINsize will wind up holding the upper bound on the value of MADDRH
//for main memory references (i.e., the largest value of the top four bits
//of a main memory address
//In 4Q mode, use 4*TMP1!0 modules; in 2Q mode, use 2*TMP1!2 modules
let Mem2Q = (TMP1!2)<<rh - 1
if Mem2Q eq -1 then PowerExit("Insufficient memory in CONFIG to run")
let Mem4Q = (TMP1>>rh lshift 1) - 1
test Mem4Q ge Mem2Q
ifso
[ LPC = table [ 4; 0; 6; 2; 5; 1; 7; 3 ]
Puts(CmdCommentStream,$4)
MAINsize = Mem4Q
]
ifnot
[ MAINsize = Mem2Q
Puts(CmdCommentStream,$2)
LPC = table [ 4; 5; 0; 1; 6; 7; 2; 3 ]
Configuration = table [
7; //JJ (impossible)
1; //JK
2; //JL
3; //JM
1; //KJ
7; //KK (impossible)
4; //KL
5; //KM
2; //LJ
4; //LK
7; //LL (impossible)
6; //LM
3; //MJ
5; //MK
6; //ML
7; //MM (impossible)
] ! (((TMP1!2 rshift 6) & 14B) + (TMP1!3)<<lh)
]
WssCSS(" quadrants ")
WssCSS(selecton MAINsize into
[ case 0: "64K"
case 1: "128K"
case 2: "192K"
case 3: "256K"
case 4: "320K"
case 5: "384K"
case 6: "448K"
case 7: "512K"
case 9: "640K"
case 11: "768K"
case 13: "896K"
case 15: "1024K"
default: "???K"
] )
@ADREG = CONFR
@OUTREG = FERDisabled % (Configuration lshift 8)
% SingleFatal % ParityFatal
@ADREG = 0
for I = 0 to 3 do //for all quadrants
[ let GOODMOD = TMP!I; let TOP = 7; let BOTTOM = 0;
let LOGMOD = nil;
for N = 0 to 7 do //for all cabinets
[ test(GOODMOD & 1) eq 0
ifso
//Module not in configuration--assign high address
[ LOGMOD = LPC!TOP; TOP = TOP-1 ]
ifnot
[ LOGMOD = LPC!BOTTOM; BOTTOM = BOTTOM+1 ]
GOODMOD = GOODMOD rshift 1
//Reverse quadrant bits for hardware
LOGMOD = ((I&1) lshift 1) + ((I&2) rshift 1) + (N lshift 2) + (LOGMOD lshift 5) + ErrC
//Note that @ADREG must be quickly zeroed below
@ADREG = PLMR; @OUTREGP = LOGMOD; @ADREG = 0
]
]
if PPVal eq 3 then ZeroLM()
if not ZCDisabled do
[ let AVec = vec 1; AVec!0 = 0; AVec!1 = 0
until AVec!0 rshift 12 > MAINsize do
if ZeroCore(AVec,40000B) ne 0 do
[ @ADREG = RESR; @OUTREG = 125B; @ADREG = 0
PowerExit("Memory errors during core-zeroing")
]
]
SwitchWss(" EC ",ErrC,"on","off")
SwitchWss(" FER ",FERDisabled,"off","on")
SwitchWss(" SE ",SingleFatal,"non-fatal","fatal")
SwitchWss(" PE ",ParityFatal,"non-fatal","fatal")
SwitchWss("",ZCDisabled," Memory 0'ed","")
PowerExit("")
]
and SwitchWss(Str1,Stat,StrZ,StrNZ) be
[ Puts(CmdCommentStream,$ ); WssCSS(Str1)
WssCSS(Stat eq 0 ? StrZ,StrNZ)
]
and ReportCab(Status) be
[ if (Status & 1) ne 0 do WssCSS(" +5")
if (Status & 2) ne 0 do WssCSS(" +16")
if (Status & 4) ne 0 do WssCSS(" +20")
if (Status & 8) ne 0 do WssCSS(" -5")
]
//CabMask is a mask of the cabinets being turned on with B[15] being
//cabinet 0 and B[8] being cabinet 7. SupNow is a mask of the supplies
//being turned on now, and SupFinally a mask of the supplies ultimately
//being turned on. In each cabinet being turned on, if SupFinally are
//already on, they are left on, else only SupNow are put on.
//Error reports are made and power is turned off on any cabinets whose
//supplies fail to turn on within the timeout. Delay*4 msec is the max.
//wait for supplies to reach new status.
and CabinetsOn(CabMask,SupNow,SupFinally,Delay) = valof
[ let J,On,EverythingOn = vec 8,nil,true
//The vector J winds up with a mask of the supplies which should be on
//for each cabinet
for I = 0 to 7 do
[ J!I = -1 //-1 indicates don't check
if (CabMask & 1) ne 0 do
[ @ADREG = CABST+I+I; On = @INREG & 17B; J!I = On
if (On ne SupNow) & (On ne SupFinally) do
[ EverythingOn = false
J!I = ((On % SupNow) eq SupFinally) ? SupFinally,SupNow
@ADREG = CABPWR+I+I
@OUTREG = J!I
]
]
CabMask = CabMask rshift 1
]
@ADREG = 0; if EverythingOn then resultis true
let StartTime = vec 2; Timer(StartTime); DoubleNeg(StartTime)
while true do
[ let TimedOut = (GetTime(StartTime)-Delay) ge 0
EverythingOn = true
for I = 0 to 7 do
[ let ShouldBeOn = J!I; if ShouldBeOn ne -1 do
[ @ADREG = CABST+I+I; On = @INREG & 17B
ShouldBeOn = ShouldBeOn & not On
if ShouldBeOn ne 0 do
[ test TimedOut
ifso
[ WssCSS((EverythingOn ? "Power off on C",", C"))
EverythingOn = false; @ADREG = CABPWR+I+I; @OUTREG = 0
Puts(CmdCommentStream,60B+I); ReportCab(ShouldBeOn)
]
ifnot [ EverythingOn = false; break ]
]
]
]
if EverythingOn % TimedOut do
[ @ADREG = 0; resultis EverythingOn ]
]
]
//Turn off processor. Pstat is 0 for "both", 2 for "processor",
//3 for "memory"
and PowOff(S,garb,Buttons,Pstat) be
[ let DesiredPstat,NewPstat,Module,PowerOK = nil,nil,nil,true
@ADREG = PPSTAT; DesiredPstat = @INREG & Pstat
if Pstat ne 2 do
[ for I = 0 to 7 do [ @ADREG = CABPWR+I+I; @OUTREG = 0 ] ]
@ADREG = PPPWR; @OUTREG = DesiredPstat
Wait(6)
@ADREG = PPSTAT; NewPstat = @INREG & 3
if NewPstat ne DesiredPstat do
[ PowerOK = false
WssCSS(selecton (NewPstat & not DesiredPstat) into
[
case 1: "Processor stuck on"
case 2: "Port stuck on"
case 3: "Port & processor stuck on "
default: ""
] )
WssCSS(selecton(DesiredPstat & not NewPstat) into
[
case 1: "Processor off erroneously"
case 2: "Port off erroneously"
case 3: "Port & processor off erroneously"
default: ""
] )
UpdateDisplay()
]
if Pstat ne 2 do
[ if not PowerOK do [ Wait(15); Resets(CmdCommentStream) ]
for I = 0 to 7 do
[ @ADREG = CABST+I+I; NewPstat = @INREG & 17B
if NewPstat ne 0 do
[ PowerOK = false; Puts(CmdCommentStream,$C)
Puts(CmdCommentStream,60B+I); ReportCab(NewPstat)
WssCSS(" stuck on ")
]
]
]
PowerExit((PowerOK ? "Power off AOK",""))
]
and PPowerTest(S,garb,Buttons,val) be
[ WssCSS("Repeating port & processor power ")
WssCSS(selecton val into
[
case 0: "off"
case 17B: "on"
] )
QuitF = AddToEveryTimeList(PPTestLp,val)
FormMenu(CmdMDFS,FormCmdmenuText)
]
and MPowerTest(S,garb,Buttons,val) be
[ WssCSS("Module number (0-7): ")
UpdateDisplay()
Module = Gets(keys)-60B
if (Module ls 0)%(Module gr 7) do
[ Resets(CmdCommentStream); PowerExit("XXX"); return
]
Resets(CmdCommentStream); WssCSS("Repeating power ")
WssCSS(selecton val into
[
case 0: "off"
case 17B: "on"
] )
WssCSS(" on module ")
Puts(CmdCommentStream,60B+Module)
QuitF = AddToEveryTimeList(MPTestLp,val)
FormMenu(CmdMDFS,FormCmdmenuText)
]
and PPTestLp(val) be
[ @ADREG = PPPWR; @OUTREG = val
]
and MPTestLp(val) be
[ @ADREG = CABPWR+Module+Module; @OUTREG = val
]
and Countbits(X) = valof
[ let N = 0
while X ne 0 do [ if (X & 1) ne 0 then N = N+1; X = X rshift 1 ]
resultis N
]
//Elapsed time returned as multiple of 4 msec
and GetTime(StartTime) = valof
[ let Now = vec 2; Timer(Now)
DoubleAdd(Now,StartTime)
resultis (Now!1 rshift 2)+(Now!0 lshift 14)+13
]