GermSwap.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Andrew Birrell May 26, 1983 9:29 am
Levin, September 20, 1983 11:25 am
Russ Atkinson (RRA) February 19, 1985 2:48:00 pm PST
Doug Wyatt, February 22, 1985 6:03:36 pm PST
Interface with the Germ.
DIRECTORY
BootFile USING [Continuation, ContinuationKind, InLoadMode, Location, MDSIndex],
BootStartList USING [Header],
PrincOps USING [BytePC, ControlLink, FrameHandle, GlobalFrameHandle, PageCount, SD, sBootSwitches, wordsPerPage, zMISC],
PrincOpsUtils USING [HighHalf, LongCopy, MakeLongPointer, MyLocalFrame];
GermSwap: DEFINITIONS
IMPORTS PrincOpsUtils
= BEGIN
Transfers to germ
OutLoad: PROC [pLocation: POINTER TO BootFile.Location, inLoadMode: BootFile.InLoadMode]
RETURNS [ResponseKind[outLoaded..resumed]] = INLINE {
Assume interrupts disabled, all devices turned off
Set up request in cross-MDS monitor shared with germ
RC: TYPE = MACHINE DEPENDENT RECORD [ to get around compiler bug
fill: [0..177B],
kind: BootFile.ContinuationKind,
mdsi: BootFile.MDSIndex,
resumee: UNSPECIFIED];
pMon.continuation ← LOOPHOLE[RC[fill: 0, kind: resumptive, mdsi: ReadMDS[], resumee: Frame.MyLocalFrame[]]];
pMon.continuation ← [vp: resumptive[mdsi: ReadMDS[], resumee: PrincOpsUtils.MyLocalFrame[]]];
pMon.inLoadMode ← inLoadMode;
SetGermArguments[outLoad, pLocation];
CallGerm[];
RETURN[pMon.responseKind]
};
ResponseKind: TYPE = {initiated, outLoaded, resumed};
InLoad: PROC [pMicrocodeCopy, pGermCopy: LONG POINTER,
nGerm: CARDINAL, pLocation: POINTER TO BootFile.Location,
switches: Switches ← defaultSwitches] = INLINE {
Load boot file, performing microcode and germ swap if necessary
IF pMicrocodeCopy~=NIL THEN DeviceCleanup.Perform[kill]; ++ causes FATAL ERROR IN PASS 4
IF pGermCopy~=NIL THEN
PrincOpsUtils.LongCopy[from: pGermCopy,
nwords: nGerm,
to: LP[NIL, mdsiGerm] + countSkip*PrincOps.wordsPerPage ];
SetGermArguments[inLoad, pLocation];
LOOPHOLE[LP[@PrincOps.SD[PrincOps.sBootSwitches], mdsiGerm], LONG POINTER TO Switches]^ ← switches;
IF pMicrocodeCopy~=NIL THEN
LoadRam[pMicrocode: pMicrocodeCopy, andJump: TRUE]; -- never returns
CallGerm[];
};
Teledebug: PROC [pLocation: POINTER TO BootFile.Location] = INLINE {
The germ is free to ingore pLocation
Assume interrupts disabled, all devices turned off
Set up request in cross-MDS monitor shared with germ
SetGermArguments[teledebug, pLocation];
CallGerm[];
};
Layout of Germ requests and switches
Request: TYPE = MACHINE DEPENDENT RECORD[
action(0): Action,
location(1): BootFile.Location
];
Action: TYPE = MACHINE DEPENDENT {
inLoad(0),
pilotOutLoad(1),
bootPhysicalVolume(2),
teledebug(3),
noOp(4),
outLoad(5),
(LAST[CARDINAL])
};
Switch: TYPE = MACHINE DEPENDENT {
zero, one, two, three, four, five, six, seven, eight, nine,
a, b, c, d, e, f, g, h, i, j,
k, l, m, n, o, p, q, r, s, t,
u, v, w, x, y, z
};
Switches: TYPE = PACKED ARRAY Switch OF DefaultSwitch ← [];
DefaultSwitch: TYPE = BOOLFALSE;
defaultSwitches: Switches = ALL[FALSE];
switches: Switches;
Switches with which we were booted. Valid only after calling GermSwap.InitialiseMDS[].
bootedFrom: Request;
Request with which we were booted. Valid only after calling GermSwap.InitialiseMDS[].
Cross-MDS linkage
Initialize: PROC [mdsiOther: BootFile.MDSIndex];
Per-system initialization (does InitializeMDS also)
InitializeMDS: PROC;
Per-MDS initialization
GetPStartListHeader: PROC RETURNS [LONG POINTER TO BootStartList.Header] =
Valid after start of initial boot file up until first call to OutLoad
INLINE { RETURN[pMon.pStartListHeader] };
SetGermArguments: PRIVATE PROC [action: Action,
pLocation: POINTER TO BootFile.Location] = INLINE {
LOOPHOLE[LP[pRequest, mdsiGerm], LONG POINTER TO Request]^ ← [action, pLocation^];
};
CallGerm: PRIVATE PROC = INLINE {
pMon.CrossMDSCall[mdsiOther: mdsiGerm, Dest: LOOPHOLE[pInitialLink]];
LOOPHOLE[pMon.CrossMDSCall, POINTER TO PrincOps.FrameHandle].pc ← LOOPHOLE[pMon.pcCross];
};
LoadRam: PRIVATE PROC [pMicrocode: LONG POINTER, andJump: BOOLEAN] =
MACHINE CODE { PrincOps.zMISC, 3 };
ReadMDS: PROC RETURNS[BootFile.MDSIndex] = INLINE {
RETURN[[PrincOpsUtils.HighHalf[LONG[LOOPHOLE[1,POINTER]]]]] };
LP: PROC[mdsRel: POINTER, mds: BootFile.MDSIndex] RETURNS[LONG POINTER] = INLINE {
RETURN[PrincOpsUtils.MakeLongPointer[low: mdsRel, high: mds]] };
Mon: PRIVATE TYPE = RECORD [
Extension to basic request for cross-MDS communication
WHEN THIS IS CHANGED, both Pilot and Germ will be incompatible until both are updated!
constants for WriteMDS hack:
CrossMDSCall: PROC [mdsiOther: BootFile.MDSIndex, Dest: PROC],
pcCross: PrincOps.BytePC,
additional fields for outLoad request:
continuation: resumptive BootFile.Continuation, -- for WriteMDS hack
inLoadMode: BootFile.InLoadMode,
response fields:
responseKind: ResponseKind,
fill: [0..8192) ← 0,
pStartListHeader: POINTER TO BootStartList.Header, -- only if responseKind=booted
selfFill: RECORD [a, b, c, d: WORD] -- obsolete, remove someday
];
Attributes of germ
Short pointers are relative to Germ's MDS. Beware of GFT at 1400B.
pRequest: POINTER TO Request = LOOPHOLE[1360B];
Arguments of each germ call.
limit: PRIVATE CARDINAL = LOOPHOLE[pRequest];
nGCross: PRIVATE CARDINAL = 12; --cross-MDS global frame words
nLCross: PRIVATE CARDINAL = 8; --cross-MDS fixed local frame words
gCross and lCross must be allocated identically in our MDS and Germ's MDS!
gCross: PRIVATE PrincOps.GlobalFrameHandle = LOOPHOLE[limit-(limit MOD 4)-nGCross];
lCross: PRIVATE PrincOps.FrameHandle = LOOPHOLE[gCross-nLCross];
pMon: PRIVATE LONG POINTER TO Mon = LOOPHOLE[LP[lCross-SIZE[Mon], mdsiGerm]];
pInitialLink: PRIVATE POINTER TO PrincOps.ControlLink = LOOPHOLE[1376B];
which is itself an indirect link within the germ MDS
pCountGerm: POINTER TO PrincOps.PageCount = LOOPHOLE[1377B];
excluding pageBuffer
mdsiGerm: BootFile.MDSIndex = [76B];
until Pilot is moved from first 64K
countSkip: PrincOps.PageCount = 2;
initial vacant pages within germ; will become 0
END.