-- File: AltoSpecialSystem.mesa,  Last Edit by: HGM  March 12, 1981  8:03 PM

DIRECTORY
  MiscAlpha USING [aREADRAM],
  CommUtilDefs USING [GetEthernetHostNumber],
  DriverDefs USING [GetUseCount, GetDeviceChain, Glitch, Network],
  InlineDefs USING [BITOR, BITSHIFT, LowByte],
  Mopcodes USING [zMISC],
  Process USING [Yield],
  SegmentDefs USING [GetMemoryConfig],
  SpecialSystem USING [HostNumber, ProcessorID];

AltoSpecialSystem: PROGRAM
  IMPORTS Process, SegmentDefs, CommUtilDefs, DriverDefs, InlineDefs
  EXPORTS SpecialSystem =
  BEGIN

  CommPackageNotActive: PUBLIC ERROR = CODE;
  FirstDriverNeitherLocalNorEthernet: PUBLIC ERROR = CODE;

  -- For now, we do not have a hard-wired ProcessorID, so we use one derived from our Ethernet Address.  That brings up the problem of which Ethernet Address should be used, since in general we may be connected to multiple networks.  The answer, for now, is to use the address from the first device on the chain, which will normally be the standard Ethernet board.

  GetProcessorID: PUBLIC PROCEDURE RETURNS [SpecialSystem.ProcessorID] =
    BEGIN
    IF SegmentDefs.GetMemoryConfig[].AltoType = D0 THEN
      RETURN[GetD0ProcessorID[]];
    RETURN[GetAltoProcessorID[]];
    END;

  GetD0ProcessorID: PROCEDURE RETURNS [SpecialSystem.ProcessorID] =
    BEGIN
    csw: CSWord = ReadRam[7777B];
    CSWord: TYPE = MACHINE DEPENDENT RECORD [
      bits16To31: CARDINAL,
      bits0To15: CARDINAL,
      bits32To35: [0..17B],
      address: [0..7777B]];
    ReadRam: PROCEDURE [address: [0..7777B]] RETURNS [CSWord] = MACHINE CODE
      BEGIN Mopcodes.zMISC, MiscAlpha.aREADRAM END;
    RETURN[SpecialSystem.HostNumber[physical[0, csw.bits0To15, csw.bits16To31]]]
    END;

  -- AltoSLADriver.EncapsulateOis knows about this encoding
  GetAltoProcessorID: PROCEDURE RETURNS [p: SpecialSystem.ProcessorID] =
    BEGIN OPEN DriverDefs, InlineDefs;
    pDotC: CARDINAL;
    network: DriverDefs.Network ← DriverDefs.GetDeviceChain[];
    IF GetUseCount[] = 0 THEN Glitch[CommPackageNotActive];
    IF network = NIL THEN Glitch[CommPackageNotActive];
    UNTIL network = NIL DO
      IF network.device = sla THEN EXIT;
      network ← network.next;
      REPEAT
      FINISHED => network ← DriverDefs.GetDeviceChain[];  -- No sla, use Ethernet
      ENDLOOP;
    SELECT network.device FROM
      local => pDotC ← CommUtilDefs.GetEthernetHostNumber[];
      sla, ethernetOne =>
	BEGIN
	UNTIL network.netNumber # [0, 0] DO Process.Yield[]; ENDLOOP;
	pDotC ← BITOR[
	  BITSHIFT[LowByte[network.netNumber.b], 8], LowByte[network.hostNumber]];
	END;
      ENDCASE => Glitch[FirstDriverNeitherLocalNorEthernet];
    --  125026B = AA16 hex.  It comes from Bob Printis.
    p ← SpecialSystem.HostNumber[physical[a: 0, b: 125026B, c: pDotC]];
    END;

  END.