-- BEWARE SHORT PACKETS
-- edited by: HGM August 10, 1977 5:45 PM
-- Module ... PUP DEFS
-- edited by: HGM July 31, 1977 11:07 PM
-- edited by: wrc June 14, 1977 1:04 PM

DIRECTORY
ProcessDefs: FROM "ProcessDefs",
MesaDefs: FROM "MesaDefs",
Mopcodes: FROM "Mopcodes",
-- Block, Free, StartIO
NovaOps: FROM "NovaOps",
-- CleanupItem
SysDefs: FROM "SysDefs";
-- Stats stuff


DEFINITIONS FROM MesaDefs;

PupDefs: DEFINITIONS=BEGIN

-- you need one of these!
PupInterface: TYPE=POINTER TO PupVector;

-- Things that you can BIND to
PupPackageMake: PROCEDURE RETURNS[PupInterface];
GetPupVector: PROCEDURE RETURNS[PupInterface];
FreePupVector: PROCEDURE;
SetSandBarOK: PROCEDURE [BOOLEAN];

-- client PROCEDURES called from within the PupPackage
ByteStreamListenerTarget: TYPE=PROCEDURE[UNSPECIFIED,ByteStream,PAddress];
PktStreamListenerTarget: TYPE=PROCEDURE[UNSPECIFIED,PktStream,PAddress];
SocketTarget: TYPE=PROCEDURE[UNSPECIFIED,Buffer];
XXX: TYPE=RECORD[POINTER TO XXX]; -- junk word if you don’t need instance data

-- buffers and streams
ByteStream: TYPE=POINTER TO ByteStreamObject;
PktStream: TYPE=POINTER TO PktStreamObject;
Buffer: TYPE=POINTER TO BufferObject;

-- for Get/Put Block
BlockHandle: TYPE=POINTER TO BlockFinger;
BlockFinger: TYPE=DESCRIPTOR FOR ARRAY OF WORD;

-- Things needed to talk about machines and ports
Connection: TYPE = POINTER TO ConnObject;
ConnObject: TYPE = RECORD[local,remote:PAddress];

PAddress: TYPE=POINTER TO Address;
Address: TYPE=MACHINE DEPENDENT RECORD[
network: Net,
host: Host,
socket: Pair];

Host: TYPE=Byte;
ThisHost: Host=377B;
AllHosts: Host=376B;
Net: TYPE=Byte;
ThisNet: Net=0B;
-- NewUniqueSocket: Pair=[0,0];
compiler won’t take it

-- Basic Data TYPEs used within Pup RECORDs
Byte: TYPE=[0..377B];
Pair: TYPE=MACHINE DEPENDENT RECORD[first,second:CARDINAL];
Triple: TYPE=MACHINE DEPENDENT RECORD[first,second,third:CARDINAL];

-- fine print that a client might be interested in

CloseReason: TYPE= {localClose, remoteClose,
transmissionTimeout, noRouteToNetwork, remoteReject};

Glitch: TYPE= {
-- dumb user BUGs
streamNotOpen, streamAlreadyOpen,
socketUninitialized, illegalPupLength, invalidAddress,
-- PupPackage BUGs
sentQueueScrambled, queueScrambled, freeQueueTrashed,
neitherDataNorMark, noBuffer, garbageBuffer, garbageQueue,
-- core clobbered, or hardware sick
badEtherDone, funnyELLoc,
-- program limitations
tooManySockets, tooManyNetworks, cantMakeImageWhilePupActive};

-- other useful things
clock:POINTER TO INTEGER=LOOPHOLE[430B];
msPerTick:INTEGER=39;

-- the Compiler won’t take multi word constants
WellKnownSocket: TYPE=CARDINAL;
telnetSoc: WellKnownSocket=1;
gatewaySoc: WellKnownSocket=2;
ftpSoc: WellKnownSocket=3;
miscSrvSoc: WellKnownSocket=4;
statSoc: WellKnownSocket=22B;


