// VMemInit.bcpl - does VMem setup for MainInit // Last change September 5, 1981 12:38 PM by Bill van Melle // Last change May 8, 1981 11:53 PM by Beau Sheil // Tone change March 17, 1981 9:18 PM by Beau Sheil // Trill change February 24, 1981 10:40 AM by Beau Sheil // Last change February 19, 1981 1:05 PM by Beau Sheil get "LispBcpl.decl" get "Stats.decl" get "VMem.decl" external [ // procedures defined here SetupLispMem; LoadIPage // O.S. procedures Closes; Endofs; ReadBlock; Zero; OpenFileFromFp; PositionPage CallSwat; Serial; Timer // procedures used @BSetBR; @BGetBase; @RWrite; IGetBase; IPutBase; ReadRP SetFlags; MachineType BP; VP2; IndexedPageIO; InitFmap; SmallUnbox; @BPutBase32 AllocVec; Bytes2; ShortStack; LockPages; InitLispRegs; WriteStatsX // statics defined and/or used @MiscSTATSbase; NPages; ScreenWidth; @InterruptEnable; @InterruptChar EmuDiskVp; EmuDiskBuffer; LispFmap; EmulatorSpace; LastRealPageNo UserName; UserPassword ] static [ // statics defined EmuDiskVp; EmuDiskBuffer; EmulatorSpace; LastRealPageNo; NPages ] manifest PTBLsize = 100 let SetupLispMem(SYSINid, VMEMid) be [ let RamV, MinBcplForRam, MinLispForRam, ScreenWords, pnum, ppm = 0, nil, nil, nil, nil, nil // adjacent for InitLispRegs InitLispRegs(lv RamV) // fills in 6 words unless RamV ge MinRamForBcpl // Check BEFORE using other ILR values do CallSwat("Microcode too old for this lisp.run") unless BcplVersion ge MinBcplForRam do CallSwat("Lisp.run too old for this microcode") ScreenWidth = ScreenWords lshift 4 // Save width in bits unless (pnum rem ppm) eq 0 // bad pages unless pnum mod ppm = 0 do CallSwat("Bad pages found in main memory") let mnum = pnum / ppm // # modules let pbm = nil // pages between mods switchon MachineType() into [ case Dorado: // Dorado specific code [ pbm = ppm; EmulatorSpace = D1BCPLspace ] endcase case Dolphin: // Dolphin specific code [ pbm = #1000; EmulatorSpace = D0BCPLspace ] endcase default: CallSwat("Invalid machine type") ] LastRealPageNo = ppm+pbm*(mnum-1) NPages = mnum*ppm // dumped by stats unless NPages gr PagesPerSegment do CallSwat("Not enough real memory") // TransferPage needs one page aligned paging buffer for reading in a page BufVp = VP2(EmulatorSpace, AllocVec(WordsPerPage, WordsPerPage)) BufRP = ReadRP(BufVp) // Disk routines need one also EmuDiskBuffer = AllocVec(WordsPerPage, WordsPerPage) EmuDiskVp = VP2(EmulatorSpace, EmuDiskBuffer) // ReadRP gets page number of first real page. Then skip over emulator pages RPoffset = ReadRP(VP2(EmulatorSpace, 0))+PagesPerSegment BptSize = LastRealPageNo-PagesPerSegment [ let BptLength = lBPT*BptSize Bpt = AllocVec(BptLength) // alloc and zero page table Zero(Bpt, BptLength) ] for i = 0 to BptSize-1 do BP(i)>>BPT.STATE = UNAVAIL // can't use buffer rel 0, as 0 used as an end marker AddBuffers(1, ppm - #401) // real pages for xvmem for m = 1 to mnum-1 do AddBuffers(pbm*m - WordsPerPage, pbm*m + ppm - #401) // make all 2↑14 map entries (except for alto emulator) vacant for s = 0 to LastVirtualPage<<VP.segment do unless s eq EmulatorSpace do for p = 0 to PagesPerSegment-1 do [ let i = Bytes2(s, p); SetFlags(i, i+PagesPerSegment, VACANT) ] LispFmap = AllocVec(PTBLsize) // for isf access to lisp.virtualmem unless InitFmap(LispFmap, PTBLsize, VMEMid, true, 50) do CallSwat("Fragmented VMem") test (SYSINid eq 0) % (SYSINid eq -1) // SYSINid is zero if no sysin file ifso LoadIPage(RamV, MinLispForRam, ScreenWords) ifnot // read sysin file into VMem [ let sst = OpenFileFromFp(SYSINid) unless sst do CallSwat("Can't find /I file") // We can use the rest of the space between the last AllocVec and the // current end of stack for buffers. This space will eventually go to // the display bit map, but for now it is empty. let Buffers = AllocVec(0, WordsPerPage) // first buf page let LowStackPage = ShortStack(1000) // allow 1000 words of stack let bsize = LowStackPage - Buffers // size of buffer region if bsize ls WordsPerPage then CallSwat("No buffers for SYSIN") let OldLowStack = rv StackEnd // save old low stack @StackEnd = LowStackPage // enforce stack end in read // Restore SavedVMEMstate from the InterfacePage PositionPage(sst, FirstVmemBlock); ReadBlock(sst, Buffers, WordsPerPage) // First page of Buffers now has InterfacePage of sysin - write it into vmem IndexedPageIO(LispFmap, FirstVmemBlock, Buffers, 1, -1) // Interface page is now in VMEM file, so load, lock and check it LoadIPage(RamV, MinLispForRam, ScreenWords) // now read the pages off the file and into vmem - the entries in // the page maps on the file have the correct vmem address already let nxtpage = FirstVmemBlock + 1 until Endofs(sst) do [ let npgs = ReadBlock(sst, Buffers, bsize)<<HiByte IndexedPageIO(LispFmap, nxtpage, Buffers, npgs, -1) nxtpage = nxtpage + npgs ] Closes(sst) @StackEnd = OldLowStack // restore previous stack end ] // get PageMapTBL and the pages of the PageMap LockPages(PMTspace, PMTbase, 2) // 2 pages covers 22-bit addresses // we need only the first page but all are locked for performance LockPages(PAGEMAPspace, PAGEMAPbase, (IGetBase(IFPNxtPMAddr)-1)<<HiByte+1) // for free variable lookup in microcode, all stack pages must be in core LockPages(STACKspace, 0, IGetBase(IFPEndOfStack)<<HiByte + 1) // bring in the pages of the MDStypeTable and the locked down STATS pages. // The latter contain the interrupttable, misc stats, UFN table, etc. LockPages(MDSTYPEspace, MDSTYPEbase, MDSTTsize) LockPages(STATSspace, STATSbase, STATSsize) // lock down the defs of the #400+ subrs as they field punts incl page faults LockPages(DEFspace, #1000, 1) compileif DTDSize then [ // lock down DTD table LockPages(DTDspace, DTDbase, DTDSize) // lock down the main GC table, so gc refs work in microcode. LockPages(HTMAINspace, HTMAINbase, HTMAINnpages) ] if SYSINid then [ BSetBR(STATSspace, MISCSTATSbase) // zero Stats counters for i = 0 to lenMiscStats-1 do RWrite(i, 0) ] [ let tmr = vec 1 // set StartTime Timer(tmr) BPutBase32(STATSspace, MISCSTATSbase+MSstrtTime, tmr) ] MiscSTATSbase = MISCSTATSbase // enable miscstats ] and AddBuffers(firstRP, lastRP) be for tn = firstRP to lastRP do [ let bp = BP(tn) bp>>BPT.STATE = EMPTY bp>>BPT.NEXT = @Bpt if @Bpt eq 0 then BptLast = tn @Bpt = tn if LogPagingFlag then WriteStatsX(evAddBuffer, 0, tn) ] and LoadIPage(RamVersion, MinLispForRam, ScreenWords) be [ // LoadIPage loads and locks the interface page and checks keys and versions LockPages(INTERFACEspace, INTERFACEbase, 1) // Key check - verify file is valid and complete if IGetBase(IFPKey) ne IFPValidKey then CallSwat(IGetBase(IFPKey) eq (not IFPValidKey) ? "Can't resume: Inconsistent VMem file" , "Invalid or obselete Lisp VMem") // Version checking // IPage has the actual version of Lisp (which is checked here against the // versions required by both ucode and Bcpl) and the min required versions // of ucode and Bcpl. Bcpl/ucode compatibility is checked earlier. let LispV = IGetBase(IFPLVersion) unless LispV ge MinLispForRam do CallSwat("Sysout too old for this microcode") unless LispV ge MinLispForBcpl do CallSwat("Sysout too old for this Lisp.Run") unless RamVersion ge IGetBase(IFPMinRVersion) do CallSwat("Microcode too old for this sysout") unless BcplVersion ge IGetBase(IFPMinBVersion) then CallSwat("Lisp.Run too old for this sysout") // Updating IPage entries IPutBase(IFPRVersion, RamVersion) IPutBase(IFPBVersion, BcplVersion) IPutBase(IFPSerialNumber, Serial()) IPutBase(IFPEmulatorSpace, EmulatorSpace) IPutBase(IFPScreenWidth, ScreenWords) IPutBase(IFPUserNameAddr, UserName) IPutBase(IFPUserPswdAddr, UserPassword) // Caching some data from the IPage into statics InterruptEnable = IGetBase(IFPInterruptEnable) InterruptChar = IGetBase(IFPInterruptChar) ]