// AltIOUtilb.bcpl -- utility routines for AltIO // Last modified April 17, 1978 2:38 PM get "streams.d" get "altio.decl" external [ //outgoing procedures LoadSaveFile; ZeroMaxcMem; BootMicroExec MemReadBlock32; MemWriteBlock32; MemReadBlock40; MemWriteBlock40 MemZero; RMWBitAbsolute; RMWBitRelative //incoming procedures OpenFile; Ws; PutTemplate; Gets; Closes; Endofs; SysErr MyFrame; GotoFrame; Zero; Usc MemRead; MemWrite; MemRMW; DoubleIncrement; DoubleAdd; Block MemReadBlock32A; MemWriteBlock32A; MemReadBlock40A MemWriteBlock40A; MemZeroA; SetOneMaxcBit MemReadAbsolute; MemWriteAbsolute; MemRMWAbsolute MemReadRelative; MemWriteRelative; MemRMWRelative AltIOReset; StartMaxc; StopMaxc; ResetMaxc; ConfigureMemory DisplayMemCode //incoming statics dsp; sysZone; adrMTBS; numMemCabs MaxcBootLoader; lenMaxcBootLoader ] // --------------------------------------------------------------------------- let LoadSaveFile(s) = valof // --------------------------------------------------------------------------- //load into Maxc memory a save-format file whose name is the //string s. [ let str = OpenFile(s, ksTypeReadOnly, charItem) if str eq 0 then [ PutTemplate(dsp, "File $S not found", s); resultis false ] StopMaxc() unless ZeroMaxcMem() resultis false str>>ST.error = LoadErrors //catch running off end of file str>>ST.par1 = MyFrame() let maxcAdr, maxcData = vec 2, vec 3 let errorCode = 0 [ unless GetMaxcWord(str, maxcData) do [ Ws("Premature end of file, probable bad format") errorCode = -1 break ] if maxcData!0 ge 0 then [ unless Endofs(str) do [ Ws("End block before eof, probable bad format") errorCode = -1 break ] //end block, put starting address in location 7 maxcData!0 = 0; maxcData!1 = maxcData!1 & #37777 MemWriteAbsolute(aSTADR, maxcData) //put something reasonable in MTBS and DLSBS maxcData!1 = #200 rshift 4; maxcData!2 = 0 MemWriteAbsolute(aMTBS, maxcData) maxcData!1 = #600 rshift 4 MemWriteAbsolute(aDLSBS, maxcData) AltIOReset() //reset Alto state ResetMaxc() //reset Maxc so "Resume" will start program break ] //this is an iowd, set up to transfer data block if (maxcData!0 & #140000) ne #140000 then [ Ws("Block size larger than 2↑16, probable bad format") errorCode = -1 break ] let count = maxcData!0 lshift 2 + maxcData!1 rshift 14 maxcAdr!0 = maxcData!1 & #37777 maxcAdr!1 = maxcData!2 [ DoubleIncrement(maxcAdr, #10000) unless GetMaxcWord(str, maxcData) break errorCode = MemWrite(maxcAdr, maxcData) count = count+1 ] repeatuntil count eq 0 % errorCode ne 0 ] repeatwhile errorCode eq 0 if errorCode gr 0 then DisplayMemCode(errorCode) Closes(str) resultis errorCode eq 0 ] // --------------------------------------------------------------------------- and GetMaxcWord(str, maxcData) = valof // --------------------------------------------------------------------------- [ let b1 = Gets(str) let b2 = Gets(str) let b3 = Gets(str) let b4 = Gets(str) let b5 = Gets(str) maxcData!0 = b1 lshift 12 + b2 lshift 4 + b3 rshift 4 maxcData!1 = b3 lshift 12 + b4 lshift 4 + b5 rshift 4 maxcData!2 = b5 lshift 12 resultis true ] // --------------------------------------------------------------------------- and LoadErrors(str, ec) be // --------------------------------------------------------------------------- [ test ec eq 1302 ifso GotoFrame(str>>ST.par1, false) //end of file ifnot SysErr(str, ec) //other error ] // --------------------------------------------------------------------------- and ZeroMaxcMem() = valof // --------------------------------------------------------------------------- //zeroes all of Maxc memory in preparation for loading a program. [ let maxcAdr = vec 2 Zero(maxcAdr, 2) for i = 0 to 4*numMemCabs-1 do [ let code = MemZero(maxcAdr, #100000) //do 2↑15 words if code ne 0 then [ DisplayMemCode(code); resultis false ] ] resultis true ] // --------------------------------------------------------------------------- and BootMicroExec(diskUnit, saveArea, autoStart) = valof // --------------------------------------------------------------------------- //loads into Maxc memory and starts the disk boot loader which //in turn starts Micro-Exec. diskUnit and saveArea specify //the disk address to load Micro-Exec from, and autoStart //supplies the top 16 bits of the "switches" (Micro-Exec //does an automatic start of Tenex if bit 0 is set). [ manifest loaderPage = #347 //page in which loader runs //normalize processor state ResetMaxc() ConfigureMemory(0, 0) //setup the first word of the loader to contain the unit number //in bits 11-13 and #6221 - #40*saveArea in bits 18-35. MaxcBootLoader!0 = diskUnit lshift 2 let diskAdr = #6221 - #40*saveArea MaxcBootLoader!1 = diskAdr rshift 4 MaxcBootLoader!2 = diskAdr lshift 12 //copy the loader to Maxc memory let v = vec 2 v!0 = loaderPage lshift 5 v!1 = 0 let code = MemWriteBlock40(v, MaxcBootLoader, lenMaxcBootLoader) if code ne 0 then [ DisplayMemCode(code); resultis false ] //set starting address and auto-start parameter, then go. MemWriteAbsolute(aSTADR, table [ 0; loaderPage lshift 5; #10000 ]) v!0 = autoStart v!1, v!2 = 0, 0 MemWriteAbsolute(aSWICH, v) StartMaxc() resultis true ] // --------------------------------------------------------------------------- and MemReadBlock32(maxcAdr, maxcData, count) = // --------------------------------------------------------------------------- MemBlockTransfer(MemReadBlock32A, maxcAdr, maxcData, count, 2) // --------------------------------------------------------------------------- and MemWriteBlock32(maxcAdr, maxcData, count) = // --------------------------------------------------------------------------- MemBlockTransfer(MemWriteBlock32A, maxcAdr, maxcData, count, 2) // --------------------------------------------------------------------------- and MemReadBlock40(maxcAdr, maxcData, count) = // --------------------------------------------------------------------------- MemBlockTransfer(MemReadBlock40A, maxcAdr, maxcData, count, 3) // --------------------------------------------------------------------------- and MemWriteBlock40(maxcAdr, maxcData, count) = // --------------------------------------------------------------------------- MemBlockTransfer(MemWriteBlock40A, maxcAdr, maxcData, count, 3) // --------------------------------------------------------------------------- and MemZero(maxcAdr, count) = // --------------------------------------------------------------------------- MemBlockTransfer(MemZeroA, maxcAdr, nil, count, 3) // --------------------------------------------------------------------------- and MemBlockTransfer(Operation, maxcAdr, maxcData, count, inc) = valof // --------------------------------------------------------------------------- //Perform some flavor of Maxc memory block transfer. //The transfer is done a piece at a time with calls to Block() //interspersed to prevent excessive latency to other contexts. //inc is the Alto address increment for each Maxc word [ let code = nil while count ne 0 do [ let c = Usc(count, maxBlt) ls 0? count, maxBlt code = Operation(maxcAdr, maxcData, c) if code ne 0 break maxcData = maxcData + c*inc count = count-c Block() ] resultis code ] // --------------------------------------------------------------------------- and RMWBitAbsolute(adr, bitNumber) = valof // --------------------------------------------------------------------------- //set bit "bitNumber" in Maxc location "adr" [ let maxcData = vec 3 SetOneMaxcBit(maxcData, bitNumber) resultis MemRMWAbsolute(adr, maxcData) ] // ---------------------------------------------------------------- and RMWBitRelative(displacement, bitNumber, base; numargs na) = valof // ---------------------------------------------------------------- //set bit "bitNumber" in Maxc location "adr" relative to "base" [ let maxcData = vec 3 SetOneMaxcBit(maxcData, bitNumber) resultis MemRMWRelative(displacement, maxcData, (na ls 3? adrMTBS, base)) ]