-- 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..