-- File: AMCUCold.mesa - last Edit:
  -- MAS  August 27, 1980  5:37 PM
  -- HGM  June 29, 1980  8:36 PM

-- Copyright  Xerox Corporation 1979, 1980

DIRECTORY
  AltoDefs: FROM "AltoDefs" USING [PageSize],
  BcplOps: FROM "BcplOps" USING [BcplJSR],
  ControlDefs: FROM "ControlDefs" USING [GlobalFrameHandle],
  DriverDefs: FROM "DriverDefs",  -- EXPORTS
  FrameDefs: FROM "FrameDefs" USING [
    MakeCodeResident, UnlockCode, GlobalFrame, IsBound],
  ImageDefs: FROM "ImageDefs" USING [
    CleanupItem, AddCleanupProcedure, RemoveCleanupProcedure],
  InlineDefs: FROM "InlineDefs" USING [BITOR, LowHalf],
  MiscDefs: FROM "MiscDefs" USING [CallDebugger],
  ProcessDefs: FROM "ProcessDefs" USING [
    Priority, InterruptLevel, CV,
    DisableInterrupts, EnableInterrupts, SetPriority],
  SegmentDefs: FROM "SegmentDefs" USING [
    DataSegmentHandle, DeleteDataSegment, PupBufferDS, VMtoDataSegment],
  SDDefs: FROM "SDDefs" USING [SD, sIOResetBits],
  SystemDefs: FROM "SystemDefs" USING [AllocateResidentPages],
  CommUtilDefs: FROM "CommUtilDefs" USING [magicMemoryLocation],
  PupDefs: FROM "PupDefs";  -- EXPORTS

AMCUCold: PROGRAM
  IMPORTS
    FrameDefs, InlineDefs, ImageDefs, MiscDefs,
    BcplOps, ProcessDefs, SegmentDefs, SystemDefs
  EXPORTS CommUtilDefs, DriverDefs, PupDefs
  SHARES SegmentDefs =
BEGIN

errorHandler: PROCEDURE [ERROR] ← DefaultErrorHandler;

CaptureErrors: PUBLIC PROCEDURE [proc: PROCEDURE[ERROR]] =
  BEGIN
  errorHandler ← proc
  END;

DefaultErrorHandler: PUBLIC PROCEDURE [why: ERROR] =
  BEGIN
  MiscDefs.CallDebugger["PupGlitch"L];
  Glitch[why];
  END;

Glitch: PUBLIC PROCEDURE [why: ERROR] =
  BEGIN
  errorHandler[why];
  END;

CleanupItem: TYPE = ImageDefs.CleanupItem;

AddCleanupProcedure: PUBLIC PROCEDURE [arg: POINTER TO CleanupItem] =
  BEGIN
  ImageDefs.AddCleanupProcedure[arg];
  END;

RemoveCleanupProcedure: PUBLIC PROCEDURE [arg: POINTER TO CleanupItem] =
  BEGIN
  ImageDefs.RemoveCleanupProcedure[arg];
  END;

Priority: TYPE = ProcessDefs.Priority;

SetPriority: PUBLIC PROCEDURE [p: Priority] =
  BEGIN
  ProcessDefs.SetPriority[p];
  END;

InterruptLevel: TYPE = ProcessDefs.InterruptLevel;

InterruptLevelAlreadyInUse: PUBLIC ERROR = CODE;
InterruptLevelNotInUse: PUBLIC ERROR = CODE;

AssignInterruptLevel: PUBLIC PROCEDURE [hint: InterruptLevel] RETURNS [InterruptLevel] =
  BEGIN
  IF ProcessDefs.CV[hint]#NIL THEN Glitch[InterruptLevelAlreadyInUse];
  RETURN[hint];
  END;

