-- File: TedOut.mesa, Last Edit: HGM  August 23, 1980  7:24 PM

-- Copyright  Xerox Corporation 1979, 1980

DIRECTORY
  InlineDefs USING [COPY],
  CommUtilDefs USING [GetTicks],
  TedDefs,
  AltoEthernetDefs,
  DriverDefs USING [Glitch, GetInputBuffer, PutOnGlobalInputQueue],
  BufferDefs,
  DriverTypes USING [pupEthernetPacket, ethernetBroadcastHost];

TedOut: MONITOR LOCKS TedDefs.lock
  IMPORTS InlineDefs, CommUtilDefs, DriverDefs, BufferDefs, AltoEthernetDefs, TedDefs
  EXPORTS TedDefs
  SHARES BufferDefs, DriverTypes =
BEGIN OPEN BufferDefs, DriverDefs, AltoEthernetDefs, TedDefs;


DriverNotActive: PUBLIC ERROR = CODE;

EncapsulateRpp: PUBLIC PROCEDURE [RppBuffer, PupHostID] = LOOPHOLE[EncapsulatePup];
EncapsulatePup: PUBLIC PROCEDURE [b: PupBuffer, destination: PupHostID] =
  BEGIN
  b.encapsulation ← [ ethernet [
    etherSpare1:, etherSpare2:, etherSpare3:, etherSpare4:,
    etherDest: destination, etherSource: TedDefs.myNetwork.hostNumber,
    ethernetType: DriverTypes.pupEthernetPacket ] ];
  b.length ← (b.pupLength+1+ethernetEncapsulationBytes)/2;
  END;

SendBuffer: PUBLIC ENTRY PROCEDURE [b: Buffer] =
  BEGIN
  copy: Buffer;
  IF tedPleaseStop THEN Glitch[DriverNotActive];
  b.device ← ethernet;
  IF b.encapsulation.etherDest=TedDefs.myNetwork.hostNumber
  OR b.encapsulation.etherDest=DriverTypes.ethernetBroadcastHost THEN
    BEGIN  -- sending to ourself, copy it over
    copy ← GetInputBuffer[];
    IF copy#NIL THEN
      BEGIN
      copy.device ← ethernet;
      InlineDefs.COPY[
        from: @b.encapsulation+ethernetEncapsulationOffset,
        nwords: b.length,
        to: @copy.encapsulation+ethernetEncapsulationOffset ];
      copy.length ← b.length;
      copy.network ← @TedDefs.myNetwork;
      PutOnGlobalInputQueue[copy];
      END;
    END;
  IF currentOutputBuffer=NIL THEN
    BEGIN
    currentOutputBuffer ← b;
    timeSendStarted ← CommUtilDefs.GetTicks[];
      IF myDevice.inputBuffer.pointer↑#0 THEN GOTO PouringIn;
      myDevice.interruptBit ← 0; -- inhibit interrupts for reset
      myDevice.postData ← EthernetNotPosted;
-- beware of hardware/microcode screwup
-- it seems to hang while sending, after a collision, until a gateway packet arrives
      UNTIL myDevice.postData#EthernetNotPosted DO
        StartIO[resetCommand];
        ENDLOOP;
      myDevice.interruptBit ← interruptBit; --interrupts back on
      myDevice.postData ← EthernetNotPosted;
    myDevice.retransmissionMask ← 0; -- zero the load for new packet
    myDevice.outputBuffer.count ← b.length;
    myDevice.outputBuffer.pointer ← ShortenData[
      @b.encapsulation+ethernetEncapsulationOffset];
    StartIO[outputCommand];
    EXITS PouringIn =>NULL;
    END
  ELSE Enqueue[@outputQueue,b];  -- output already in progress, don't klobber it
  END;

END.  -- TedOut