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