Cedar Nucleus: Interface with Germ.
GermSwap.mesa
Andrew Birrell May 26, 1983 9:29 am
Last Edited by: Levin, June 14, 1983 4:47 pm
DIRECTORY
BootFile USING [Continuation, ContinuationKind, InLoadMode, Location, MDSIndex],
BootStartList USING [Header],
PrincOps USING [BytePC, ControlLink, FrameHandle, GlobalFrameHandle, LongNumber, PageCount, SD, sBootSwitches, wordsPerPage, zMISC],
PrincOpsUtils USING [HighHalf, LongCOPY, MyLocalFrame];
GermSwap:
DEFINITIONS
IMPORTS PrincOpsUtils =
BEGIN
Transfers to germ
OutLoad:
PROC [pLocation:
POINTER
TO BootFile.Location, inLoadMode: BootFile.InLoadMode]
RETURNS [ResponseKind[outLoaded..resumed]] =
Assume interrupts disabled, all devices turned off
INLINE BEGIN
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]
END;
ResponseKind: TYPE = {initiated, outLoaded, resumed};
InLoad:
PROC [pMicrocodeCopy, pGermCopy:
LONG
POINTER, nGerm:
CARDINAL, pLocation:
POINTER
TO BootFile.Location, switches: Switches ← defaultSwitches] =
Load boot file, performing microcode and germ swap if necessary
INLINE BEGIN
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[];
END;
Teledebug:
PROC [pLocation:
POINTER
TO BootFile.Location] =
The germ is free to ingore pLocation
Assume interrupts disabled, all devices turned off
INLINE BEGIN
Set up request in cross-MDS monitor shared with germ
SetGermArguments[teledebug, pLocation];
CallGerm[];
END;
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 BOOL ← ALL[FALSE];
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 BEGIN
pMon.CrossMDSCall[mdsiOther: mdsiGerm, Dest: LOOPHOLE[pInitialLink]];
LOOPHOLE[pMon.CrossMDSCall, POINTER TO PrincOps.FrameHandle].pc ← LOOPHOLE[pMon.pcCross];
END;
LoadRam:
PRIVATE
PROC [pMicrocode:
LONG
POINTER, andJump:
BOOLEAN] =
MACHINE CODE BEGIN PrincOps.zMISC, 3 END;
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[LOOPHOLE[PrincOps.LongNumber[any[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: UNSPECIFIED] -- 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 = 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.