-- 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;
MachineIDTooBigForEthernet: 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 [] ← DriverDefs.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 [RppBuffer, 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.pupLength+1+localEncapsulationBytes)/2;
END;
ForwardBuffer: PROCEDURE [b: Buffer] RETURNS [PupTypes.PupErrorCode] =
BEGIN
SendBuffer[b];
RETURN[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;
PutOnGlobalDoneQueue[b]; -- just throw it away
END;
CreateLoopBackNetwork: PUBLIC PROCEDURE RETURNS [BOOLEAN] =
BEGIN
AddDeviceToChain[@myNetwork,0];
RETURN[TRUE];
END;
DeleteDriver: PROCEDURE =
BEGIN
END;
ActivateDriver: PROCEDURE =
BEGIN
myNetwork.hostNumber ← CommUtilDefs.GetEthernetHostNumber[];
END;
DeactivateDriver: PROCEDURE =
BEGIN
END;
PupStats: PROCEDURE [PupBuffer, Network] RETURNS [BOOLEAN] =
BEGIN
RETURN[FALSE];
END;
-- initialization
[] ← PupDefs.GetDoStats[]; -- Get main PupPackage started
END. -- LoopBackPlug module