-- MMStart.Mesa  Edited by Sandman on May 23, 1979  11:52 AM
-- Edited by Forrest on October 8, 1980  2:42 PM

DIRECTORY
  AltoDefs USING [PageNumber],
  BcplOps USING [BcplJSR],
  ControlDefs USING [FrameHandle, GlobalFrameHandle, NullFrame, StateVector],
  FrameOps USING [GetReturnFrame, MyLocalFrame],
  ImageDefs USING [UserCleanupProc],
  InlineDefs USING [BITSHIFT, BITOR],
  MMInit,
  MMSDEntries,
  ProcessDefs USING [
    DefaultPriority, Detach, DisableInterrupts, DisableTimeout, DIW,
    EnableInterrupts, GetPriority, Priority, SetPriority, SetTimeout,
    TimeoutLevel],
  ProcessOps,
  PSBDefs,
  SDDefs USING [
    sAllocTrap, sBLTE, sBLTEC, sBYTBLTE, sBYTBLTEC, sBreak, sControlFault,
    sCopy, SD, sError, sErrorList, sFork, sJoin, sLongDiv, sLongDivMod,
    sLongMod, sLongMul, sProcessTrap, sRestart, sGoingAway, sReturnError,
    sReturnErrorList, sSignal, sSignalList, sSignedDiv, sStackError,
    sStart, sStringInit, sSwapTrap, sUnbound, sULongDiv, sULongDivMod,
    sULongMod, sUnnamedError, sUnNew],
  SegmentDefs USING [DeleteDataSegment],
  SystemDefs USING [FreePages],
  SwapperOps,
  WartDefs;

