//Run.bcpl - Run a Mesa Image file - R. Johnsson //last modified by Johnsson: September 30, 1980 12:22 PM //Bldr/L/V 200/W Front.run/S Run MBoot Mesa-Nova1 Mesa-Nova2 MesaImage XMesaImage XMesaOverflow Configuration ReadPram // This program may be run as the main program or may be driven // by the more general RunMesa.bcpl get "AltoDefs.d" get "SysDefs.d" get "AltoFileSys.d" get "Streams.d" get "RunMesa.d" external // ReadPram [ LoadPackedRAM ] static [ bootList bootLoader bootMap bootMapSize memoryBanks = allBanks // bit mask (100000b rshift bank) microcodeLoaded = 0 // bit mask (1 lshift bank) tempBootList tempBootMap ] manifest [ lvEndCode = #335 ] let RunThisFile (layout, up, cfa) be [ until up!0 eq 0 do [ if up>>UPE.type eq mesaMemoryMask then [ memoryBanks = up!1; break ] up = up + up>>UPE.length ] let file = CreateDiskStream(lv cfa>>CFA.fp, ksTypeReadOnly) JumpToFa(file, lv cfa>>CFA.fa) if Endofs(file) then [ GiveMicrocodeVersion() Closes(file) file = CreateDiskStream(lv cfa>>CFA.fp, ksTypeReadWrite) JumpToFa(file, lv cfa>>CFA.fa) MoveToPageBoundary(file) // will extend to page boundary // patch word 1 of file (SV.H.length) to be the page number of // the last page in the file before the image file. GetCompleteFa(file, cfa) SetFilePos(file, 0, 2) Puts(file, cfa>>CFA.fa.pageNumber-1) Closes(file) finish ] let header = vec lImagePrefix-1 ReadBlock(file,header,lImagePrefix) DetermineConfiguration() LoadInternalMicrocode() Run(file,header) ] and Run(image,pHeader) be [ // image prefix has been read and is pointed to by pHeader // stream is positioned just after header @lvEndCode = MesaImage // reclaim space tempBootMap = AllocCodeSpace(3*256) tempBootList = AllocCodeSpace(lBootList) Zero(tempBootList, lBootList) let header = AllocCodeSpace(lImagePrefix) MoveBlock(header, pHeader, lImagePrefix) let intvec = AllocCodeSpace(16) bootMap = header>>ImagePrefix.diskAddresses //read in the page address-count words until a 0 is found let pageMap=vec 250 let mapLast=nil for i=0 to 250 do [ pageMap!i=Gets(image) if pageMap!i eq 0 then [ mapLast=i break ] ] MoveToPageBoundary(image) let cfa = vec lCFA-1 GetCompleteFa(image, cfa) let daOfFirstPage = nil RealDiskDA(sysDisk, cfa>>CFA.fa.da, lv daOfFirstPage) FindSpace(pageMap, mapLast, lv bootLoader, lv bootList) //get stuff ready for page zero FixMESANOVA(tempBootList) SetupBootMap(pageMap, mapLast, tempBootMap, cfa) FixMBOOT(tempBootList,bootMap,daOfFirstPage) FixInterrupts(tempBootList, intvec) let initialstate = xNovaCode+MesaNovaSize2 MakeBltItem(lv tempBootList>>BootList.blt↑blInitialState, lv header>>ImagePrefix.state, initialstate, lStateVector) tempBootList>>BootList.initialState = initialstate; MakeBltItem(lv tempBootList>>BootList.blt↑blPageMap, tempBootMap, bootMap, bootMapSize) @lvUserFinishProc = FinishPtr Junta(levBasic, Go) ] and Go() be [ MoveBlock(bootList, tempBootList, 256); MoveBlock(bootLoader, MBOOT, 256); bootLoader(bootList) ] and AllocCodeSpace(length) = valof [ let p = @lvEndCode @lvEndCode = p + length resultis p ] and MoveToPageBoundary(stream) be [ let fa = vec lFA-1 GetCurrentFa(stream,fa) if fa>>FA.charPos eq 0 then return PositionPage(stream, fa>>FA.pageNumber+1) ] and FindSpace(pageMap,mapLast,lvLoader,lvList) be [ //find space for boot loader and pagemap which does not interfere //with this program or the image to be loaded let inUse=vec 15 Zero(inUse, 16) bootMapSize = lFP+1+1 // FP + page + terminator let nexti = nil let i = 0 until i eq mapLast do [ let item = lv (pageMap!i) test item>>MapItem.tag ifso [ nexti = i+lchangeMapItem bootMapSize = bootMapSize + 2 ] ifnot nexti = i+lnormalMapItem let page, count = item>>MapItem.page, item>>MapItem.count bootMapSize = bootMapSize + count for j=page to page+count-1 do [ let wd = j rshift 4 inUse!(wd) = inUse!(wd) % (#100000 rshift (j)) ] i = nexti ] // The bootMap page(s) is not available either for j = bootMap rshift 8 to (bootMap rshift 8)+((bootMapSize+255) rshift 8)-1 do [ let wd = j rshift 4 inUse!(wd) = inUse!(wd) % (#100000 rshift (j)) ] let lastpage= #174000 rshift 8 let firstpage=(@lvEndCode+255) rshift 8 let p = AllocPages(inUse, firstpage, lastpage, 1) @lvLoader = p lshift 8 if p ne 0 then p = AllocPages(inUse, p+1, lastpage, 1) @lvList = p lshift 8 if @lvList eq 0 then AbortMsg("*NCan't find enough space for loader.") ] and AllocPages(map, first, last, npages) = valof [ let n = 0 for i = first to last do [ test (map!(i rshift 4) & (#100000 rshift (i & #17))) eq 0 ifso [ n = n + 1; if n eq npages then resultis i-n+1 ] ifnot n = 0 ] resultis 0 ] and SetupBootMap(pageMap, mapLast, pmLoc, cfa) be [ MoveBlock(pmLoc,lv (cfa>>CFA.fp),lFP) pmLoc>>BootMap.firstpage = cfa>>CFA.fa.pageNumber let a = 0 let nexti = nil let i = 0 until i eq mapLast do [ let item = lv (pageMap!i) test item>>MapItem.tag ifso [ pmLoc>>BootMap.address↑a = (item>>MapItem.base lshift 1) + 1 pmLoc>>BootMap.address↑(a+1) = item>>MapItem.da a = a + 2 nexti = i+lchangeMapItem ] ifnot nexti = i+lnormalMapItem let memaddress = item>>MapItem.page lshift 8 for j = 1 to item>>MapItem.count do [ pmLoc>>BootMap.address↑a = memaddress memaddress = memaddress + #400 a = a + 1 ] i = nexti ] pmLoc>>BootMap.address↑a = 0 ] and FixMBOOT(data,pmLoc,firstDa) be [ @PointerToBootMap = pmLoc data>>BootList.pageMap = pmLoc data>>BootList.firstDa = firstDa ] and FixMESANOVA(data) be [ @OSFPtr = OsFinish @AC1Ptr = MesaStart @OutLdPtr = OutLd @InLdPtr = InLd @FinProcPtr = SystemDispatch+sGoingAway @processTrapPtr = SystemDispatch+sProcessTrap @firstProcessPtr = FirstProcess @lastProcessPtr = LastProcess @firstStateVectorPtr = FirstStateVector @STOPUser = STOPImplementer @CleanUpQueueUser = CleanUpQueueImplementer @RequeueSubUser = RequeueSubImplementer @WakeHeadUser = WakeHeadImplementer MakeBltItem(lv data>>BootList.blt↑blMesaNova1, MesaNova1, TXV, MesaNovaSize1) MakeBltItem(lv data>>BootList.blt↑blMesaNova2, MesaNova2, xNovaCode, MesaNovaSize2) @PuntData = 0 ] and MakeBltItem(item, source, dest, count) be [ item>>BltItem.firstSourceM1 = source-1 item>>BltItem.lastDest = dest+count-1 item>>BltItem.minusCount = -count ] and FixInterrupts(data,v) be [ let t=@PScode - 2 for i=0 to 14 do [ t=t+1; v!i=t ] MakeBltItem(lv data>>BootList.blt↑blInterruptVector, v, interruptVector, 15) DisableInterrupts() @displayInterrupt = 0 @activeInterrupts = 0 @wakeupsWaiting = 0 EnableInterrupts() v!TimeoutInterruptLevel = AdvanceTimerPtr ] and let LoadInternalMicrocode() = valof [ let MBFile=0 let ramver = 0 if HardwareConfiguration>>HardwareInfo.ControlStore eq RAMandROM then [CompatibilityCheck // this implicitly allows XMesa 5.0 ROM to be used with (X)Mesa 6.0 if @MesaImage ne ROMCompatibility then // ROM too old [ HardwareConfiguration>>HardwareInfo.XMmicrocode = false HardwareConfiguration>>HardwareInfo.useXM = false ] ]CompatibilityCheck // are we D0 or Dorado? if HardwareConfiguration>>HardwareInfo.AltoType > 3 then resultis false switchon HardwareConfiguration>>HardwareInfo.ControlStore into [ControlStoreCases case RAM0only: [NoROM if microcodeLoaded ne 0 then endcase LoadPackedRAM(MesaImage, lv ramver) HardwareConfiguration>>HardwareInfo.mesaMicrocodeVersion = ramver endcase ]NoROM case RAM3K: if (microcodeLoaded & 2) eq 0 then [TwoRAMs LoadPackedRAM(XMesaImage, lv ramver, 1) // load RAM1 HardwareConfiguration>>HardwareInfo.mesaMicrocodeVersion = ramver ]TwoRAMs case RAMandROM: [ if (microcodeLoaded & 1) ne 0 then endcase test HardwareConfiguration>>HardwareInfo.XMmicrocode ifso LoadPackedRAM(XMesaOverflow, lv ramver, 0) ifnot [IgnoreROM LoadPackedRAM(MesaImage, lv ramver, 0) HardwareConfiguration>>HardwareInfo.mesaMicrocodeVersion = ramver ]IgnoreROM ] ]ControlStoreCases resultis true ] and GiveMicrocodeVersion() be [ Ws("microcode ") Wns(dsp, @MesaImage) Puts(dsp,$[) Wns(dsp, @XMesaImage) Puts(dsp,$-) Wns(dsp, @XMesaOverflow) Puts(dsp, $]) ] and AbortMsg(s; numargs na) be [ if na ne 0 then Ws(s) Resets(keys) KeyboardWait() abort ] and KeyboardWait() be [ Ws(" [] ") let char=Gets(keys) Puts(dsp,char) if char eq $f % char eq 3 then finish ]