#ifndef __MAGPLIP_H
#define __MAGPLIP_H
/*
** $VER: magplip.h 1.9 (03 Sep 1995)
**
** magplip.device - Parallel Line Internet Protocol
**
** Original code written by Oliver Wagner and Michael Balzer.
**
** This version has been completely reworked by Marius Gröger,
** introducing slight protocol changes. The new source is
** a lot better organized and maintainable.
**
** Additional changes and code cleanup by Jan Kratochvil and Martin Mares.
** The new source is significantly faster and yet better maintainable.
**
** (C) Copyright 1993-1994 Oliver Wagner & Michael Balzer
** (C) Copyright 1995 Jan Kratochvil & Martin Mares
** (C) Copyright 1995 Marius Gröger
**     All Rights Reserved
**
** $HISTORY:
**
** 03 Sep 1995 : 001.009 :  + removed PLIP(F|B)_SIDEA
**                          + hardware addressing fields in PLIPBase
** 30 Aug 1995 : 001.008 :  support for timer-timed timeout :-)
**                          some pecularities moved to compiler.h
** 13 Aug 1995 : 001.007 :  code cleanup
** 29 Jul 1995 : 001.006 :  support for arbitration delay
** 24 Jul 1995 : 001.005 :  only one delay value in config
**                          some volatile elements in GD
** 25 Apr 1995 : 001.004 :  #define's FAR
** 06 Mar 1995 : 001.003 :  added collision delays
** 04 Mar 1995 : 001.002 :  packet-type now ULONG
** 18 Feb 1995 : 001.001 :  some SAS/C wrappers, better data base handling
** 12 Feb 1995 : 001.000 :  reworked original
*/

   /* system header files */
#ifndef DEVICES_SANA2_H
#include <devices/sana2.h>
#endif
#ifndef EXEC_SEMAPHORES_H
#include <exec/semaphores.h>
#endif
#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif
#ifndef EXEC_INTERRUPTS_H
#include <exec/interrupts.h>
#endif
#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif
#ifndef DOS_DOS_H
#include <dos/dos.h>
#endif

#ifndef __COMPILER_H
#include "compiler.h"
#endif


/****************************************************************************/


   /* memory economy is *everything* :-) */
#define SERVERTASKNAME           pb->pb_DevNode.lib_Node.ln_Name

      /* default values */
#define PLIP_DEFMTU              1024
#define PLIP_DEFBPS              100000
#define PLIP_DEFRETRIES          32
#define PLIP_DEFTIMEOUT          (500*1000)
#define PLIP_DEFDELAY            0
#define PLIP_DELAYDIFF           2000
#define PLIP_DEFARBITRATIONDELAY 500

      /* maximum values */
#define PLIP_MAXMTU              8192
#define PLIP_MAXRETRIES          127   /* this is really the maximum, don't */
                                                      /* try higher values! */
#define PLIP_ADDRFIELDSIZE       1

/****************************************************************************/


#define PKTFRAMESIZE_1           4        /* the sync-field and packet-size */
#define PKTFRAMESIZE_2           6                   /* crc and packet type */

struct PLIPFrame {
   USHORT   pf_Sync;
   SHORT    pf_Size;
   USHORT   pf_CRC;
   ULONG    pf_Type;
   UBYTE    pf_Data[PLIP_MAXMTU];
};


#define SYNCBYTE_HEAD   0x42
#define SYNCBYTE_CRC    0x01
#define SYNCBYTE_NOCRC  0x02
#define SYNCWORD_CRC    ((SYNCBYTE_HEAD << 8) | SYNCBYTE_CRC)
#define SYNCWORD_NOCRC  ((SYNCBYTE_HEAD << 8) | SYNCBYTE_NOCRC)


/****************************************************************************/


struct TrackRec {
   struct MinNode              tr_Link;
   ULONG                       tr_PacketType;
   struct Sana2PacketTypeStats tr_Sana2PacketTypeStats;
};


/****************************************************************************/


typedef BOOL (* ASM BMFunc)(REG(a0) void *, REG(a1) void *, REG(d0) LONG);

struct BufferManagement
{
    struct MinNode   bm_Node;
    BMFunc           bm_CopyFromBuffer;
    BMFunc           bm_CopyToBuffer;
};


/****************************************************************************/


