-- 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,
    GotRfc,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.