-- Wart.Mesa Edited by Sandman on September 2, 1980 7:52 AM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY AltoFileDefs USING [CFP, FP], BcplOps USING [BcplJSR], ControlDefs USING [ AV, FrameHandle, GlobalFrameHandle, GFT, NullFrame, StateVector, TraceOff], CoreSwapDefs USING [level], DirectoryDefs USING [EnumerateDirectory], DiskDefs USING [DA, VirtualDA], ForgotOps USING [disableInterrupt], FrameOps USING [GetReturnFrame, MyGlobalFrame, Restart, Start], ImageFormat USING [FirstImageDataPage], ImageDefs USING [FileRequest, PuntMesa], InlineDefs USING [COPY], LoadStateFormat USING [LoadState, LoadStateObject], LoadStateOps USING [dirty, gft, initstate, loadstate, ReleaseLoadState, state], NucleusOps, ProcessDefs USING [ CV, Detach, DisableTimeout, EnableInterrupts, GetPriority, ParityLevel, Priority, SetPriority, SetTimeout], ProcessOps USING [FirstProcess, WriteWDC], SDDefs, SDOps, SegmentDefs USING [ AccessOptions, AddressFromPage, DataSegmentHandle, DeleteDataSegment, DeleteFileSegment, EnumerateFileSegments, FileHandle, FileHint, FileSegmentAddress, FileSegmentHandle, FrameDS, InsertFile, LockFile, PageNumber, Read, SwapOut, SystemDS, Unlock, VMtoDataSegment, Write], StringDefs USING [EquivalentString], SwapperOps USING [ BootDataSegment, BootFile, BootFileSegment, EnableHyperspace, InitMemory, MoveCode], TrapOps USING [WriteXTS], WartDefs USING [ Header, LinkEntry, LinkIndex, SegIndex, SegEntry, SegHandle, TableBase, VersionID]; Wart: PROGRAM [h: POINTER TO WartDefs.Header] RETURNS [PROGRAM] IMPORTS CoreSwapDefs, DirectoryDefs, DiskDefs, ForgotOps, FrameOps, ImageDefs, LoadStateOps, SwapperOps, BcplOps, NucleusOps, ProcessDefs, ProcessOps, SDOps, SegmentDefs, StringDefs, TrapOps, InlineDefs EXPORTS NucleusOps SHARES ControlDefs, DiskDefs, SegmentDefs = BEGIN OPEN WartDefs, ControlDefs, SegmentDefs; WartBreak: PROCEDURE = BEGIN OPEN BcplOps; s: StateVector; f: FrameHandle; break: RECORD [a, b: WORD]; s ← STATE; break ← [77400B, 1400B]; f ← FrameOps.GetReturnFrame[]; s.dest ← f; f.pc ← [IF f.pc < 0 THEN -f.pc ELSE (1 - f.pc)]; s.instbyte ← BcplJSR[JSR, @break, 0]; RETURN WITH s; END; Nub: TYPE = PROGRAM [GlobalFrameHandle]; InitSD: PROCEDURE = BEGIN OPEN SDDefs, SDOps; sd: POINTER TO ARRAY [0..0) OF UNSPECIFIED ← SD; sd[sStart] ← Start; sd[sRestart] ← Restart; sd[sBLTE] ← BlockEqual; sd[sBLTEC] ← BlockEqualCode; sd[sBLTEL] ← BlockEqualLong; sd[sBLTECL] ← BlockEqualCodeLong; sd[sBYTBLTE] ← ByteBlockEqual; sd[sBYTBLTEC] ← ByteBlockEqualCode; sd[sBYTBLTEL] ← ByteBlockEqualLong; sd[sBYTBLTECL] ← ByteBlockEqualCodeLong; sd[sStringInit] ← StringInit; sd[sSignedDiv] ← SignDivide; sd[sLongDivMod] ← DDivMod; sd[sLongMod] ← DMod; sd[sLongDiv] ← DDiv; sd[sLongMul] ← DMultiply; sd[sULongDivMod] ← DUnsignedDivMod; sd[sULongMod] ← DUnsignedMod; sd[sULongDiv] ← DUnsignedDiv; sd[sStackError] ← StackErrorTrap; sd[sControlFault] ← ControlFaultTrap; sd[sBoundsFault] ← BoundsFaultTrap; sd[sPointerFault] ← PointerFaultTrap; sd[sWakeupError] ← WakeupErrorTrap; sd[sZeroDivisor] ← ZeroDivisorTrap; sd[sDivideCheck] ← DivideCheckTrap; sd[sUnimplemented] ← UnimplementedInstTrap; sd[sPageFault] ← PageFaultTrap; sd[sWriteProtect] ← WriteProtectFaultTrap; sd[sHardwareError] ← HardwareErrorTrap; sd[sAllocTrap] ← AllocTrap[AllocTrap[NullFrame]]; sd[sSwapTrap] ← CodeTrap; sd[sUnbound] ← UnboundProcedureTrap; sd[sBreak] ← Break; sd[sAlternateBreak] ← WorryBreaker[]; sd[sWorryCallDebugger] ← WorryCallDebugger[]; sd[sIOResetBits] ← 3; sd[sSignalList] ← SignalList; sd[sSignal] ← Signal; sd[sErrorList] ← ErrorList; sd[sError] ← Error; sd[sReturnErrorList] ← ReturnErrorList; sd[sReturnError] ← ReturnError; sd[sUnnamedError] ← UnnamedError; END; InitInterrupts: PUBLIC PROCEDURE = BEGIN OPEN ProcessDefs; save: Priority = GetPriority[]; ForgotOps.disableInterrupt ← FALSE; SetTimeout[@NucleusOps.interruptWakeup, 1]; SetPriority[NucleusOps.InterruptPriority]; Detach[FORK NucleusOps.InterruptProcess]; SetPriority[save]; RETURN END; InitParity: PUBLIC PROCEDURE = BEGIN OPEN ProcessDefs; p: PROCESS; save: Priority ← GetPriority[]; DisableTimeout[@NucleusOps.parityWakeup]; CV[ParityLevel] ← @NucleusOps.parityWakeup; SetPriority[LAST[Priority]]; p ← FORK NucleusOps.ParityProcess; SetPriority[save]; RETURN END; InitLoadState: PROCEDURE [ls, initls, bcdseg: FileSegmentHandle] = BEGIN OPEN SegmentDefs, LoadStateOps; initloadstate: LoadStateFormat.LoadState ← FileSegmentAddress[initls]; initstate ← initls; loadstate ← FileSegmentAddress[state ← ls]; gft ← DESCRIPTOR[@loadstate.gft, SDDefs.SD[SDDefs.sGFTLength]]; InlineDefs.COPY[ from: initloadstate, to: loadstate, nwords: LENGTH[gft] + SIZE[LoadStateFormat.LoadStateObject]]; WITH loadstate.bcds[0] SELECT FROM alto => { base ← bcdseg.base; WITH s: bcdseg SELECT FROM disk => da ← s.hint.da; ENDCASE}; ENDCASE; dirty ← TRUE; ReleaseLoadState[]; Unlock[initls]; initls.write ← FALSE; SwapOut[initls]; IF bcdseg.lock = 1 THEN Unlock[bcdseg]; DeleteFileSegment[bcdseg]; END; ProcessWartList: PROCEDURE RETURNS [PROGRAM] = BEGIN segBase: TableBase = h.tablebase + h.segOffset; linkBase: TableBase = h.tablebase + h.linkOffset; imagefile: SegmentDefs.FileHandle; link: LinkIndex; seg: SegIndex; access: SegmentDefs.AccessOptions; s: SegHandle; frame: ControlDefs.GlobalFrameHandle; vmaddr, nub: POINTER; RequestHead: POINTER TO ImageDefs.FileRequest ← NIL; useHyperSpace: BOOLEAN ← h.useHyperSpace; AddFileRequest: PROCEDURE [r: POINTER TO ImageDefs.FileRequest] = BEGIN r.link ← RequestHead; RequestHead ← r; END; ProcessFileRequests: PROCEDURE = BEGIN OPEN AltoFileDefs; checkone: PROCEDURE [fp: POINTER TO FP, dname: STRING] RETURNS [BOOLEAN] = BEGIN r: POINTER TO ImageDefs.FileRequest; prev: POINTER TO ImageDefs.FileRequest ← NIL; FOR r ← RequestHead, r.link UNTIL r = NIL DO IF StringDefs.EquivalentString[dname, r.name] THEN BEGIN IF r.file = NIL THEN LockFile[r.file ← InsertFile[fp, r.access]] ELSE r.file.fp ← fp↑; IF prev = NIL THEN RequestHead ← r.link ELSE prev.link ← r.link; END ELSE prev ← r; ENDLOOP; RETURN[RequestHead = NIL] END; DirectoryDefs.EnumerateDirectory[checkone]; END; SDDefs.SD[SDDefs.sBreak] ← WartBreak; SDDefs.SD[SDDefs.sAddFileRequest] ← AddFileRequest; FrameOps.Start[LOOPHOLE[NucleusOps.Resident]]; FrameOps.Start[LOOPHOLE[NucleusOps.NonResident]]; FrameOps.Start[LOOPHOLE[NucleusOps.Faults]]; InitSD[]; SDDefs.SD[SDDefs.sBreak] ← WartBreak; NucleusOps.InitSwapPorts[]; CoreSwapDefs.level ← -1; START NucleusOps.DiskIO; START NucleusOps.Miscellaneous; START NucleusOps.MesaInit; IF h.version # WartDefs.VersionID THEN ImageDefs.PuntMesa[]; SwapperOps.InitMemory[h.ffvmp, h.lfvmp]; START NucleusOps.OurProcess; ProcessDefs.EnableInterrupts[]; START NucleusOps.Signaller; START NucleusOps.SegmentsA; START NucleusOps.SegmentsB; START NucleusOps.Files; START NucleusOps.Modules; imagefile ← SwapperOps.BootFile[Read]; FOR seg ← LOOPHOLE[SIZE[Header]], seg + SIZE[SegEntry] UNTIL seg = h.segLength DO s ← @segBase[seg]; access ← IF s.write THEN Read + Write ELSE Read; vmaddr ← IF s.in THEN AddressFromPage[s.vmPage] ELSE NIL; IF s.data THEN s.handle ← SwapperOps.BootDataSegment[s.vmPage, s.pages] ELSE s.handle ← SwapperOps.BootFileSegment[ file: imagefile, base: s.base, pages: s.pages, access: access, addr: vmaddr]; IF ~s.locked AND vmaddr # NIL THEN Unlock[s.handle]; ENDLOOP; FOR link ← FIRST[LinkIndex], link + SIZE[LinkEntry] UNTIL link = h.linkLength DO frame ← linkBase[link].frame; s ← @segBase[linkBase[link].codeseg]; frame.code.handle ← s.handle; LOOPHOLE[frame.code.handle, FileSegmentHandle].class ← code; ENDLOOP; VMtoDataSegment[FrameOps.MyGlobalFrame[]].type ← FrameDS; VMtoDataSegment[ControlDefs.AV].type ← SystemDS; VMtoDataSegment[ControlDefs.GFT].type ← SystemDS; VMtoDataSegment[ProcessOps.FirstProcess↑].type ← SystemDS; InitInterrupts[]; START NucleusOps.DiskKD; BootPageTable[imagefile, h.diskAddresses]; -- no swapping before here DeleteDataSegment[VMtoDataSegment[h.diskAddresses]]; START NucleusOps.LoadState; InitLoadState[ ls: segBase[h.loadState].handle, initls: segBase[h.initLoadState].handle, bcdseg: segBase[h.bcd].handle]; START LOOPHOLE[nub ← h.nub, Nub][h.user]; ProcessFileRequests[]; InitParity[]; DeleteDataSegment[VMtoDataSegment[segBase]]; SwapperOps.EnableHyperspace[]; IF useHyperSpace THEN SwapperOps.MoveCode[direction: outofMDS]; SDDefs.SD[SDDefs.sAddFileRequest] ← 0; SDDefs.SD[SDDefs.sBreak] ← SDOps.Break; FrameOps.GetReturnFrame[].returnlink ← LOOPHOLE[FrameOps.Restart]; RETURN[LOOPHOLE[nub]]; END; -- page table PageTable: TYPE = MACHINE DEPENDENT RECORD [ fp: AltoFileDefs.CFP, firstpage: CARDINAL, table: ARRAY [0..1) OF DiskDefs.DA]; BootPageTable: PROCEDURE [file: FileHandle, pt: POINTER TO PageTable] = BEGIN OPEN AltoFileDefs, DiskDefs; lastpage: PageNumber; pageInc: PageNumber = pt.firstpage - ImageFormat.FirstImageDataPage; PlugHint: PROCEDURE [seg: FileSegmentHandle] RETURNS [BOOLEAN] = BEGIN IF seg.file = file THEN BEGIN seg.base ← seg.base + pageInc; IF seg.base IN [pt.firstpage..lastpage] THEN WITH s: seg SELECT FROM disk => s.hint ← FileHint[ page: s.base, da: DiskDefs.VirtualDA[pt.table[s.base - pt.firstpage]]]; ENDCASE; END; RETURN[FALSE] END; file.open ← TRUE; file.fp ← FP[serial: pt.fp.serial, leaderDA: pt.fp.leaderDA]; FOR lastpage ← 0, lastpage + 1 UNTIL pt.table[lastpage] = DA[0, 0, 0, 0, 0] DO NULL ENDLOOP; IF lastpage = 0 THEN RETURN; lastpage ← lastpage + pt.firstpage - 1; [] ← EnumerateFileSegments[PlugHint]; RETURN END; ProcessOps.WriteWDC[1]; -- interrupts off TrapOps.WriteXTS[ControlDefs.TraceOff]; RETURN[ProcessWartList[]]; END..