// AltIOMaxc2.bcpl -- code implementing communication with Maxc // and error monitoring // Last modified April 17, 1978 2:57 PM get "altio.decl" get "altiomaxc2.decl" external [ //outgoing procedures MaxcWatcher; ClockInterrupt; SignalMaxc; AltIOReset StartMaxc; StopMaxc; StopMaxcForcefully; ResetMaxc TakeDLSOutput; GiveDLSInput; ConfigureMemory; ResetMemory MaxcState; PrintMaxcState; StartEmulator ReadLM; ReadSM //incoming procedures Block; Allocate; Free; MoveBlock; SetBlock; CallSwat; Timer DoubleIncrement; DoubleDifference; Puts; Ws SetTimer; TimerHasExpired; PupReset; ImpReset InputSMI; OutputSMI; OutputSMIPulse; InputSMIErrors; OutputSMITest ExecuteMicroInstruction; LoadBus; ReadBus; DisplaceMaxcAdr FindZeroMaxcBit; SetOneMaxcBit; IncrementMaxcWord StartIntervalTimer; DisableInterrupts; EnableInterrupts MemReadAbsolute; MemWriteAbsolute; MemRMWAbsolute MemReadRelative; MemWriteRelative; MemRMWRelative RMWBitAbsolute; RMWBitRelative; MemWriteBlock40A //outgoing statics adrMTBS; adrDLSBS; maxcRunning; resetExecuted; dlsOutputChar maxcClock; lastTime; interruptInterval; clockMask fatalError; stdMemConf //incoming statics dsp; updateDisplayValid; sysZone pupInputRequest; pupOutputRequest; impInputRequest; impOutputRequest ] static [ adrMTBS; adrDLSBS dlsOutputChar maxcRunning = false resetExecuted = false smiErr = 0 fatalSE = false fatalPBF = false fatalError = false clockUpdateEnabled = false interruptInterval = 17 maxcClock; lastTime; interruptTimer; clockMask ] // --------------------------------------------------------------------------- let MaxcWatcher() be // --------------------------------------------------------------------------- //process that watches for Maxc i/o requests and errors [ Block() unless maxcRunning do [ //watch only for memory errors if Maxc not running if InputSMI(smiJKERRS) ne 0 % InputSMI(smiLMERRS) ne 0 then [ let qErr = vec 2 ReadMemErrors(qErr) if FatalMemError(qErr) then [ ReportMemErrorsToDisplay(qErr) fatalError = true ] ] loop ] //all places that read the SMI error register must update smiErr. //this is because reading the register causes it to be cleared, //and signals such as COMA may be lost if we aren't careful smiErr = (smiErr % InputSMIErrors()) & smiErrorMask if smiErr ne 0 then [ if smiErr<>QErr^q & mask) ne 0 then Puts(dsp, $J+q) ] ] ] // --------------------------------------------------------------------------- and ReportMemErrorsToMaxc(qErr) be // --------------------------------------------------------------------------- [ //figure out which kind of error to hand Maxc manifest timeMask = qeTimeout + qeTimeout lshift 8 let errBit = (qErr!0 & timeMask) ne 0 % (qErr!1 & timeMask) ne 0? nmNXM, nmPARERR RMWBitAbsolute(aNVMAX, errBit) //set NXM or PARERR //hand over assorted other interesting information MemWriteRelative(xMEMER, qErr) let uInst = table [ #040102; #077546; #120001; #000000; #003400 // B_MAR #040102; #077546; #100001; #000000; #003400 // B_MDR #040102; #077546; #110001; #000000; #003400 // B_MDRL #040102; #077546; #160001; #000000; #003400 // B_KMAR #040102; #077546; #140001; #000000; #003400 // B_KMDR #040102; #077546; #150001; #000000; #003400 // B_KMDRL ] let errorData = vec 3*6 for i = 0 to 15 by 3 do [ ExecuteMicroInstruction(uInst) uInst = uInst+5 ReadBus(errorData+i) ] let errorAdr = vec 1 DisplaceMaxcAdr(xMAR, errorAdr) MemWriteBlock40A(errorAdr, errorData, 6) MemWriteRelative(xPSCAN, table [ -1; -1; -1 ]) ] // --------------------------------------------------------------------------- and DLSOutputRequest() be // --------------------------------------------------------------------------- [ let maxcData = vec 3 MemReadRelative(xDLSO, maxcData, adrDLSBS) //read request bits [ let line = FindZeroMaxcBit(maxcData) if line ls 0 return //no lines requesting output if line ls numDLSLines then [ //found line requesting output, copy the character MemReadRelative(xDLSB+2*line+1, maxcData, adrDLSBS) dlsOutputChar!line = maxcData!0 ] SetOneMaxcBit(maxcData, line) MemRMWRelative(xDLSO, maxcData, adrDLSBS) //reset line request ] repeat ] // --------------------------------------------------------------------------- and TakeDLSOutput(line) = valof // --------------------------------------------------------------------------- //procedure called externally to wait for a DLS output request //on line and return the character. [ Block() repeatwhile dlsOutputChar!line eq -1 let char = dlsOutputChar!line dlsOutputChar!line = -1 //no character pending now RMWBitRelative(xDLSOD, line, adrDLSBS) //set done bit for line RMWBitAbsolute(aNVMAX, nmDLSDN) //signal DLS done SignalMaxc() resultis char ] // --------------------------------------------------------------------------- and GiveDLSInput(line, char) be // --------------------------------------------------------------------------- //procedure called externally to send a DLS input character to Maxc [ MemWriteRelative(xDLSB+2*line, lv char, adrDLSBS) //give char to Maxc RMWBitRelative(xDLSIN, line, adrDLSBS) //set done bit for line RMWBitAbsolute(aNVMAX, nmDLSDN) //signal DLS done SignalMaxc() ] // --------------------------------------------------------------------------- and AltIOReset() be // --------------------------------------------------------------------------- //perform i/o reset operation [ OutputSMITest(#16) //put SMI in normal mode OutputSMI(smiRESR, allResetErrors) //reset memory error latches let maxcData = vec 3 let zeroWord = table [ 0; 0; 0 ] let oneWord = table [ #177777; #177777; #177400 ] //read the addresses of the communication regions MemReadAbsolute(aMTBS, maxcData) MoveBlock(adrMTBS, maxcData+1, 2) MemReadAbsolute(aDLSBS, maxcData) MoveBlock(adrDLSBS, maxcData+1, 2) //reset DLS state SetBlock(dlsOutputChar, -1, numDLSLines) //no output chars pending MemWriteRelative(xDLSOD, zeroWord, adrDLSBS) //reset output done MemWriteRelative(xDLSO, oneWord, adrDLSBS) //reset output requests MemWriteRelative(xDLSIN, zeroWord, adrDLSBS) //reset input done //reset Maxc clock SetClockInterval(0) //reset the Pup and Imp processes PupReset() ImpReset() //finally, reset NVMAX and MAXNV to their idle states MemWriteAbsolute(aNVMAX, zeroWord) MemWriteAbsolute(aMAXNV, oneWord) ] // --------------------------------------------------------------------------- and SignalMaxc() be // --------------------------------------------------------------------------- if maxcRunning then OutputSMI(smiCR, not (crNormal+crStrobe)) // --------------------------------------------------------------------------- and StartMaxc(microAdr; numargs na) be // --------------------------------------------------------------------------- //start Maxc running at the specified micro-address, or just //resume it if microAdr is not specified [ if na gr 0 then [ let maxcData = vec 3 maxcData!0 = 0 maxcData!1 = microAdr rshift 4 maxcData!2 = microAdr lshift 12 LoadBus(maxcData) ExecuteMicroInstruction( // NPC_BR, ENPC table [ #040102; #077546; #000000; #020000; #113600 ]) DoubleIncrement(maxcData+1, #10000) LoadBus(maxcData) ExecuteMicroInstruction( // NPC_BR, ENPC, EIMA table [ #040102; #077546; #000000; #020000; #133600 ]) ExecuteMicroInstruction( // IRET, INHINT table [ #040102; #077546; #000152; #000000; #103400 ]) ResetArm() //reset bipolar memory errors ] ExecuteMicroInstruction( // WRESTART, KWRESTART table [ #040102; #077546; #000110; #160000; #103400 ]) ExecuteMicroInstruction( // FRZBALUBC, EIC, EB, ENPC, EIMA, NOTSS, Strobe table [ #040102; #077546; #000155; #000000; #177140 ]) //now that Maxc is running again, read and reset the SMI error //register, ignoring FER (which will be on) but being careful //not to lose other signals (COMA). smiErr = (smiErr % InputSMIErrors()) & (smiErrorMask - #100000 rshift offset SMIErr.fer) maxcRunning = true ] // --------------------------------------------------------------------------- and StopMaxc() be // --------------------------------------------------------------------------- [ if maxcRunning then [ RMWBitAbsolute(aNVMAX, nmHALT) //request console halt SignalMaxc() maxcRunning = false //shut off MaxcWatcher process let timer, state = nil, nil SetTimer(lv timer, 5) //wait 50 ms for request to take [ Block() state = MaxcState() ] repeatuntil state ne stateRunning % TimerHasExpired(lv timer) unless state eq stateBreakpoint do [ Ws("*nUnclean micro stop: ") test state eq stateRunning ifso //Maxc didn't stop, halt it by force. [ StopMaxcForcefully() Ws("Maxc didn't respond to halt request") ] ifnot PrintMaxcState(state) ] ] ] // --------------------------------------------------------------------------- and StopMaxcForcefully() be // --------------------------------------------------------------------------- OutputSMI(smiCR, not (crEIC+crEB+crEIMA+crENPC+crIntOn)) // --------------------------------------------------------------------------- and ResetMaxc() be // --------------------------------------------------------------------------- //do emulator reset in preparation for starting a program [ StopMaxc() StartMaxc(emulatorReset) StopMaxc() //wait for reset to complete MemWriteAbsolute(aNVMAX, table [ 0; 0; 0 ]) //reset Alto requests ] // --------------------------------------------------------------------------- and MaxcState() = valof // --------------------------------------------------------------------------- [ let runReg = InputSMI(smiRUN) if runReg<