// AltIOInit.bcpl -- Initialization for AltIO // Last modified March 14, 1981 3:25 PM get "altio.decl" get "altiomaxc2.decl" get "pup0.decl" get "streams.d" get "AltoDefs.d" external [ //outgoing procedures AltIOInit //incoming procedures GetFixed; MyFrame; CallersFrame InitializeZone; Allocate; Free; Zero; MoveBlock LogOpen; AltIOReset; AltIOFinish; OpenFile; CallSwat; FileLength SysErr; Resets; ReadBlock; Closes; SetupReadParam; ReadParam CreateDisplayStream; ShowDisplayStream; Enqueue InitializeInterrupt; FindInterruptMask; Timer InitializeContext; AltIOCommand; UpdateRegisterDisplay; KeySwitch MaxcKeyboard; MaxcTerminal; MaxcWatcher; PutsWithCursor MaxcTerminal1; DiabloError; CreateDiabloStream LoadRam; Ws; Wss; Ding; Dismiss; PutTemplate; InitBcplRuntime OutputSMI; OutputSMITest; StopMaxcForcefully; ClockInterrupt ResetMemory; InputSMI; InitAltoEther; InitAltoImp; AltIOParityHandler AltIOSwatProc; ZeroMaxcMem; ConfigureMemory //outgoing statics numPBI; debug; savedParityHandler; altIOSavedSCP ctxQ; altIOSavedUFP; tDspLines; numMemCabs; stdMemConf; topStack; lenTopStack //incoming statics dsp; sysZone; lvSysZone; sysFont; fpSysFont; lvUserFinishProc fpComCm; switchStartTenex; switchBoot; switchHalt; protected loadFilename; silentBoot; sysDisk; versionText; lvAbortFlag tDsp; hDsp; hShow; hNoShow; commandCtx; maxcKeysCtx keysCtx; cursorDsp; DisplayPuts; diabloStr; bootDiskUnit adrMTBS; adrDLSBS; RamImage; dlsOutputChar; lvSwatContextProc maxcClock; lastTime; clockMask; ClockSecond lenPup; lenPBI; pbiIQ; pbiFreeQ; ndbQ; pupCtx; lenPupCtx etherNDB; impNDB ] static [ ctxQ; tDspLines; numMemCabs; stdMemConf altIOSavedUFP; altIOSavedSCP savedParityHandler = 0 lastShownStream = 0 numPBI = 0 //number of pbis to allocate initially spyBuffer = 0 debug = false switchZero = false topStack; lenTopStack ] manifest [ endCode = #335 lenCDsp = 5000 //space for command display bitmap lenTDsp = 17000 //space for maxc tty display bitmap ] structure String: [ length byte; char^1,255 byte ] // --------------------------------------------------------------------------- let AltIOInit() be // --------------------------------------------------------------------------- [ // Load the special Ram microcode let res = LoadRam(RamImage, true) //load and boot if res ne 0 then CallSwat("LoadRam failed") silentBoot = true InitBcplRuntime() @endCode = LoadRam // Throw away LoadRam and RamImage // First allocate some big blocks using GetFixed. This ensures // that we will have less than 32k left to pass to InitializeZone. dsp = GetFixed(lenCDsp) //command display window tDsp = GetFixed(lenTDsp) //maxc tty display window // Turn remaining storage into a zone topStack = MyFrame()-1000 //top-level stack during initialization lenTopStack = CallersFrame()-topStack sysZone = InitializeZone(@endCode, topStack-@endCode, SysErr, (debug? SysErr, 0)) @lvSysZone = sysZone @endCode = topStack // Reinitialize some things we Junta'ed away LogOpen(sysZone) //Junta closed the log but we want it open altIOSavedUFP = @lvUserFinishProc @lvUserFinishProc = AltIOFinish altIOSavedSCP = @lvSwatContextProc @lvSwatContextProc = AltIOSwatProc // Read in the system font let fontStr = OpenFile("SysFont.al", ksTypeReadOnly, 0, 0, fpSysFont) if fontStr eq 0 then CallSwat("Can't open SysFont.al") let fontSize = (FileLength(fontStr)+1) rshift 1 Resets(fontStr) sysFont = Allocate(sysZone, fontSize) ReadBlock(fontStr,sysFont, fontSize) Closes(fontStr) let fontHeight = (sysFont!0+1) & #177776 let lineWords = lDCB + 38*fontHeight sysFont = sysFont+2 // Initialize the display ShowNext(MakeBar(5, 0)) //10 scan lines of white at top //2 lines for register display header hDsp = CreateDisplayStream(2, Allocate(sysZone, 2*lineWords+20), 2*lineWords+10, sysFont, 0, DSstopright) ShowNext(hDsp) //2 one-liners for updated display (show only the first) hShow = CreateDisplayStream(1, Allocate(sysZone, lineWords+20), lineWords+10, sysFont, 0, DSstopright) hNoShow = CreateDisplayStream(1, Allocate(sysZone, lineWords+20), lineWords+10, sysFont, 0, DSstopright) ShowNext(hShow) ShowNext(MakeBar(2, 0)) //4 scan lines of white ShowNext(MakeBar(2, 1)) //4 scan lines of black hNoShow>>DS.ldcb>>DCB.next = hShow>>DS.ldcb>>DCB.next // AltIOInit (cont'd) // Command display stream doesn't need a full bitmap let cmdScanLines = 808-(10+2+3*fontHeight+8+4+lenTDsp/38+4) dsp = CreateDisplayStream(cmdScanLines/fontHeight, dsp, lenCDsp-10, sysFont) DisplayPuts = dsp>>ST.puts dsp>>ST.puts = PutsWithCursor ShowNext(dsp) ShowNext(MakeBar(2,1)) //4 scan lines of black // Maxc tty display stream does need a full bitmap tDspLines = (lenTDsp-20)/lineWords tDsp = CreateDisplayStream(tDspLines, tDsp, lenTDsp-10, sysFont, 0, DSnone) ShowNext(tDsp) ShowNext(MakeBar(2, 1)) //4 scan lines of black PutTemplate(dsp, "$S - command window", versionText) Wss(tDsp, "Maxc console terminal window*n") // Initialize contexts ctxQ = Allocate(sysZone, 2) ctxQ!0 = 0 commandCtx = MakeContext(AltIOCommand, 1000) maxcKeysCtx = MakeContext(MaxcKeyboard, 100) keysCtx = commandCtx //initially type to command window cursorDsp = dsp MakeContext(MaxcTerminal, 200) MakeContext(MaxcTerminal1, 200) MakeContext(UpdateRegisterDisplay, 200) MakeContext(KeySwitch, 100) MakeContext(MaxcWatcher, 500) //initialize Diablo printer diabloStr = CreateDiabloStream(0, 0, 0, 0, 25*6) diabloStr>>ST.error = DiabloError //initialize Pup package InitAltIOPup() //check for Maxc being powered on, and find out how much //memory there is. OutputSMITest(#16) //put SMI in normal mode StopMaxcForcefully() //make sure the processor isn't running if InputSMI(smiPPSTAT) ne 3 then Punt("*nProcessor or port not turned on, can't do anything") let lastModuleOff = false stdMemConf, numMemCabs = 0, 0 for physMod = 0 to 3 do [ let logMod = nil test InputSMI(smiCABST+2*physMod) eq #17 ifso [ logMod = table [ 4; 0; 6; 2 ]!numMemCabs numMemCabs = numMemCabs+1 if lastModuleOff then [ Ws("*nUnusual memory configuration: ") PutTemplate(dsp, "Cabinet $O off but $O on", physMod-1, physMod) Ding(dsp) lastModuleOff = false ] ] ifnot [ lastModuleOff = true logMod = 3 ] stdMemConf = stdMemConf + logMod lshift (12-4*physMod) ] if numMemCabs eq 0 then Punt("*nNo memories turned on, can't do anything") // AltIOInit (cont'd) //prepare to scan command line let comStr = OpenFile("Com.cm", ksTypeReadOnly, charItem, 0, fpComCm) if comStr eq 0 then Punt("*Can't open Com.cm") let stringVec = Allocate(sysZone, 128) let switchVec = Allocate(sysZone, 128) //read program name and global switches SetupReadParam(0, 0, comStr, switchVec) for i = 1 to switchVec!0 do switchon switchVec!i into [ case $S: case $s: switchStartTenex = true //fall into case $B case $B: case $b: switchBoot = true //fall into case $Z case $Z: case $z: [ switchZero = true; endcase ] case $H: case $h: [ switchHalt = true; endcase ] case $P: case $p: [ protected = true; endcase ] case $R: case $r: [ ResetMemory(); endcase ] //full memory reset case $D: case $d: [ debug = true; endcase ] default: PutTemplate(dsp,"*nBad global switch /$C, ignored", switchVec!i) ] //read parameters and local switches [ if ReadParam($P, -1, stringVec, switchVec) eq -1 then break if switchVec!0 ne 1 then [ CantParse(stringVec, switchVec); loop] switchon switchVec!1 into [ case $L: case $l: //save file from which to load memory [ let length = stringVec>>String.length rshift 1 +1 loadFilename = Allocate(sysZone, length+2) //room for .Sav MoveBlock(loadFilename, stringVec, length) endcase ] case $U: case $u: //unit number for booting Micro-Exec [ let char = stringVec>>String.char^1 test stringVec>>String.length eq 1 & char ge $0 & char le $7 ifso bootDiskUnit = char-$0 ifnot CantParse(stringVec, switchVec) endcase ] default: CantParse(stringVec, switchVec) ] ] repeat Free(sysZone, stringVec) Free(sysZone, switchVec) Closes(comStr) // AltIOInit (cont'd) //put hardware and software in standard initial state adrMTBS,adrDLSBS = Allocate(sysZone, 2),Allocate(sysZone, 2) dlsOutputChar = Allocate(sysZone, numDLSLines) if switchZero then [ ConfigureMemory(0, 0); ZeroMaxcMem() ] AltIOReset() //simulate i/o reset //initialize clock interrupt maxcClock = Allocate(sysZone, 3) lastTime = Allocate(sysZone, 2) Timer(lastTime) clockMask = FindInterruptMask(1) InitializeInterrupt(Allocate(sysZone, 75), 75, clockMask, ClockInterrupt) ClockInterrupt() //get clock going //the Maxc2 Alto's clock is a bit slow. //set clock constants in OS to compensate. if ClockSecond ne 0 then MoveBlock(ClockSecond, table [ #31; #120162 ], 2) //1679474 //install own parity handler savedParityHandler = @#501 @#501 = AltIOParityHandler //diable shift-swat abort @lvAbortFlag = 1 // Install own cursor pattern MoveBlock(#431, table [ #110000; #170000; #110000; #113000; #114400; #007400; #004620; #004540 #000157; #000150; #074230; #004010; #034017; #040000; #074000; #000000 ], 16) // *** for performance debugging *** if debug then spyBuffer = Allocate(sysZone, 1000) ] // --------------------------------------------------------------------------- and MakeBar(height, color) = valof // --------------------------------------------------------------------------- //make a bar 2*height scan lines high of specified color (black=1) [ structure Bar: [ firstDCB word; lastDCB word; dcb: @DCB ] manifest lenBar = size Bar/16 let bar = Allocate(sysZone, lenBar, false, true) //even word Zero(bar, lenBar) bar>>Bar.firstDCB = lv bar>>Bar.dcb bar>>Bar.lastDCB = lv bar>>Bar.dcb bar>>Bar.dcb.background = color bar>>Bar.dcb.height = height resultis bar ] // --------------------------------------------------------------------------- and ShowNext(str) be // --------------------------------------------------------------------------- //show display stream immediately below lastShownStream [ ShowDisplayStream(str, (lastShownStream eq 0? DSalone, DSbelow), lastShownStream) lastShownStream = str ] // --------------------------------------------------------------------------- and MakeContext(proc, len) = valof // --------------------------------------------------------------------------- [ let ctx = InitializeContext(Allocate(sysZone, len), len, proc) Enqueue(ctxQ, ctx) resultis ctx ] // --------------------------------------------------------------------------- and InitAltIOPup() be // --------------------------------------------------------------------------- [ // Since we are not using Pup level 1, we have to do a lot of // initialization ourselves // The Pup portion of a PBI must be a multiple of 4 bytes. lenPup = (pupOvBytes+defaultPupDataBytes)/2+1 & #177776 lenPBI = lenPBIOverhead+lenPup let level1Qs = Allocate(sysZone, 6) Zero(level1Qs, 6) pbiIQ = level1Qs pbiFreeQ = level1Qs+2 ndbQ = level1Qs+4 for i = 1 to numPBI do Enqueue(pbiFreeQ, Allocate(sysZone, lenPBI)) InitAltoEther(sysZone, ctxQ, 0) etherNDB = ndbQ!0 // the one and only Ethernet NDB InitAltoImp(sysZone, ctxQ) // Wire-in the local net numbers (yuk) etherNDB>>NDB.localNet = netEther impNDB>>NDB.localNet = netArpa // Allocate but do not initialize context for Pup process. // It will get reset by later AltIOReset pupCtx = Allocate(sysZone, lenPupCtx) ] // --------------------------------------------------------------------------- and Punt(string) be // --------------------------------------------------------------------------- [ Ws(string) Ding(dsp) Dismiss(500) //5 seconds to let user see message finish ] // --------------------------------------------------------------------------- and CantParse(stringVec,switchVec) be // --------------------------------------------------------------------------- PutTemplate(dsp, "*nCan't parse *"$S$C$US*" -- ignored", stringVec, (switchVec!0 eq 0? $*s,$/), switchVec)