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