RCS_ID agnet_h_id[]="$Id: agnet.h,v 3.1 93/10/07 19:24:17 ppessi Exp $";
/*
 * agnet.h --- agnet.device C definitions
 *
 * Author: ppessi <Pekka.Pessi@hut.fi>
 *
 * Copyright (c) 1993 OHT-AmiTCP/IP Group,
 *                    Helsinki University of Technology, Finland.
 *                    All rights reserved.
 *
 * Created      : Thu Jan 21 17:36:36 1993 ppessi
 * Last modified: Thu Oct  7 18:53:59 1993 ppessi
 *
 * $Log:	agnet.h,v $
 * Revision 3.1  93/10/07  19:24:17  ppessi
 * Release 2.1 version
 * 
 * Revision 2.1  93/05/14  16:48:01  ppessi
 * Release version
 * 
 */

#include <exec/types.h>
#include <exec/devices.h>
#include <exec/ports.h>
#include <exec/semaphores.h>
#include <exec/memory.h>
#include <exec/execbase.h>

#include <devices/sana2.h>

#include "lrandom.h"

/* Minimum Stacksize and Priority of agnet.device Process */
#define AGNET_STACKSIZE 4000
#define AGNET_PRI       3	/* We are running an ARexx Port */
#define AGNET_DEV_PRI   5	/* for device node */

#define AD_MAXUNITS 16		/* Max # of Units allowed */

/* Maximum address size in bytes */
#define MAX_ADDR_BYTES 8

/* A non-standard wiretype */
#define S2WireType_LoopBack  0 

/* 
 *   Agnet Device Data Structure 
 */
struct AgnetDevice
{
  struct Library	 ad_Device;
#define ad_Dev_Flags     ad_Device.lib_Flags
#define ad_Dev_pad       ad_Device.lib_pad
#define ad_Dev_NegSize   ad_Device.lib_NegSize		/* number of bytes before library */
#define ad_Dev_PosSize   ad_Device.lib_PosSize		/* number of bytes after library */
#define ad_Dev_Version   ad_Device.lib_Version		/* major */
#define ad_Dev_Revision  ad_Device.lib_Revision		/* minor */
#define ad_Dev_IdString  ad_Device.lib_IdString		/* ASCII identification */
#define ad_Dev_Sum       ad_Device.lib_Sum		/* the checksum itself */
#define ad_Dev_OpenCnt   ad_Device.lib_OpenCnt		/* number of current opens */

  struct SignalSemaphore ad_Lock;
  UBYTE		         ad_Flags;
  UBYTE		         ad_Pad1;
  struct AgnetDevUnit   *ad_Units[AD_MAXUNITS];
  struct Task           *ad_Task;
  struct ExecBase	*ad_SysBase;
  struct Library	*ad_DOSBase;
  struct Library	*ad_IntuitionBase;
  struct timerequest     ad_Timer;
  struct MsgPort         ad_MsgPort;
};

/* Typedef's for the SANA-II callback functions. */

typedef BOOL (*SANA2_CFB)(APTR to, APTR from, LONG length);
typedef BOOL (*SANA2_CTB)(APTR to, APTR from, LONG length);

struct BufferManagement
{
    struct MinNode	bm_Node;
    SANA2_CFB		bm_CopyFromBuffer;
    SANA2_CTB		bm_CopyToBuffer;
};

struct SuperS2PTStats
{
  struct MinNode	      ss_Node;
  ULONG			      ss_PType;
  struct Sana2PacketTypeStats ss_Stats;
};

/* 
 * Structure for our internal delayed transfer
 */
struct DelayRequest {
  struct IORequest    tr_node;
  struct timeval      tr_time;
  struct AgnetDevUnit*dr_Unit;
  ULONG               dr_HardwareType;
  ULONG               dr_PacketType;
  UWORD	              dr_Cmd;
  LONG                dr_PPUnit;
  UBYTE               dr_SrcAddr[MAX_ADDR_BYTES];
  UBYTE               dr_DstAddr[MAX_ADDR_BYTES];
  UWORD               dr_DataLen; /* Length of Data */
  UWORD               dr_Len;	 /* Length of Data Field */
  UBYTE               dr_Data[0]; /* Actually at least MTU */
};