-- this is an attempt to get the TYPE checker to help us
-- unfortunately, the values are a bit sparce
-- be sure to have enough values to make it an 8 bit field
PupType: TYPE={
-- 000-077 OCTAL!
Registered Pup Types
echoMe,
iAmEcho,badEcho,pt003,error,pt005,pt006,pt007,
rfc,
abort,end,endRep,pt014,pt015,pt016,pt017,
data,
aData,ack,mark,int,intRep,aMark,pt027,
eData,
eAck,eEnd,eAbort,pt034,pt035,pt036,pt037,
pt040,
pt041,pt042,pt043,pt044,pt045,pt046,pt047,
pt050,
pt051,pt052,pt053,pt054,pt055,pt056,pt057,
pt060,
pt061,pt062,pt063,pt064,pt065,pt066,pt067,
pt070,
pt071,pt072,pt073,pt074,pt075,pt076,pt077,
-- 100-177
pt100,
pt101,pt102,pt103,pt104,pt105,pt106,pt107,
pt110,
pt111,pt112,pt113,pt114,pt115,pt116,pt117,
pt120,
pt121,pt122,pt123,pt124,pt125,pt126,pt127,
pt130,
pt131,pt132,pt133,pt134,pt135,pt136,pt137,
pt140,
pt141,pt142,pt143,pt144,pt145,pt146,pt147,
pt150,
pt151,pt152,pt153,pt154,pt155,pt156,pt157,
pt160,
pt161,pt162,pt163,pt164,pt165,pt166,pt167,
pt170,
pt171,pt172,pt173,pt174,pt175,pt176,pt177,

-- 200+
Unregistered Pup Types
-- Socket 2 - Gateway info
gatewayRequest,
gatewayInfo,

-- Socket 4 - Misc services
dateTenexRequest,
dateTenexIs,
dateAltoRequest,
dateAltoIs,
pt206,pt207,
mailCheck,
mailIsNew,mailNotNew,mailError,
pt214,pt215,pt216,pt217,
nameLookup,
nameIs,nameError,
pt223,pt224,pt225,pt226,pt227,
whereIsUser,
userIs,userError,
pt233,pt234,pt235,pt236,pt237,
netDirVersion,
sendNetDir,
pt242,pt243,pt244,pt245,pt246,pt247
};



-- see <PUP>Servers.EARS (Taft)

-- Socket 4 Misc Services - these overlap with Gateway info
dateTextRequest: PupType=gatewayRequest;
dateTextIs: PupType=gatewayInfo;

-- Socket 22 Statistics - more overlap
statisticsRequest: PupType=gatewayRequest;
statisticsAre: PupType=gatewayInfo;

-- Compile time switches

doStats: BOOLEAN=SysDefs.doStats;
doCheck: BOOLEAN=TRUE; -- normal run time checks
doDebug: BOOLEAN=TRUE; -- extra run time checks
validPointer: TYPE=[7400B..163000B); -- from a COremap of Mesa.Image

-- This is the giant PupVector

