-- MesaInit.mesa; edited by Sandman, August 27, 1980 10:01 AM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY AllocDefs USING [SwappingProcedure, SwapStrategy, TryCodeSwapping], AltoDefs USING [MaxMDSPage, PageSize, PagesPerMDS], ControlDefs USING [GlobalFrameHandle], FrameDefs USING [ EnumerateGlobalFrames, GlobalFrame, MakeCodeResident, RemoveGlobalFrame, UnlockCode, UnNew, ValidateGlobalFrame], FrameOps USING [CodeHandle], InlineDefs USING [BITAND, LongCOPY], Map USING [Clean, Entry, SETF, VacantFlags], MiscDefs USING [], Mopcodes USING [zRBL, zSTARTIO, zWBL], NucleusOps USING [], OsStaticDefs USING [OsStatics], ProcessDefs USING [CV, DisableInterrupts, EnableInterrupts, ParityLevel], Region USING [Count, Handle, HyperRegion, Index, Node, Page, PageStatus], SegmentDefs USING [ AddressFromPage, AllocInfo, BankIndex, Banks, DefaultANYBase, DefaultMDSBase, EasyUp, EnumerateFileSegments, FileSegmentClass, FileSegmentHandle, LongAddressFromPage, MachineType, MakeSwappedIn, MemoryConfig, PageNumber, SegLockCount, SegmentHandle, SegmentLocation, SegmentType, SwapIn, Unlock], SwapperOps USING [ Alloc, AllocVM, Available, BusyPage, Count, Direction, Disable, ff, FreePage, initMemoryConfig, lf, map, mdsIndex, mdsNodes, mdsRegion, MDSRegion, memConfig, Page, PageMap, PageStatus, regions, rover, Status, strategyList, Swapper, systemTable, Table, TableHandle, TrySwapping, Update, UpdateVM]; MesaInit: PROGRAM IMPORTS SwapperOps, FrameDefs, FrameOps, InlineDefs, Map, AllocDefs, ProcessDefs, Region, SegmentDefs EXPORTS AllocDefs, MiscDefs, NucleusOps, SwapperOps SHARES SegmentDefs =PUBLIC BEGIN OPEN ControlDefs, AllocDefs, SegmentDefs, SwapperOps; LastResort: SwapStrategy _ SwapStrategy[NIL, TryCodeSwapping]; AddSwapStrategy: PUBLIC PROCEDURE [strategy: POINTER TO SwapStrategy] = BEGIN sp: POINTER TO SwapStrategy; ProcessDefs.DisableInterrupts[]; FOR sp _ SwapperOps.strategyList, sp.link UNTIL sp = NIL DO IF sp = strategy THEN RETURN; ENDLOOP; strategy.link _ SwapperOps.strategyList; SwapperOps.strategyList _ strategy; ProcessDefs.EnableInterrupts[]; RETURN END; RemoveSwapStrategy: PUBLIC PROCEDURE [strategy: POINTER TO SwapStrategy] = BEGIN sp: POINTER TO SwapStrategy; prev: POINTER TO SwapStrategy _ NIL; ProcessDefs.DisableInterrupts[]; FOR sp _ SwapperOps.strategyList, sp.link UNTIL sp = NIL DO IF sp = strategy THEN BEGIN IF prev = NIL THEN SwapperOps.strategyList _ sp.link ELSE prev.link _ sp.link; EXIT END; prev _ sp; ENDLOOP; ProcessDefs.EnableInterrupts[]; strategy.link _ NIL; RETURN END; MoveCode: PROCEDURE [direction: Direction] = BEGIN OPEN SegmentDefs; CheckOne: PROCEDURE [seg: FileSegmentHandle] RETURNS [BOOLEAN] = BEGIN oldVMpage, newVMpage: PageNumber; delta: LONG CARDINAL; UpdateCodebase: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] = BEGIN IF FrameOps.CodeHandle[f] = seg AND ~f.code.out THEN SELECT direction FROM outofMDS => BEGIN f.code.longbase _ LONG[f.code.shortbase] + delta; IF f.code.highHalf = 0 THEN f.code.handle _ seg; END; intoMDS => BEGIN f.code.longbase _ f.code.longbase + delta; IF f.code.highHalf # 0 THEN ERROR; f.code.handle _ seg; END; ENDCASE; RETURN[FALSE] END; IF seg.class # code OR seg.lock = 0 THEN RETURN[FALSE]; IF seg.VMpage >= 256 AND direction = outofMDS THEN RETURN[FALSE]; IF seg.VMpage < 256 AND direction = intoMDS THEN RETURN[FALSE]; SwapIn[seg]; oldVMpage _ seg.VMpage; newVMpage _ AllocVM[ base: IF direction = outofMDS THEN DefaultANYBase ELSE DefaultMDSBase, pages: seg.pages, info: [hard, bottomup, code], seg: seg]; ProcessDefs.DisableInterrupts[]; InlineDefs.LongCOPY[ from: LongAddressFromPage[oldVMpage], to: LongAddressFromPage[newVMpage], nwords: AltoDefs.PageSize*seg.pages]; delta _ AltoDefs.PageSize*(LONG[newVMpage] - LONG[oldVMpage]); [] _ FrameDefs.EnumerateGlobalFrames[UpdateCodebase]; UpdateVM[oldVMpage, seg.pages, FreePage]; seg.VMpage _ newVMpage; UpdateVM[newVMpage, seg.pages, seg]; ProcessDefs.EnableInterrupts[]; Unlock[seg]; RETURN[FALSE] END; IF ~memConfig.useXM OR memConfig.banks = 100000B THEN RETURN; [] _ EnumerateFileSegments[CheckOne]; END; EnableHyperspace: PROCEDURE = { IF memConfig.useXM THEN FOR i: BankIndex IN (FIRST[BankIndex]..LAST[BankIndex]] DO IF LOOPHOLE[memConfig.banks, Banks][i] THEN EnableBank[i]; ENDLOOP}; DisableHyperspace: PROCEDURE = BEGIN i: BankIndex; FOR i IN (FIRST[BankIndex]..LAST[BankIndex]] DO DisableBank[i]; ENDLOOP; RETURN END; NullManager: PROGRAM [Region.Index] RETURNS [Region.Handle] = LOOPHOLE[0]; originalManager: PROGRAM [Region.Index] RETURNS [Region.Handle] _ NullManager; nHyperRegions: CARDINAL _ 0; EnableBank: PROCEDURE [bank: BankIndex] = BEGIN bankManager: PROGRAM [Region.Index] RETURNS [Region.Handle]; IF bank = 0 THEN RETURN; IF originalManager = NullManager THEN bankManager _ originalManager _ Region.HyperRegion ELSE bankManager _ NEW Region.HyperRegion; IF nHyperRegions = 0 THEN FrameDefs.MakeCodeResident[FrameDefs.GlobalFrame[bankManager]]; SwapperOps.regions[bank] _ START bankManager[bank]; nHyperRegions _ nHyperRegions + 1; RETURN END; DisableBank: PROCEDURE [bank: BankIndex] = BEGIN OPEN FrameDefs; bankManager: PROGRAM [Region.Index] RETURNS [Region.Handle]; region: Region.Handle; IF bank = 0 THEN RETURN; IF (region _ SwapperOps.regions[bank]) = NIL THEN RETURN; bankManager _ LOOPHOLE[GlobalFrame[region.alloc]]; region.disable[FALSE]; SwapperOps.regions[bank] _ NIL; IF bankManager # originalManager THEN UnNew[LOOPHOLE[bankManager]]; IF (nHyperRegions _ nHyperRegions - 1) = 0 THEN UnlockCode[originalManager]; RETURN END; -- D0/Dorado hyperspace stuff ComputeRealMemory: PUBLIC PROC RETURNS [pages: CARDINAL, banks: Banks] = BEGIN OPEN AltoDefs, SwapperOps; banks _ ALL[FALSE]; pages _ 0; SELECT memConfig.AltoType FROM AltoIIXM => IF memConfig.xmMicroCode THEN { word: CARDINAL; parity: POINTER = ProcessDefs.CV[ProcessDefs.ParityLevel]; ProcessDefs.CV[ProcessDefs.ParityLevel] _ NIL; FOR i: CARDINAL IN [1..3] DO word _ RBL[LP[0, i]]; WBL[word + 1, LP[0, i]]; IF RBL[LP[0, i]] = word + 1 THEN { WBL[word, LP[0, i]]; banks[i] _ TRUE; pages _ pages + PagesPerMDS}; ENDLOOP; ProcessDefs.CV[ProcessDefs.ParityLevel] _ parity} ELSE {pages _ PagesPerMDS; banks[0] _ TRUE}; D0, Dorado => { t: Map.Entry; FOR pages _ PagesPerMDS, pages + 1 DO t _ Map.SETF[pages, Map.Clean]; [] _ Map.SETF[pages, t]; IF t.flags = Map.VacantFlags THEN EXIT; ENDLOOP; FOR i: CARDINAL IN [0..(pages + MaxMDSPage)/PagesPerMDS) DO banks[i] _ TRUE; ENDLOOP}; ENDCASE => {pages _ PagesPerMDS; banks[0] _ TRUE}; RETURN END; RBL: PROCEDURE [LONG POINTER] RETURNS [CARDINAL] = MACHINE CODE BEGIN Mopcodes.zRBL, 0 END; WBL: PROCEDURE [CARDINAL, LONG POINTER] = MACHINE CODE BEGIN Mopcodes.zWBL, 0 END; LP: PROCEDURE [CARDINAL, CARDINAL] RETURNS [LONG POINTER] = MACHINE CODE BEGIN END; InitMemoryConfig: PROCEDURE = BEGIN pages: CARDINAL; banks: Banks; MDSOnly: CARDINAL = 100000B; memConfig _ initMemoryConfig^; [pages: pages, banks: banks] _ ComputeRealMemory[]; memConfig.banks _ InlineDefs.BITAND[banks, memConfig.banks]; IF memConfig.banks # MDSOnly THEN memConfig.useXM _ memConfig.xmMicroCode; END; Disable: PROCEDURE [BOOLEAN] = BEGIN END; InitMemory: PROCEDURE [ffvmp, lfvmp: CARDINAL] = BEGIN OPEN SwapperOps; page: [0..AltoDefs.MaxMDSPage]; pages: CARDINAL _ lfvmp - ffvmp + 1; node: Region.Node = AddressFromPage[ffvmp]; START Swapper; START MDSRegion; mdsRegion _ [basePage: 0, alloc: Alloc, update: Update, available: Available, status: Status, disable: Disable, swap: TrySwapping, hole: pages]; ff _ rover _ ffvmp; lf _ lfvmp; node^ _ [base: ffvmp, pages: pages, fwd: @mdsNodes, back: @mdsNodes]; mdsNodes _ [base: 177777B, pages: 0, fwd: node, back: node]; FOR page IN [0..AltoDefs.MaxMDSPage] DO map[page] _ IF page IN [ffvmp..lfvmp] THEN FreePage ELSE BusyPage; ENDLOOP; regions _ ALL[NIL]; regions[mdsIndex _ 0] _ @mdsRegion; strategyList _ @LastResort; InitMemoryConfig[]; systemTable _ [mdsMap: map, memConfig: @memConfig, table: NIL, regions: @regions]; END; -- Fake Modules DestroyFakeModule: PROCEDURE [f: GlobalFrameHandle] RETURNS [seg: SegmentDefs.FileSegmentHandle, offset: CARDINAL] = BEGIN FrameDefs.ValidateGlobalFrame[f]; seg _ FrameOps.CodeHandle[f]; IF seg = NIL THEN RETURN[NIL, 0]; IF ~f.shared THEN seg.class _ other; FrameDefs.RemoveGlobalFrame[f]; ProcessDefs.DisableInterrupts[]; IF f.code.out THEN BEGIN f.code.out _ FALSE; offset _ f.code.offset; END ELSE offset _ f.code.offset - seg.VMpage*AltoDefs.PageSize; ProcessDefs.EnableInterrupts[]; RETURN END; -- Get Network Number wordsPerPup: INTEGER = 280; Byte: TYPE = [0..255]; PupHeader: TYPE = MACHINE DEPENDENT RECORD [ eDest, eSource: Byte, eWord2, pupLength: INTEGER, transportControl, pupType: Byte, pupID1, pupID2: INTEGER, destNet, destHost: Byte, destSocket1, destSocket2: INTEGER, sourceNet, sourceHost: Byte, sourceSocket1, sourceSocket2: INTEGER, xSum: CARDINAL]; Pup: TYPE = MACHINE DEPENDENT RECORD [ head: PupHeader, junk: ARRAY [0..100] OF WORD]; EthernetDeviceBlock: TYPE = MACHINE DEPENDENT RECORD [ EPLocMicrocodeStatus, EPLocHardwareStatus: Byte, EBLocInterruptBit: WORD, EELocInputFinishCount: INTEGER, ELLocCollisionMagic: WORD, EILocInputCount: INTEGER, EILocInputPointer: POINTER, EOLocOutputCount: INTEGER, EOLocOutputPointer: POINTER]; timer: POINTER TO INTEGER = LOOPHOLE[430B]; GetNetworkNumber: PROCEDURE RETURNS [CARDINAL] = BEGIN myHost: Byte _ OsStaticDefs.OsStatics.SerialNumber; then: INTEGER; now: INTEGER; device: POINTER TO EthernetDeviceBlock _ LOOPHOLE[600B]; xpup: Pup; pup: POINTER TO Pup = @xpup; -- StartIO is Mesa bytecode used to control Ethernet interface StartIO: PROCEDURE [WORD] = MACHINE CODE BEGIN Mopcodes.zSTARTIO END; outputCommand: WORD = 1; inputCommand: WORD = 2; resetCommand: WORD = 3; gatewayRequest: PupHeader _ [eDest: 0, eSource: myHost, eWord2: 1000B, pupLength: 22, transportControl: 0, pupType: 200B, pupID1:, pupID2:, destNet: 0, destHost: 0, destSocket1: 0, destSocket2: 2, sourceNet: 0, sourceHost: myHost, sourceSocket1: 0, sourceSocket2: 2, xSum: 177777B]; device.EBLocInterruptBit _ 0; THROUGH [0..2) DO StartIO[resetCommand]; device^ _ EthernetDeviceBlock[ EPLocMicrocodeStatus: 0, EPLocHardwareStatus: 0, EBLocInterruptBit: 0, EELocInputFinishCount: 0, ELLocCollisionMagic: 0, EILocInputCount: 0, EILocInputPointer: pup, EOLocOutputCount: 13, EOLocOutputPointer: @gatewayRequest]; StartIO[outputCommand]; then _ timer^; DO IF device.EPLocHardwareStatus # 0 THEN BEGIN IF device.EPLocMicrocodeStatus = 0 AND pup.head.eWord2 = 1000B AND wordsPerPup + 2 - device.EELocInputFinishCount > 13 AND pup.head.destSocket1 = 0 AND pup.head.destSocket2 = 2 AND pup.head.pupType = 201B THEN RETURN[pup.head.sourceNet]; device^ _ EthernetDeviceBlock[ EPLocMicrocodeStatus: 0, EPLocHardwareStatus: 0, EBLocInterruptBit: 0, EELocInputFinishCount: 0, ELLocCollisionMagic: 0, EILocInputCount: wordsPerPup + 2, EILocInputPointer: pup, EOLocOutputCount: 0, EOLocOutputPointer: NIL]; StartIO[inputCommand]; END; now _ timer^; IF now - then > 14 THEN EXIT; ENDLOOP; ENDLOOP; RETURN[0]; END; END...