AddInterruptHandler: PUBLIC PROCEDURE [
    i: InterruptLevel, c: POINTER TO CONDITION, w: WORD] =
  BEGIN
  IF ProcessDefs.CV[i]#NIL THEN Glitch[InterruptLevelAlreadyInUse];
  ProcessDefs.CV[i] ← c;
  ProcessDefs.DisableInterrupts[];
  SDDefs.SD[SDDefs.sIOResetBits] ←
    InlineDefs.BITOR[SDDefs.SD[SDDefs.sIOResetBits],w];
  ProcessDefs.EnableInterrupts[];
  END;

RemoveInterruptHandler: PUBLIC PROCEDURE [i: InterruptLevel] =
  BEGIN
  IF ProcessDefs.CV[i]=NIL THEN Glitch[InterruptLevelNotInUse];
  ProcessDefs.CV[i] ← NIL;
  END;


GetEthernetHostNumber: PUBLIC PROCEDURE RETURNS [CARDINAL] =
  BEGIN
  HostCode: ARRAY[0..3) OF WORD ← [
    102400B,	-- sub 0,0
    061004B,	-- startio - returns host number in ac0
    001400B];  -- jmp 0,3
  RETURN[BcplOps.BcplJSR[JSR,@HostCode[0],NIL] MOD 400B];
  END;

LockCode: PUBLIC PROCEDURE [what: UNSPECIFIED] =
  BEGIN
  who: ControlDefs.GlobalFrameHandle = FrameDefs.GlobalFrame[what];
  FrameDefs.MakeCodeResident[who];
  END;

UnlockCode: PUBLIC PROCEDURE [what: UNSPECIFIED] =
  BEGIN
  who: ControlDefs.GlobalFrameHandle = FrameDefs.GlobalFrame[what];
  FrameDefs.UnlockCode[who];
  END;


-- On the Alto, all data is Resident - no need to do anything

LockData: PUBLIC PROCEDURE [p: LONG POINTER] =
  BEGIN
  END;

UnlockData: PUBLIC PROCEDURE [p: LONG POINTER] =
  BEGIN
  END;



AllocateSegment: PUBLIC PROCEDURE [nwords: CARDINAL] RETURNS [base: POINTER] =
  BEGIN
  pages: CARDINAL ← (nwords+AltoDefs.PageSize-1)/AltoDefs.PageSize;
  seg: SegmentDefs.DataSegmentHandle;
  base ← SystemDefs.AllocateResidentPages[pages];
  seg ← SegmentDefs.VMtoDataSegment[base];
  seg.type ← SegmentDefs.PupBufferDS;
  END;

FreeSegment: PUBLIC PROCEDURE [base: POINTER] =
  BEGIN OPEN SegmentDefs;
  seg: DataSegmentHandle ← VMtoDataSegment[base];
  DeleteDataSegment[seg];
  END;


-- Used only to allocate the buffer pool
AllocateHyperspace: PUBLIC PROCEDURE [
    nwords: CARDINAL] RETURNS [base: POINTER] =
  BEGIN
  pages: CARDINAL ← (nwords+AltoDefs.PageSize-1)/AltoDefs.PageSize;
  base ← SystemDefs.AllocateResidentPages[pages];
  END;

FreeHyperspace: PUBLIC PROCEDURE [base: POINTER] =
  BEGIN OPEN SegmentDefs;
  seg: DataSegmentHandle ← SegmentDefs.VMtoDataSegment[base];
  DeleteDataSegment[seg];
  END;

AllocateIocbs: PUBLIC PROCEDURE [n: CARDINAL] RETURNS [LONG POINTER] =
  BEGIN
  RETURN[AllocateSegment[n]];
  END;

FreeIocbs: PUBLIC PROCEDURE [p: LONG POINTER] =
  BEGIN
  FreeSegment[InlineDefs.LowHalf[p]];
  END;

IsBound: PUBLIC PROCEDURE [who: UNSPECIFIED] RETURNS [BOOLEAN] =
  BEGIN
  RETURN[FrameDefs.IsBound[who]];
  END;

SetDebuggingPointer: PUBLIC PROCEDURE [where: LONG POINTER] =
  BEGIN
  CommUtilDefs.magicMemoryLocation↑ ← InlineDefs.LowHalf[where];
  END;


-- initialization
END.  -- AMCUCold