MMStart: PROGRAM [h: POINTER TO WartDefs.Header] RETURNS [PROGRAM]
  IMPORTS BcplOps, FrameOps, ImageDefs, InlineDefs, MMInit,
    MMSDEntries, ProcessDefs, ProcessOps, SegmentDefs, SystemDefs, SwapperOps
  EXPORTS MMInit =
  BEGIN OPEN MMInit, SDDefs;

  InitSD: PUBLIC PROCEDURE =
    BEGIN OPEN SDDefs, MMSDEntries;
    sd: POINTER TO ARRAY [0..0) OF UNSPECIFIED ← SD;
    sd[sSignalList] ← SignalList;
    sd[sSignal] ← Signal;
    sd[sErrorList] ← ErrorList;
    sd[sError] ← Error;
    sd[sReturnErrorList] ← ReturnErrorList;
    sd[sReturnError] ← ReturnError;
    sd[sUnnamedError] ← UnnamedError;
    sd[sStackError] ← StackErrorTrap;
    sd[sControlFault] ← ControlFaultTrap;
    sd[sStart] ← Start;
    sd[sRestart] ← Restart;
    sd[sBLTE] ← BlockEqual;
    sd[sBYTBLTE] ← ByteBlockEqual;
    sd[sBLTEC] ← BlockEqualCode;
    sd[sBYTBLTEC] ← ByteBlockEqualCode;
    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[sAllocTrap] ← AllocTrap[AllocTrap[ControlDefs.NullFrame]];
    sd[sSwapTrap] ← CodeTrap;
    sd[sUnbound] ← UnboundProcedureTrap;
    sd[sCopy] ← Copy;
    sd[sUnNew] ← UnNew;
    sd[sGoingAway] ← ImageDefs.UserCleanupProc;
    END;

  Memory: PUBLIC PROCEDURE [ff, lf: AltoDefs.PageNumber] =
    BEGIN
    MMInit.lfvmp ← lf; MMInit.ffvmp ← ff;
    FOR i: CARDINAL IN [ff..lf] DO MMInit.pageMap[i] ← free ENDLOOP;
    END;

  Interrupt: PROCEDURE =
    BEGIN OPEN ProcessDefs;
    save: Priority = GetPriority[];
    START MMInterrupt;
    SetTimeout[@wakeup, 1];
    SetPriority[6];
    Detach[FORK CheckInterrupt];
    SetPriority[save];
    RETURN
    END;

  InitializeProcesses: PROCEDURE =
    BEGIN OPEN SDDefs, ProcessDefs, ProcessOps, PSBDefs;
    sd: POINTER TO ARRAY [0..0) OF UNSPECIFIED ← SD;
    PSBBase: CARDINAL = 0;
    firstPSB: ProcessHandle ← FirstProcess↑;
    lastPSB: ProcessHandle ← LastProcess↑;
    psb: ProcessHandle;
    DisableTimeout[@dead];
    DisableTimeout[@frameReady];
    DisableTimeout[@frameTaken];
    DisableTimeout[@rebirth];
    CurrentState↑ ← FirstStateVector↑ +
      DefaultPriority*SIZE[ControlDefs.StateVector];
    -- locate and initialize PSBs  
    sd[sProcessTrap] ← ProcessTrap;
    sd[sFork] ← Fork;
    sd[sJoin] ← Join;
    -- fabricate PSB for self
    lastPSB↑ ← PSB[
      link: lastPSB,
      cleanup: Clean,
      timeout: 0,
      enterFailed: FALSE,
      detached: FALSE,
      fill: 0B,
      state: alive,
      timeoutAllowed:,
      abortPending: FALSE,
      timeoutPending: FALSE,
      waitingOnCV: FALSE,
      priority: DefaultPriority,
      frame: FrameOps.MyLocalFrame[]];
    CurrentPSB↑ ← ReadyList↑ ← lastPSB;
    -- set up free PSB pool ("rebirth" condition)
    FOR psb ← firstPSB, psb+SIZE[PSB]
    UNTIL psb = lastPSB DO
      psb↑ ← PSB[
	link: psb-SIZE[PSB],
	cleanup: Clean,
	timeout: 0,
	enterFailed: FALSE,
	detached: FALSE,
	fill: 0B,
	state: dead,
	timeoutAllowed:,
	abortPending: FALSE,
	timeoutPending: FALSE,
	waitingOnCV: TRUE,
	priority: DefaultPriority,
	frame: ControlDefs.NullFrame];
      ENDLOOP;
    LOOPHOLE[rebirth, Condition].queue ←
      (firstPSB.link ← lastPSB-SIZE[PSB])-PSBBase;
    -- CV↑ already set up by Nova code
    ActiveWord↑ ← 77777B;
    RETURN
    END;

  InitializeTimeouts: PROCEDURE =
    BEGIN OPEN InlineDefs, ProcessDefs;
    TimeoutMask: WORD = BITSHIFT[1,TimeoutLevel];
    DisableInterrupts[];
    -- Nova code has set up IntVec[TimeoutLevel]
    DIW↑ ← BITOR[DIW↑, TimeoutMask];
    EnableInterrupts[];
    RETURN
    END;

  ProcessWartList: PROCEDURE RETURNS [PROGRAM] =
    BEGIN OPEN WartDefs;
    segBase: TableBase = h.tablebase + h.segOffset;
    linkBase: TableBase = h.tablebase + h.linkOffset;
    ProcessOps.WriteWDC[0];  -- interrupts on
    FOR seg: SegIndex ← LOOPHOLE[SIZE[Header]],
        seg + SIZE[SegEntry] UNTIL seg = h.segLength
      DO
      s: SegHandle = @segBase[seg];
      IF s.in THEN s.handle ← SwapperOps.BootDataSegment[s.vmPage, s.pages]
      ENDLOOP;
    FOR link: LinkIndex ← FIRST[LinkIndex],
        link + SIZE[LinkEntry] UNTIL link = h.linkLength
      DO
      frame: ControlDefs.GlobalFrameHandle = linkBase[link].frame;
      s: SegHandle = @segBase[linkBase[link].codeseg];
      IF s.handle=NIL THEN ERROR;
      frame.code.handle ← LOOPHOLE[s.vmPage*256];
      ENDLOOP;
    InitializeProcesses[];
    InitializeTimeouts[];
    Interrupt[];
    SegmentDefs.DeleteDataSegment[segBase[h.loadState].handle];
    SegmentDefs.DeleteDataSegment[segBase[h.initLoadState].handle];
    IF segBase[h.bcd].in THEN
      SegmentDefs.DeleteDataSegment[segBase[h.bcd].handle];
    SystemDefs.FreePages[h];
    START MMDebug[LOOPHOLE[h.user]];
    FrameOps.GetReturnFrame[].returnlink ← LOOPHOLE[MMSDEntries.Restart];
    SDDefs.SD[sBreak] ← MMSDEntries.Break;
    RETURN[LOOPHOLE[MMDebug]];
    END;

  WartBreak: PROCEDURE  =
    BEGIN OPEN BcplOps, ControlDefs;
    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;

  SDDefs.SD[sBreak] ← WartBreak;
  InitSD[];
  START MMTraps;
  START MMMemory;
  START MMSignals;
  START MMProcess;
  Memory[h.ffvmp, h.lfvmp];
  RETURN[ProcessWartList[]];

  END......