PupVector: TYPE=MACHINE DEPENDENT RECORD[

-- frequently used things
ScheduleeYields: PROCEDURE,
StatIncr: PROCEDURE[SysDefs.CI],
StatBump: PROCEDURE[SysDefs.CI,CARDINAL],
mesa: MesaFacilitiesHandle,

-- Packet level routines
GetContentsLength: PROCEDURE [Buffer] RETURNS[CARDINAL],
SetContentsLength: PROCEDURE [Buffer,CARDINAL],
SetPupLength: PROCEDURE [Buffer,CARDINAL],
GetFreePacket: PROCEDURE RETURNS [Buffer],
ReturnFreePacket: PROCEDURE [Buffer],

--Queue Interface
Dequeue: PROCEDURE [Queue] RETURNS [Buffer],
Enqueue: PROCEDURE [Queue,Buffer],
LockedDequeue: PROCEDURE [Queue] RETURNS [Buffer],
LockedEnqueue: PROCEDURE [Queue,Buffer],
QueueMake: PROCEDURE RETURNS [Queue],
QueueDestroy: PROCEDURE[Queue],

-- Socket Interface
SocketMake: PROCEDURE RETURNS [Socket],
SocketDestroy: PROCEDURE [Socket],
SocketTakeFromUser: SocketTarget,
SocketSet: PROCEDURE [Socket, SocketType, Connection, UNSPECIFIED, SocketTarget],

-- ByteStream Interface
ByteStreamPutBlock: PROCEDURE [ByteStream,BlockHandle],
ByteStreamGetEasyBlock: PROCEDURE [ByteStream,BlockHandle] RETURNS [CARDINAL],
ByteStreamGetWholeBlock: PROCEDURE [ByteStream,BlockHandle],

ByteStreamGet: PROCEDURE [ByteStream] RETURNS [Byte],
ByteStreamGetChar: PROCEDURE [ByteStream] RETURNS [CHARACTER],
ByteStreamAbortGet: PROCEDURE [ByteStream],

ByteStreamPut: PROCEDURE [ByteStream,Byte],
ByteStreamPutChar: PROCEDURE [ByteStream,CHARACTER],
ByteStreamPutString: PROCEDURE [ByteStream,STRING],
ByteStreamSendNow: PROCEDURE [ByteStream],
ByteStreamPutMark: PROCEDURE [ByteStream,Byte],

ByteStreamMake:PROCEDURE [Connection] RETURNS [ByteStream],
ByteStreamMakeListener: PROCEDURE
[Pair, ByteStreamListenerTarget, UNSPECIFIED] RETURNS [ByteStream],
ByteStreamOpen: PROCEDURE [ByteStream],
ByteStreamClose: PROCEDURE [ByteStream],
ByteStreamDestroy: PROCEDURE [ByteStream],


-- PacketStream Interface
PktStreamMake: PROCEDURE [Connection] RETURNS [PktStream],
PktStreamMakeListener: PROCEDURE
[Pair, PktStreamListenerTarget, UNSPECIFIED] RETURNS [PktStream],
PktStreamDestroy: PROCEDURE[PktStream],
PktStreamOpen, PktStreamClose: PROCEDURE[PktStream],
PktStreamTakeFromUser: PROCEDURE[PktStream,Buffer],
PktStreamGetForUser: PROCEDURE[PktStream] RETURNS [Buffer],
PktStreamSendMark: PROCEDURE[PktStream,Byte],

--Common to PS hot and cold (and ByteStream)
PktStreamSlowFromUser, PktStreamFastFromUser:SocketTarget,
PktStreamMakeAid: PROCEDURE [Connection, PktStreamState, Pair] RETURNS [PktStream],
ByteStreamMakeAid: PROCEDURE [Connection, PktStreamState, Pair] RETURNS [ByteStream],
PktStreamTakeFromDistributor:SocketTarget,
Retransmitter,SendAbort,SendAck,SendRfc,SendEnd,
Got
Rfc,GotEnd,GotEndReply,GotAbort,GotError:
PROCEDURE[PktStream],
SmashClosed: PROCEDURE[PktStream,CloseReason],

-- NameLookup
TestAndSetChecksum: PROCEDURE[Buffer] RETURNS [BOOLEAN],
EthernetInputProcess: PROCEDURE[Queue],
GetAddress,NameLookup:
PROCEDURE[a:PAddress,s:STRING,e:STRING] RETURNS[BOOLEAN],
ParseAddressConstant:
PROCEDURE[PAddress,STRING] RETURNS[BOOLEAN],
AppendAddress:PROCEDURE[s:STRING,a:PAddress],
PrintAddress:
PROCEDURE [a:PAddress],

--SHOW
ShowBuffer: PROCEDURE
[CARDINAL,Buffer],

-- SIGNALs
PupGlitch: SIGNAL [why: Glitch],
StreamClosing: SIGNAL [why: CloseReason],
NoRouteToNetwork: SIGNAL,
AbortGet: SIGNAL [discardedWords:CARDINAL],
OddBytes: SIGNAL,
MarkInStream: SIGNAL,

-- Start+Stop
PupPackageMake: PROCEDURE RETURNS[PupInterface],
PupPackageDestroy: PROCEDURE,
RouterHotInit,GatewayRequest: PROCEDURE,
EthernetInterruptRoutine: PROCEDURE,
GatewayTimeout: PROCEDURE[UNSPECIFIED],
GatewaySee,DistributorTakeThis: PROCEDURE[Buffer],

-- various other user interface goodies
bufferPoolSize:CARDINAL,
myHost:CARDINAL,
myNetwork:CARDINAL,
checkit:BOOLEAN,
showit:BOOLEAN,
stormy:BOOLEAN,
localOnly:BOOLEAN,

-- fixup parPup in case it moves
routerHotParPup,
routerColdParPup, psHotParPup,
psColdParPup,
bytestreamParPup, nameLookupParPup,
showParPup:
POINTER TO PupInterface,

-- things that live here rather than in global frames
ZeroPair: Pair,
pupUseCount: CARDINAL,
cleanupItem: NovaOps.CleanupItem, -- RouterCold
firstConnectionID: CARDINAL, --PSCold:PKTStreamOpen
spareSocket: CARDINAL, -- RouterCold:SocketSet, PsCold:SendRfc
lightning,bolt: INTEGER, -- RouterHot debugging hack

freeQueue: Queue, -- FreeQueue+buffers
packetDataSegment: DataSegmentHandle,
firstBuffer: Buffer, -- debugging

globalInQ: Queue, -- RouterHot
socTab: SocTab,
routeBySoc: ARRAY SocTab OF Socket,
routeTable: RouteTable,

RouterPleaseDie: BOOLEAN, -- RouterHot.GateWayTimeout
oldTime: INTEGER,

EtherPleaseDie: BOOLEAN, -- RouterHot.EthernetInterruptRoutine
oneNetwork: Network,
myPs: PktStream,
fastAckQueue: Queue,
fastAckQueueObject: QueueObject,
fastAck: BufferObject,
fastAckXSum: WORD,
pCurrentOutBuffer: POINTER TO Buffer, -- debugging
pCurrentInBuffer: POINTER TO Buffer,
pNextInBuffer: POINTER TO Buffer,

ScheduleeCreate: PROCEDURE[PROCEDURE[UNSPECIFIED],UNSPECIFIED],
GetMesaVector: PROCEDURE RETURNS[MesaFacilitiesHandle],
GetPupVector: PROCEDURE RETURNS[PupInterface],
FreeMesaVector: PROCEDURE,
FreePupVector: PROCEDURE,
LockPupCode: PROCEDURE [GlobalFrameHandle],
parStats: SysDefs.StatsInterface,
RouterHotFH: UNSPECIFIED -- GlobalFrameHandle, ControlLink
];



