-- File: LoopBackPlug.mesa, Last Edit:
-- MAS April 17, 1980 10:55 PM
-- HGM October 15, 1979 10:26 PM
-- This module is needed/used only in the funny localOnly mode.

-- Copyright Xerox Corporation 1979, 1980


DIRECTORY
InlineDefs: FROM "InlineDefs" USING [COPY],
CommUtilDefs: FROM "CommUtilDefs" USING [GetEthernetHostNumber],
StatsDefs: FROM "StatsDefs" USING [StatBump, StatIncr],
DriverDefs: FROM "DriverDefs" USING [
doStats, Glitch,
useCount, firstNetwork, CreateDefaultEthernetDriver,
GetInputBuffer, AddDeviceToChain, Network, NetworkObject,
PutOnGlobalDoneQueue, PutOnGlobalInputQueue],
PupDefs: FROM "PupDefs" USING [GetDoStats],
BufferDefs: FROM "BufferDefs",
DriverTypes: FROM "DriverTypes" USING [pupLocalPacket],
PupTypes: FROM "PupTypes" USING [PupErrorCode, noErrorPupErrorCode];

LoopBackPlug: MONITOR
IMPORTS InlineDefs, CommUtilDefs, StatsDefs, DriverDefs, PupDefs
EXPORTS DriverDefs, PupDefs
SHARES BufferDefs, DriverTypes =
BEGIN OPEN StatsDefs, BufferDefs, DriverDefs;

localEncapsulationOffset: CARDINAL = 4;
localEncapsulationBytes: CARDINAL = 4;

myNetwork: DriverDefs.NetworkObject ← [
decapsulateBuffer: DecapsulateBuffer,
encapsulatePup: EncapsulatePup,
encapsulateRpp: EncapsulateRpp,
sendBuffer: SendBuffer,
forwardBuffer: ForwardBuffer,
activateDriver: ActivateDriver,
deactivateDriver: DeactivateDriver,
deleteDriver: DeleteDriver,
interrupt: DeactivateDriver, -- No interrupt routine
device: local,
alive: TRUE,
speed: 3000,
index: ,
netNumber: 0,
hostNumber: ,
next: NIL,
pupStats: PupStats,
stats: NIL ];

CommPackageAlreadyActive: PUBLIC ERROR = CODE;
Machin
eIDTooBigForEthernet: PUBLIC ERROR = CODE;

SetLocalOnly: PUBLIC PROCEDURE [localOnly: BOOLEAN] =
BEGIN
-- NB: This won’t work in the multi network case.
IF DriverDefs.useCount#0 THEN DriverDefs.Glitch[CommPackageAlreadyActive];
DriverDefs.firstNetwork ← NIL;
IF localOnly THEN [] ← CreateLoopBackNetwork[]
ELSE [] ← Driver
Defs.CreateDefaultEthernetDriver[];
END;

DecapsulateBuffer: PROCEDURE [b: Buffer] RETURNS [BufferDefs.BufferType] =
BEGIN
SELECT b.encapsulation.localType FROM
DriverTypes.pupLocalPacket => RETURN[pup
];
ENDCASE
=> RETURN[rejected];
END;

EncapsulateRpp: PROCEDURE [RppBuf
fer, PupHostID] = LOOPHOLE[EncapsulatePup];
EncapsulatePup: PROCEDURE [b: PupBuffer, destination: PupHostID] =
BEGIN
b.encapsulation ← [ local [
localSpare1:, localSpare2:, localSpare3:, localSpare4:,
localHost: b.dest.host,
localType: DriverTypes.pupLocalPacket ] ];
b.length ← (b.pupL
ength+1+localEncapsulationBytes)/2;
END;

ForwardBuffer: PROCEDURE [b: Buffer] RETURNS [PupTypes.PupErrorCode] =
BEGIN
SendBuffer[b];
RE
TURN[PupTypes.noErrorPupErrorCode];
END;

SendBuffer: ENTRY PROCEDURE [b: Buffer] =
BEGIN
copy: Buffer;
b.device ← local;
IF b.encapsulation.localHost=myNetwork.hostNumber THEN
BEGIN -- sending to ourself, copy it over
copy ← GetInputBuffer[];
IF copy#NIL THEN
BEGIN
copy.device ← local;
InlineDefs.COPY[
from: @b.encapsulation+localEncapsulationOffset,
nwords: b.length,
to: @copy.encapsulation+localEncapsulationOffset ];
copy.length ← b.length;
copy.network ← @myNetwork;
IF doStats THEN StatIncr[statEtherPacketsLocal];
IF doStats THEN StatBump[statEtherWordsLocal,b.length];
END
ELSE IF doStats THEN StatIncr[statEtherEmptyFreeQueue];
PutOnGlobalDoneQueue[b]; -- give this one back first
IF copy#NIL THEN PutOnGlobalInputQueue[copy];
RETURN
END;
PutOnGlobalD
oneQueue[b]; -- just throw it away
END;

CreateLoopBackNetwork: PUBLIC PROCEDURE RETURNS [BOOLEAN] =
BEGIN
AddDeviceToC
hain[@myNetwork,0];
RETURN[TRUE];
END;


DeleteDriver
: PROCEDURE =
BEGIN
END;

ActivateDriver: PROCEDURE =
BEGIN
myNetwork.hostNumber ← Co
mmUtilDefs.GetEthernetHostNumber[];
END;

De
activateDriver: PROCEDURE =
BEGIN
END;

PupStats: PROCEDURE [PupBuffer, Network] RETURNS [BOOLEAN] =
BEGIN
RETURN[FALSE];
END;

-- initialization
[] ← PupDefs.GetDoStats[]; -- Get main PupPackage started
END. -- LoopBackPlug module