-- File: BufferDefs.Mesa
-- Last Edit: HGM  January 7, 1981  4:40 PM
-- Last Edit: BLyon  January 13, 1981  2:53 PM
DIRECTORY
  PupTypes USING [
    maxDataWordsPerGatewayPup, Pair, PupAddress, PupErrorCode, PupHostID,
    PupNetID, PupSocketID, PupType],
  DriverTypes USING [DeviceType, Encapsulation, Seal],
  OISCPTypes USING [BufferBody, maxDataWordsPerSpp],
  System USING [Pulses];
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 = LONG POINTER TO QueueObject;
  QueueObject: TYPE = PRIVATE RECORD [
    length: PUBLIC CARDINAL, first, last: Buffer, seal: DriverTypes.Seal];
  -- Buffer Access
  BufferAccessHandle: TYPE = LONG POINTER TO 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,
    seal: PRIVATE DriverTypes.Seal,
    length: PRIVATE CARDINAL,
    network: PRIVATE Network,
    iocbChain: PRIVATE LONG POINTER,
    status: PRIVATE WORD,
    time: PRIVATE 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.