--QUEUE
Queue: TYPE = POINTER TO QueueObject;
QueueObject: TYPE = RECORD [length: CARDINAL, first, last: Buffer];

--PACKET
WordBlockDescriptor:TYPE =
MACHINE DEPENDENT RECORD [count:CARDINAL, pointer:POINTER];
--overheadPerPacket:CARDINAL=3+2;
bytesPerPupHeader:CARDINAL=22;
dataBytesPerAck:CARDINAL=6; bytesPerAck:CARDINAL=bytesPerPupHeader+dataBytesPerAck;
dataBytesPerRFC:CARDINAL=6; bytesPerRFC:CARDINAL=bytesPerPupHeader+dataBytesPerRFC;
dataWordsPerPup:CARDINAL=28; --266;
wordsPerPup:CARDINAL=10+dataWordsPerPup+1;
wordsPerBuffer:CARDINAL=10+wordsPerPup+2;--2 spare

BufferObject: TYPE = MACHINE DEPENDENT RECORD[
next: Buffer, queue, requeue: Queue,
length: CARDINAL,
time: INTEGER,
network: Network, -- FastHeader starts here
tries: CARDINAL,
eWord: Pair,
pupLength: CARDINAL, -- first word of PUP
transportControl: Byte,
pupType: PupType,
pupID: Pair,
dest, source: Address,
text: Triple];--there is more beyond here, of course

