-- File: AltoSlaDefs.mesa,  Last Edit: HGM  December 7, 1980  10:55 PM

DIRECTORY
  InlineDefs USING [BcplLongNumber],
  Mopcodes USING [zPOP],
  Password USING [Encrypted],
  StatsDefs USING [StatCounterIndex],
  BufferDefs USING [Buffer, QueueObject];

AltoSlaDefs: DEFINITIONS =
  BEGIN

  NIL0: POINTER = LOOPHOLE[0];
  noLCB: LCB = NIL0;

  maxLine: CARDINAL = 16;
  Line: TYPE = [0..maxLine);

  LTE: TYPE = POINTER TO LineTableEntry;
  LineTableEntry: TYPE = MACHINE DEPENDENT RECORD [
    -- EVEN WORD BOUNDARY
    link: POINTER, -- not used by microcode
    hardwareStatus: WORD,
    inputLCB: LCB,
    inputState: State,
    outputLCB: LCB,
    outputState: State];

  LCB: TYPE = POINTER TO LineControlBlock;
  LongLCB: TYPE = LONG POINTER TO LineControlBlock;
  LineControlBlock: TYPE = MACHINE DEPENDENT RECORD [
    -- EVEN WORD BOUNDARY
    next: LCB,
    interruptBit: WORD,
    finished: BOOLEAN,
    microcodeError: Error,
    hardwareStatus: WORD,
    -- this is really just one variant of several, but it is the only one we use
    half: {left, right},
    bytesLeft: [0..77777B],
    currentData: POINTER,
    partialCrc: WORD,
    unused: WORD];

  State: TYPE = MACHINE DEPENDENT{
    reset(0B), rIdle(1B), tIdle(2B), rCaat(3B), tCaat(4B), tUIdl(5B),
    -- Initial states
    rDLE1(10B), rData, rDLE2, rETX1, rETX2, -- Bisync Recv states
    tSYN1, tSYN2, tSYN3, tDLE1, tData, tDLE2, tDLE3, tETX1, tETX2, tEnd(26B),
    tUblk(27B), (177777B)};

  Error: TYPE = MACHINE DEPENDENT{
    ok(0B), hardware(1B), missingStx(3B), bufferOverflow(4B), trashAfterDle(5B),
    crc(6B), (77777B)};

  maxSlaHost: CARDINAL = 64;
  SlaHost: TYPE = (0..maxSlaHost];
  noPartner: CARDINAL = 0;

  maxByte: CARDINAL = 256;
  Byte: TYPE = [0..377B];

  syn: Byte = 26B;
  dle: Byte = 20B;
  stx: Byte = 2B;
  etx: Byte = 203B;
  fill: Byte = 377B;

  -- doesn't count dle doubling
  overheadPerPacket: CARDINAL = 9;
  -- syn, syn, syn dle, stx, ... dle, etx, crc, crc



  eiaControlAddr: POINTER TO WORD = LOOPHOLE[177700B];
  commProcControlAddr: POINTER TO WORD = LOOPHOLE[177300B];

  eiaShift: CARDINAL = 1000B; -- shift line number into EIA control word
  commProcShift: CARDINAL = 4; -- shift line number into ComProc address offset


  ShortenIocb: PROCEDURE [LongLCB] RETURNS [LCB] = MACHINE CODE
    BEGIN Mopcodes.zPOP; END;

  ShortenData: PROCEDURE [LONG POINTER] RETURNS [POINTER] = MACHINE CODE
    BEGIN Mopcodes.zPOP; END;

  -- Things used by SLA driver.  Needed by GatePrint

  LIB: TYPE = POINTER TO LineInfoBlock;
  LineInfoBlock: TYPE = RECORD [
    sendBuffer: BufferDefs.Buffer, -- there should normally be only one or none
    recvBuffer: BufferDefs.Buffer, -- there should normally be two
    state: LineState,
    lineNeedsPassword: BOOLEAN,
    partner: Byte, -- SlaHost number of other end of this line, 0 if none
    timeOfLastRT, timeSendStarted: CARDINAL,
    hiPriQueue, lowPriQueue: BufferDefs.QueueObject,
    hiPacketsSent, hiBytesSent, hiQueueDelay: LONG CARDINAL,
    queueDelay: LONG CARDINAL,
    connRejections, hiRejections, rejections: LONG CARDINAL,
    deaths, stuck, timeout, overrun: CARDINAL,
    -- The following statistics are the same as the ones kept by the Novas
    packetsSent, packetsRecv: LONG CARDINAL,
    bytesSent, bytesRecv: LONG CARDINAL,
    syncErrors, crcErrors, controlErrors: CARDINAL];

  LineState: TYPE = {
    down, up, loopedBack, missing, halfUp, passwordOk, needPassword, badPassword};

  RoutingTableEntry: TYPE = RECORD [hops: Byte, line: Byte];
  maxHops: Byte = 15; -- highest legal hop count
  longHop: Byte = 377B; -- flag for can't get there
  RoutingTablePacket: TYPE = RECORD [
    sourceHost: Byte, numEntries: Byte, rt: ARRAY SlaHost OF RoutingTableEntry];


  -- Password things
  RememberDialinPassword: PROCEDURE [Password.Encrypted]; -- listener
  RememberDialoutPassword: PROCEDURE [STRING]; -- sender
  LineNeedsPassword: PROCEDURE [Line];

  GetSlaLineTable: PROCEDURE RETURNS [POINTER TO ARRAY Line OF LineTableEntry];
  GetCrcTable: PROCEDURE RETURNS [POINTER TO ARRAY [0..maxByte) OF WORD];
  GetSlaRoutingTable: PROCEDURE
    RETURNS [POINTER TO ARRAY SlaHost OF RoutingTableEntry];
  GetSlaInfoBlocks: PROCEDURE RETURNS [DESCRIPTOR FOR ARRAY OF LineInfoBlock];


  SetupSlaThings: PROCEDURE;

  statSlaPacketsSent: StatsDefs.StatCounterIndex;
  statSlaWordsSent: StatsDefs.StatCounterIndex;

  statSlaPacketsRecv: StatsDefs.StatCounterIndex;
  statSlaWordsRecv: StatsDefs.StatCounterIndex;

  statSlaRoutingPacketsSent: StatsDefs.StatCounterIndex;
  statSlaRoutingPacketsReceived: StatsDefs.StatCounterIndex;

  statSlaEmptyFreeQueue: StatsDefs.StatCounterIndex;
  statSlaROR: StatsDefs.StatCounterIndex;
  statSlaCRCError: StatsDefs.StatCounterIndex;
  statSlaSyncError: StatsDefs.StatCounterIndex;
  statSlaControlError: StatsDefs.StatCounterIndex;

  statSlaNoRoute: StatsDefs.StatCounterIndex;
  statSlaQueueFull: StatsDefs.StatCounterIndex;
  statSlaConnectionLimit: StatsDefs.StatCounterIndex;

  statSlaPacketsStuck: StatsDefs.StatCounterIndex;
  statSlaLineTimeout: StatsDefs.StatCounterIndex;
  statSlaLineDied: StatsDefs.StatCounterIndex;
  statSlaFCT: StatsDefs.StatCounterIndex;


  -- Statistics info for GateControl or whatever...
  slaStatsReply: WORD = 4;

  -- The second word of the reply is the version number.  The third word is the number of hosts in the routing table, then comes the routing table itself.  (Don't forget to skip host 0.)  The next word is the highest line number, and it is followed by an array of info for each line.

  slaVersion: WORD = 1;

  SlaStatsEntry: TYPE = RECORD [
    packetsSent: InlineDefs.BcplLongNumber,
    packetsRecv: InlineDefs.BcplLongNumber,
    bytesSent: InlineDefs.BcplLongNumber,
    bytesRecv: InlineDefs.BcplLongNumber,
    syncErrors: CARDINAL,
    badCrc: CARDINAL,
    controlError: CARDINAL,
    state: LineState];

  END.