-- File: LoopBackPlug.mesa, Last Edit: BLyon January 16, 1981 1:36 PM -- This module is needed/used only in the funny localOnly mode. DIRECTORY CommFlags USING [doStats], CommUtilDefs USING [GetEthernetHostNumber, CopyLong], StatsDefs USING [StatBump, StatIncr], DriverDefs USING [ Glitch, GetUseCount, SmashDeviceChain, GetInputBuffer, AddDeviceToChain, Network, NetworkObject, PutOnGlobalDoneQueue, PutOnGlobalInputQueue], PupDefs USING [GetDoStats], BufferDefs, DriverTypes USING [localEncapsulationBytes, localEncapsulationOffset], PupTypes USING [PupErrorCode], SpecialSystem USING [HostNumber]; LoopBackPlug: MONITOR IMPORTS CommUtilDefs, StatsDefs, DriverDefs, PupDefs EXPORTS BufferDefs, DriverDefs, PupDefs SHARES BufferDefs, DriverTypes, SpecialSystem = BEGIN OPEN StatsDefs, BufferDefs, DriverDefs; -- EXPORTed TYPEs Network: PUBLIC TYPE = DriverDefs.Network; myNetwork: DriverDefs.NetworkObject ← [decapsulateBuffer: DecapsulateBuffer, encapsulatePup: EncapsulatePup, encapsulateOis: EncapsulateOis, sendBuffer: SendBuffer, forwardBuffer: ForwardBuffer, activateDriver: ActivateDriver, deactivateDriver: DeactivateDriver, deleteDriver: DeleteDriver, interrupt: DeactivateDriver, -- No interrupt routine device: local, alive: TRUE, speed: 3000, index:, buffers: 0, spare: 0, netNumber: [0, 0], hostNumber:, next: NIL, pupStats: PupStats, stats: NIL]; CommPackageAlreadyActive: PUBLIC ERROR = CODE; SetLocalOnly: PUBLIC PROCEDURE [localOnly: BOOLEAN] = BEGIN -- NB: This won't work in the multi network case. IF DriverDefs.GetUseCount[] # 0 THEN DriverDefs.Glitch[CommPackageAlreadyActive]; DriverDefs.SmashDeviceChain[]; IF localOnly THEN [] ← CreateLoopBackDriver[]; END; DecapsulateBuffer: PROCEDURE [b: Buffer] RETURNS [BufferDefs.BufferType] = BEGIN SELECT b.encapsulation.localType FROM pup => RETURN[pup]; ois => RETURN[ois]; ENDCASE => RETURN[rejected]; END; EncapsulatePup: PROCEDURE [b: PupBuffer, destination: PupHostID] = BEGIN b.encapsulation ← [local[ localSpare1:, localSpare2:, localSpare3:, localSpare4:, localSpare5:, localHost: b.dest.host, localType: pup]]; b.length ← (b.pupLength + 1 + DriverTypes.localEncapsulationBytes)/2; END; EncapsulateOis: PROCEDURE [ b: OisBuffer, destination: SpecialSystem.HostNumber] = BEGIN IF TRUE THEN ERROR; b.length ← (b.ois.pktLength + 3)/2; END; ForwardBuffer: PROCEDURE [b: Buffer] RETURNS [PupTypes.PupErrorCode] = BEGIN SendBuffer[b]; RETURN[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; CommUtilDefs.CopyLong[ from: @b.encapsulation + DriverTypes.localEncapsulationOffset, nwords: b.length, to: @copy.encapsulation + DriverTypes.localEncapsulationOffset]; copy.length ← b.length; copy.network ← LONG[@myNetwork]; IF CommFlags.doStats THEN StatIncr[statEtherPacketsLocal]; IF CommFlags.doStats THEN StatBump[statEtherWordsLocal, b.length]; END ELSE IF CommFlags.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; CreateLoopBackDriver: 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.