-- File: BufferDefs.Mesa
-- Last Edit: HGM  January 7, 1981  4:40 PM
-- Last Edit: BLyon  January 13, 1981  2:53 PM
-- Last Edit: Andrew Birrell  June 22, 1983 5:19 pm

DIRECTORY
  PupTypes USING [
    maxDataWordsPerGatewayPup, Pair, PupAddress, PupErrorCode, PupHostID,
    PupNetID, PupSocketID, PupType],
  DriverTypes USING [DeviceType, Encapsulation, Seal],
  OISCPTypes USING [BufferBody, maxDataWordsPerSpp];


BufferDefs: DEFINITIONS =
  BEGIN

  -- Opaque Data TYPEs gets value through EXPORTED TYPEs
  Network: TYPE [2];  -- defined by DriverDefs.Network

  -- Basic Data TYPEs
  Byte: TYPE = [0..377B];

  PupAddress: TYPE = PupTypes.PupAddress;
  PupHostID: TYPE = PupTypes.PupHostID;
  PupNetID: TYPE = PupTypes.PupNetID;
  PupSocketID: TYPE = PupTypes.PupSocketID;


  -- QUEUE
  Queue: TYPE = REF QueueObject;
  QueueObject: TYPE = PRIVATE RECORD [
    length: PUBLIC CARDINAL, first, last: Buffer, seal: DriverTypes.Seal];

  -- Buffer Access
  BufferAccessHandle: TYPE = REF BufferAccessObject;
  BufferAccessObject: TYPE = PRIVATE RECORD [
    receiveInUse, sendInUse: CARDINAL,
    receive, send, total, reserve: CARDINAL,
    active: BOOLEAN,
    madeForSystem: BOOLEAN,
    filler: [0..37777B),
    bufferAvailable: CONDITION,
    recovered: CARDINAL,
    firstBuffer: Buffer,
    wordsPerBuffer: CARDINAL,
    next: BufferAccessHandle,
    seal: DriverTypes.Seal ];

  systemAccessHandle: BufferAccessHandle; -- ReadOnly but two modules here use it

  Enqueue: PROCEDURE [Queue, Buffer];
  Dequeue: PROCEDURE [Queue] RETURNS [Buffer];
  ExtractFromQueue: PUBLIC PROCEDURE [Queue, Buffer] RETURNS [Buffer];
  QueueLength: PROCEDURE [q: Queue] RETURNS [CARDINAL] = INLINE
    BEGIN RETURN[q.length]; END;

  QueueEmpty: PROCEDURE [q: Queue] RETURNS [BOOLEAN] = INLINE
    BEGIN RETURN[q.length = 0]; END;

  QueueInitialize: PROCEDURE [Queue];
  QueueCleanup: PROCEDURE [Queue];


  PupBufferObject: TYPE = pup BufferObject;
  PupBuffer: TYPE = LONG POINTER TO PupBufferObject;
  OisBufferObject: TYPE = ois BufferObject;
  OisBuffer: TYPE = LONG POINTER TO OisBufferObject;
  --SppBufferObject: TYPE = spp ois BufferObject;
  SppBuffer: TYPE = LONG POINTER TO OisBufferObject;


  MakeBufferPool: PROCEDURE [
    total: CARDINAL, send: CARDINAL ← 0, receive: CARDINAL ← 0,
    reserve: CARDINAL ← 0, forSystemUse: BOOLEAN ← TRUE]
    RETURNS [BufferAccessHandle];
  FreeBufferPool: PROCEDURE [BufferAccessHandle];
  BuffersLeft: PROCEDURE [aH: BufferAccessHandle ← systemAccessHandle]
    RETURNS [CARDINAL];
  SendBuffersLeft: PROCEDURE [BufferAccessHandle] RETURNS [CARDINAL];
  ReceiveBuffersLeft: PROCEDURE [BufferAccessHandle] RETURNS [CARDINAL];
  EnumerateBuffersInPool: PROCEDURE [BufferAccessHandle, PROCEDURE [Buffer]];
  GetFreeBuffer: PROCEDURE [
    bufType: BufferType ← raw, aH: BufferAccessHandle ← systemAccessHandle,
    bufFunc: BufferFunction ← systemUse] RETURNS [Buffer];
  MaybeGetFreeBuffer: PROCEDURE [
    bufType: BufferType ← raw, aH: BufferAccessHandle ← systemAccessHandle,
    bufFunc: BufferFunction ← systemUse] RETURNS [Buffer];
  ReturnFreeBuffer: PROCEDURE [Buffer];
  AdjustBufferSize: PROCEDURE [bufferSize: CARDINAL];
  GetBufferSize: PROCEDURE RETURNS [bufferSize: CARDINAL];

  DataWordsPerRawBuffer: PROCEDURE RETURNS [CARDINAL];
  DataWordsPerPupBuffer: PROCEDURE RETURNS [CARDINAL];
  DataWordsPerOisBuffer: PROCEDURE RETURNS [CARDINAL];
  DataWordsPerSppBuffer: PROCEDURE RETURNS [CARDINAL];

  defaultSystemBufferPoolSize: CARDINAL = 0;
  defaultSystemBuffersToReserve: CARDINAL = 0;
  defaultDataWordsPerSystemBuffer: CARDINAL = MAX[
    PupTypes.maxDataWordsPerGatewayPup, OISCPTypes.maxDataWordsPerSpp];

  -- BUFFER
  BufferFunction: TYPE = {send, receive, systemUse};
  BufferType: TYPE = {raw, pup, ois, oisSpp, rejected, processed};

  Buffer: TYPE = LONG POINTER TO BufferObject;
  BufferObject: TYPE = MACHINE DEPENDENT RECORD [
    next: PRIVATE Buffer,
    queue: PRIVATE Queue,
    pool: PRIVATE BufferAccessHandle,
    currentOwner: PRIVATE BufferAccessHandle,
    requeueProcedure: PROCEDURE [Buffer],
    requeueData: UNSPECIFIED,
    requeueRef: REF ANY, -- BEWARE:  storing into here is not reference-counted
    seal: PRIVATE DriverTypes.Seal,
    length: PRIVATE CARDINAL,
    network: PRIVATE Network,
    iocbChain: PRIVATE LONG POINTER,
    status: PRIVATE WORD,
    time: PRIVATE LONG CARDINAL--System.Pulses--,
    tries: PRIVATE CARDINAL,
    allNets: PRIVATE BOOLEAN,
    bypassZeroNet: PRIVATE BOOLEAN,
    device: PRIVATE DriverTypes.DeviceType,
    type: BufferType,
    bufFunc: BufferFunction,
    spare: [0..37B],
    debug: PRIVATE UNSPECIFIED,
    encapsulation: PRIVATE DriverTypes.Encapsulation,

    bufferBody:
      SELECT OVERLAID BufferType FROM
	raw => [rawWords: ARRAY [0..0) OF WORD],

	pup => [
	  pupLength: CARDINAL, -- in bytes, includes header
	  pupTransportControl: Byte, -- 4 bits of hopcount, 4 spares
	  pupType: PupTypes.PupType,
	  pupID: PupTypes.Pair,
	  dest, source: PupAddress,
	  pupBody:
	    SELECT OVERLAID * FROM
	      pupWords => [pupWords: ARRAY [0..0) OF WORD],
	      pupBytes => [pupBytes: PACKED ARRAY [0..0) OF Byte],
	      pupChars => [pupChars: PACKED ARRAY [0..0) OF CHARACTER],
	      pupString => [pupString: StringBody],
	      rfc => [address: PupAddress],
	      ack => [
		maximumBytesPerPup: CARDINAL,
		numberOfPupsAhead: CARDINAL,
		numberOfBytesAhead: CARDINAL],
	      abort => [
		abortCode: WORD, abortText: PACKED ARRAY [0..0) OF CHARACTER],
	      error => [
		-- see [MAXC]<PUP>Error.ears
		errorHeader: ARRAY [0..9] OF WORD,
		errorCode: PupTypes.PupErrorCode,
		errorOptions: WORD,
		errorText: PACKED ARRAY [0..0) OF CHARACTER],
	      ENDCASE],
	-- software checksum (1 word) comes after all the data

	ois => [ois: OISCPTypes.BufferBody]
	ENDCASE];

  -- Magic numbers describing the buffer
  zz: PRIVATE POINTER TO BufferObject = NIL;
  wordsPerNonVarientBufferOverhead: CARDINAL =
    LOOPHOLE[@zz.bufferBody, CARDINAL] - LOOPHOLE[zz, CARDINAL];

  END.