#define MAX_TXED 4

/* 
 * Unit Data Structure 
 */
struct AgnetDevUnit
{
    struct Unit		    adu_Unit;		/* Standard Unit Structure           */
#define adu_Unit_MsgPort    adu_Unit.unit_MsgPort  /* queue for unprocessed messages */
#define adu_Unit_flags      adu_Unit.unit_flags
#define adu_Unit_OpenCnt    adu_Unit.unit_OpenCnt          /* number of active opens */
    UBYTE		    adu_UnitNum;	/* Unit number                       */
    UBYTE		    adu_State;		/* State bits                        */
    struct Device	   *adu_Device;		/* Pointer to our device node        */
    UBYTE		    adu_Addr[MAX_ADDR_BYTES];      /* Our "hardware" address */
    UWORD		    adu_AddrFieldSize;	/* address size in bits              */
    LONG		    adu_PPUnit;		/* Destination of p-to-p connection  */
    ULONG		    adu_MaxTU;		/* Maximum Transfer Unit             */
    ULONG		    adu_HardwareType;
    ULONG		    adu_BPS;		/* line rate (bits/second)           */
    ULONG		    adu_MinTU;		/* Minumum Transfer Unit             */
    ULONG		    adu_Delay;		/* Delay for outgoing packets in ms  */
    ULONG		    adu_Deviation;	/* Deviation in delay in ms          */
    ULONG		    adu_Errors;		/* Packet bit-error probabilty       */
    ULONG		    adu_Loss;		/* Packet loss probabilty            */
    struct SignalSemaphore  adu_Lock;	        /* A Semaphore for all queues.       */
    struct DelayRequest    *adu_TxEd[MAX_TXED]; /* Transfer buffers                  */
    struct MinList          adu_FreeToTx;       /* Free Transfer buffer              */
    struct MinList	    adu_Rx;		/* Pending CMD_READ's                */
    struct MinList	    adu_RxOrph;		/* Pending CMD_READORPHAN's          */
    struct MinList	    adu_Tx;		/* Pending CMD_WRITE's               */
    struct MinList	    adu_Events;		/* Pending S2_ONEVENT's              */
    struct MinList	    adu_Track;		/* List of tracked packet types      */
    struct MinList	    adu_BuffMgmt;	/* List of Callback routines         */
    struct Sana2DeviceStats adu_Stats;		/* Global device statistics          */
};

/*
 * Parameters for bit errors and packet loss
 */
#define ERRORS_MAX 1000000000
#define LOSS_MAX   1000000

/*
 * State bits for adu_State
 */
#define AGUB_CONFIG 0
#define AGUB_ONLINE 1
#define AGUB_SETCONFIG 2

#define AGUF_CONFIG		(1<<AGUB_CONFIG)
#define AGUF_ONLINE		(1<<AGUB_ONLINE)
#define AGUF_SETCONFIG	        (1<<AGUB_SETCONFIG)

/*
 * Device Name
 */

#define AGNETDEVNAME "agnet.device"

#define ASM           __asm
#define REG(x)        register __ ## x

#define TAILP(x) (!(struct Node *)x->ln_Succ)
#define HEADP(x) (!(struct Node *)x->ln_Pred)

/*
 * Unit access control
 */
#define LockUnit(adu)   ObtainSemaphore(&adu->adu_Lock)
#define UnlockUnit(adu) ReleaseSemaphore(&adu->adu_Lock)

#ifndef NOINLINE
#define RemHead execRemHead
/* 
 * List init routine 
 */
static __inline VOID 
NewList(register struct List *list)
{
  list->lh_Head = (struct Node *)&list->lh_Tail;
  list->lh_Tail = NULL;
  list->lh_TailPred = (struct Node *)list;
}
/*
 * List handling routines
 */
static __inline struct Node *
RemHead(register struct List *list)
{
  register struct Node * head = list->lh_Head;
  
  if (TAILP(head)) return NULL;
  (list->lh_Head = head->ln_Succ)->ln_Pred = (struct Node *)list;
  return head;
}
#endif