-- PktStream keeps one of these all setup, and just BLTs
-- it into the buffer rather than moving each field
-- be sure it is kept parallel to BufferObject
PtrFastHeader: TYPE = POINTER TO FastHeader;
FastHeader: TYPE = MACHINE DEPENDENT RECORD[
network: Network,
tries: CARDINAL,
eWord: Pair,
pupLength: CARDINAL,
transportControl: Byte,
pupType: PupType,
pupID: Pair,
dest, source: Address];

--SOCKET

SocketType: TYPE = {wild,verify,latch};
Socket: TYPE=POINTER TO SocketObject;
SocketObject: TYPE=RECORD[
local,remote: Address,
myUser: UNSPECIFIED,
target: SocketTarget,
init: BOOLEAN, type: SocketType];

--BYTE STREAM

ByteBuffer: TYPE=STRING;
-- Should be POINTER TO ARRAY [0.. 2*dataWordsPerPup] OF Byte;
-- but Mesa won’t hack that

ByteStreamObject:TYPE=RECORD[
myPacketStream: PktStream,
outBuffer, inBuffer: Buffer,
outData, inData: ByteBuffer,
outIndex, inIndex, inEnd, outEnd: CARDINAL,
c: CARDINAL,
abortGet: BOOLEAN];


--PKT STREAM

PktStreamState: TYPE = {idle,halfOpen,open,talking,finishing,end,closed};
ListenerKind: TYPE = {NotListener, ByteListener, PktListener};

PktStreamObject: TYPE = RECORD[
state: PktStreamState,
inQueue, outOfOrderQueue, sentQueue, tempQueue: Queue,
socket: Socket,
local, remote: Address,
c: Buffer, --the currently active one
id: Pair, pupLength: CARDINAL, --the currently active ones
sentBuffer: Buffer, --holds the head of the sent queue
connectionID, nextInputID, nextOutputID, allocatedID,
maxOutputID, allocationID, ackedID: Pair,
unackedPups, allocatedPups, outEnd: CARDINAL,
freedUp, requestAck: CARDINAL,
temp, range: INTEGER,
listenerTarget: PktStreamListenerTarget,
listenerData: UNSPECIFIED,
listenerKind: ListenerKind,
whyClosed: CloseReason,
controlTimer: INTEGER, -- PsHot: Retransmitter
probeCounter: CARDINAL,
pleaseDie: BOOLEAN,
fastHeader: FastHeader, -- RouterHot: EthernetInterruptRoutine
fastLocalQueue: Queue, -- PsHot: PktStreamFastFromUser
fastRoute: Host,
wait: PupType];


Allocation: TYPE=POINTER TO AllocationRecord;
AllocationRecord: TYPE=RECORD
[maximumBytesPerPup,numberOfPupsAhead,numberOfBytesAhead:CARDINAL];

-- these things live here rather than in PS
-- because they are used by PsHot, PsCold and RouterHot too
ethernetDelayKludge: CARDINAL=100; -- else sender is faster than receiver
retransmitTime:CARDINAL=10;
rangeInit:CARDINAL=10000;--range is a terrible name
duplicateWindow:CARDINAL=10000;
retransmitionsBeforeAbort:INTEGER=100;
ctlRetransmitTime:INTEGER=4*retransmitTime+1;--must be odd!!!
maxAllocate:INTEGER=5;
byteAllocate:INTEGER=4000;
packetsPerAdata:CARDINAL=4;
minAllocationBeforeAck:INTEGER=100;