struct PLIPBase
{
   struct Library              pb_DevNode;        /* basic device structure */
   UBYTE                       pb_Unit;         /* unit of 1st OpenDevice() */
   UBYTE                       pb_pad1; /* make the following long alligned */
   BPTR                        pb_SegList;               /* pointer to code */
   struct Library          *   pb_MiscBase,          /* various libs & res. */
                           *   pb_CIAABase,
                           *   pb_UtilityBase,
                           *   pb_TimerBase,
                           *   pb_DOSBase,
                           *   pb_SysBase;
   struct Process          *   pb_Server;             /* main server proces */
   struct Task             *   pb_Task;         /* used for server shutdown */
   struct Interrupt            pb_Interrupt;          /* for AddICRVector() */
   ULONG                       pb_IntSig;        /* sent from int to server */
   ULONG                       pb_IntSigMask;                  /* for speed */
   ULONG                       pb_ServerStoppedSigMask;     /* for shutdown */
   struct MsgPort          *   pb_ServerPort,       /* for IOReq forwarding */
                           *   pb_TimeoutPort,      /* for timeout handling */
                           *   pb_CollPort;       /* for collision handling */
   struct timerequest          pb_TimeoutReq,       /* for timeout handling */
                               pb_CollReq;        /* for collision handling */
   struct Sana2DeviceStats     pb_DevStats;            /* SANA-2 wants this */
   volatile struct List        pb_ReadList,                  /* the readers */
                               pb_WriteList,                 /* the writers */
                               pb_EventList,              /* event tracking */
                               pb_ReadOrphanList,   /* for spurious packets */
                               pb_TrackList,                  /* track type */
                               pb_BufferManagement;          /* Copy-In/Out */
   struct SignalSemaphore      pb_EventListSem,     /* protection for lists */
                               pb_ReadListSem,
                               pb_WriteListSem,
                               pb_TrackListSem,
                               pb_ReadOrphanListSem,
                               pb_Lock;
   ULONG                       pb_Retries;                 /* config values */
   ULONG                       pb_ReportBPS;
   ULONG                       pb_MTU;
   ULONG                       pb_AllocFlags;
   ULONG                       pb_Timeout;
   LONG                        pb_CollisionDelay;
   LONG                        pb_ArbitrationDelay;
   volatile UBYTE              pb_TimeoutSet;/* if != 0, a timeout occurred */
   volatile UBYTE              pb_Flags;                       /* see below */
   APTR                        pb_OldExceptCode;
   APTR                        pb_OldExceptData;
   ULONG                       pb_OldExcept;
   UBYTE                       pb_HandshakeMask[2],   /* crossed for side-a */
                               pb_HandshakeBit[2];            /* and side-b */
   UBYTE                       pb_SrcAddr[PLIP_ADDRFIELDSIZE];
   UBYTE                       pb_DstAddr[PLIP_ADDRFIELDSIZE];
   volatile struct PLIPFrame   pb_SendFrame,
                               pb_ReceiveFrame;
};

   /*
   ** used as index for PLIPBase->pb_HandshakeMask[]/pb_HandshakeBit[]
   */
#define HS_LINE        0   /* as we use compatible plip wireing, our magic */
#define HS_REQUEST     1   /* is to cross the lines transparently by software */

#ifdef __SASC
     /*
     ** redirect all shared library bases to our device base.
     */
#  define SysBase      pb->pb_SysBase
#  define DOSBase      pb->pb_DOSBase
#  define TimeBase     pb->pb_TimeBase
#  define UtilityBase  pb->pb_UtilityBase
#  define MiscBase     pb->pb_MiscBase
#  define CIAABase     pb->pb_CIAABase
#  define CiaBase      pb->pb_CIAABase
#  define TimerBase    pb->pb_TimerBase
     /*
     ** This macro declares a local variable which temporary gets
     ** SysBase directly from AbsExecBase.
     */
#  define LOCALSYSBASE struct { void *pb_SysBase; } *pb = (void*)0x4
     /*
     ** Use this macro as argument for all functions which need to
     ** have access to your data base.
     */
#  define BASEPTR      struct PLIPBase *pb
#else
#  error Please define library bases for your compiler
#endif

   /*
   ** Values for PLIPBase->pb_Flags
   ** Note that the Flags field is intentionally only 8 bits wide so that
   ** the ASM parts my use the bit functions.
   */
#define PLIPB_EXCLUSIVE       1   /* current opener is exclusive */
#define PLIPB_NOTCONFIGURED   2   /* not configured */
#define PLIPB_OFFLINE         3   /* currently not online (sic!) */
#define PLIPB_SENDCRC         4   /* send with CRC sum */
#define PLIPB_RECEIVING       5   /* set by interrupt */
#define PLIPB_COLLISION       6   /* arbitration detected a collision */
#define PLIPB_SERVERSTOPPED   7   /* set by server while passing away */

#define PLIPF_EXCLUSIVE       (1<<PLIPB_EXCLUSIVE)
#define PLIPF_NOTCONFIGURED   (1<<PLIPB_NOTCONFIGURED)
#define PLIPF_OFFLINE         (1<<PLIPB_OFFLINE)
#define PLIPF_SENDCRC         (1<<PLIPB_SENDCRC)
#define PLIPF_RECEIVING       (1<<PLIPB_RECEIVING)
#define PLIPF_COLLISION       (1<<PLIPB_COLLISION)
#define PLIPF_SERVERSTOPPED   (1<<PLIPB_SERVERSTOPPED)


/****************************************************************************/


   /*
   ** sent to the server task after being CreateNewProc()ed
   */
struct ServerStartup
{
   struct Message    ss_Msg;
   struct PLIPBase  *ss_PLIPBase;
};


/****************************************************************************/


   /*
   ** configuration stuff
   */
#define CONFIGFILE "ENV:SANA2/magPLIP.config"

#define TEMPLATE "TIMEOUT/K/N,PRIORITY=PRI/K/N,MTU/K/N,BPS/K/N,RETRIES/K/N,SENDCRC/S,CD=COLLISIONDELAY/K/N,AD=ARBITRATIONDELAY/K/N"

struct PLIPConfig
{
      ULONG *timeout;
      LONG  *priority;
      LONG  *mtu;
      LONG  *bps;
      LONG  *retries;
      ULONG  sendcrc;
      LONG  *collisiondelay;
      LONG  *arbitrationdelay;
};

#endif