--ROUTER
maxNet: CARDINAL = 20;
socTabMax: CARDINAL = 20;

Nip: TYPE = [0..15];
RouteTable: TYPE = ARRAY LegalNets OF RouteTableEntry;
RouteTableEntry: TYPE = RECORD [hop, time: Nip, route: Host, ethernet: Network];
LegalNets: TYPE = [0..maxNet];
SocTab: TYPE = [0..socTabMax];


--NETWORK
Network: TYPE = POINTER TO NetworkObject;
NetworkObject: TYPE = RECORD[
actualDevice: EthernetDeviceBlockHandle,
net: Net,
host: Host,
outputQueue: Queue,
currentInBuffer, nextInBuffer, currentOutBuffer: Buffer,
nextBufferPointer: POINTER,
interruptBit: WORD,
hardProcessHandle: ProcessDefs.ProcessHandle,
etherIntLF: UNSPECIFIED]; -- LF of EthernetInterruptRoutine

EthernetPost: TYPE = MACHINE DEPENDENT RECORD[
microcodeStatus: EthernetMicrocodeStatus,
hardwareStatus: EthernetHardwareStatus];
EthernetMicrocodeStatus: TYPE = [0..255];
EthernetHardwareStatus: TYPE = [0..255];
EthernetNotPosted:EthernetPost=[0,0];
inputDone: EthernetMicrocodeStatus = 0;
outputDone: EthernetMicrocodeStatus = 1;
inputBufferOverflow: EthernetMicrocodeStatus = 2;
outputLoadOverflow: EthernetMicrocodeStatus = 3;
zeroLengthBuffer: EthernetMicrocodeStatus = 4;
hardwareReset: EthernetMicrocodeStatus = 5;
interfaceBroken: EthernetMicrocodeStatus = 6;

hardwareAOK: EthernetHardwareStatus = 377B;
-- from bit 200 [unused,unused,inputDataLate,Collision
-- ,CRCbad,InputIssued,OutputIssued,packetNoEndOnWord]


BLOCK: MACHINE CODE = INLINE [Mopcodes.zBLOCK];
StartIO: MACHINE CODE [StartIOParameter] = INLINE [Mopcodes.zSTARTIO];
StartIOParameter: TYPE = RECORD[WORD];
outputCommand: StartIOParameter = [1];
inputCommand: StartIOParameter = [2];
resetCommand: StartIOParameter = [3];
-- to give back local frame of interrupt routine
FREE: MACHINE CODE [POINTER] = INLINE [Mopcodes.zFREE];

EthernetDeviceBlockHandle: TYPE = POINTER TO EthernetDeviceBlock;
OneDevice: EthernetDeviceBlockHandle = LOOPHOLE[600B];
EthernetDeviceBlock: TYPE = MACHINE DEPENDENT RECORD[
EPLoc: EthernetPost, -- post location
EBLoc: WORD, -- bit location
EELoc: CARDINAL, -- eot location
ELLoc: WORD, -- load location
inputBuffer: WordBlockDescriptor, -- count,pointer
-- EICLoc: CARDINAL - input counter location
-- EIPLoc: EthernetPacketHandle - input pointer location
outputBuffer: WordBlockDescriptor, -- count,pointer
-- EOCLoc: CARDINAL - output counter location
-- EOPLoc: EthernetPacketHandle - output pointer location
ESLoc: Host]; -- serial number location

EthernetAddressWord: TYPE = RECORD[destination, source:Host];

EthernetPacketType: TYPE = CARDINAL;
pupEthernetPacket: EthernetPacketType=1000B;
-- echoMeEthernetPacket: EthernetPacketType=700B;
-- echoEthernetPacket: EthernetPacketType=701B;

-- DEBUGGING
-- "unused" corner of Ethernet Interface
DebugPointer:POINTER TO PupInterface=LOOPHOLE[613B];

END.