/*****************************************************************************
 * Copyright (c) 1988-95 Digi International Inc., All Rights Reserved
 * 
 * This  software  contains  proprietary  and  confidential   information   of
 * Digi International  Inc.   By  accepting  transfer  of this copy, Recipient
 * agrees to retain this software in  confidence,  to  prevent  disclosure  to
 * others,  and  to make no  use of this software other than that for which it
 * was delivered.  This is an unpublished copyright work  Digi   International
 * Inc.    Except   as   permitted   by  federal  law,  17 USC 117, copying is
 * strictly prohibited.
 * 
 * Digi  International  Inc.  CONFIDENTIAL  -   (Digi    International    Inc.
 * Confidential  when   combined   with   the   aggregated  modules  for  this
 * product) OBJECT CODE ONLY SOURCE MATERIALS
 * 
 * (C) COPYRIGHT Digi International Inc. 1995
 * 
 * All Rights Reserved
 * 
 * US   Government   Users   Restricted   Rights   -   Use,   duplication   or
 * disclosure  restricted by GSA ADP Schedule Contract with Digi International
 * Inc.
 * 
 *****************************************************************************/

/*
 * $Id: lapd.h,v 1.8 1999/05/24 20:05:49 erics Exp $
 *
 * Copyright (c) 1993-1994 Spider Systems Limited
 *
 * This Source Code is furnished under Licence, and may not be
 * copied or distributed without express written agreement.
 *
 * All rights reserved.  Made in Scotland.
 *
 * Authors: Duncan Walker
 *
 * lapd.h of lapd module
 *
 * SpiderISDN
 * Release 3.0.0 94/12/20
 * 
 * SpiderISDN Release 3 - Official Release.
 *
 */

/*
 * lapd.h
 *	Private LAPD declarations.	
 */

/*
 *  Local macros
 */
#define FAR
#define STATIC

#ifndef DL_MAXPRIM
#define DL_MAXPRIM	DL_GET_STATISTICS_ACK
#endif

/*
 *  Temporary define to allow quick avoidance of bufcall fix
 */
#define LAPD_BUFCALL_FIX 1

/*
 * strlog macros
 */
#define STRACE_MGMT	1	/* level for management activity tracing */
#define STRACE_SETUP	2	/* level for setup/disconnect tracing */
#define STRACE_RESET	3	/* level for reset activity tracing */
#define STRACE_ERROR	4	/* level for error activity tracing */
#define STRACE_BUSY	5	/* level for busy activity tracing */

#define SERROR_LEVEL	0	/* all errors get lowest level */

#ifdef HAVE_STRLOG
#define LAPD_INFO2(sapi,level,fmt,tei,snid)	\
		strlog(LAPD_STID, sapi, level, SL_TRACE, fmt, tei, snid, 0)
#define LAPD_INFO3(sapi,level,fmt,tei,snid,param)	\
		strlog(LAPD_STID, sapi, level, SL_TRACE, fmt, tei, snid, param)

#define LAPD_ERR(sapi,fmt) \
		strlog(LAPD_STID, sapi, SERROR_LEVEL, SL_ERROR, fmt, 0, 0, 0)
#define LAPD_ERR1(sapi,fmt,a) \
		strlog(LAPD_STID, sapi, SERROR_LEVEL, SL_ERROR, fmt, a, 0, 0)
#define LAPD_ERR2(sapi,fmt,a, b) \
		strlog(LAPD_STID, sapi, SERROR_LEVEL, SL_ERROR, fmt, a, b, 0)
#else
#define LAPD_INFO2(sapi,level,fmt,tei,snid)       { printf(fmt, tei, snid) ; printf("\n") ; }
#define LAPD_INFO3(sapi,level,fmt,tei,snid,param) { printf(fmt, tei, snid, param) ; printf("\n") ; }

#define LAPD_ERR(sapi,fmt)       { printf(fmt) ; printf("\n") ; }
#define LAPD_ERR1(sapi,fmt,a)    { printf(fmt, a) ; printf("\n") ; }
#define LAPD_ERR2(sapi,fmt,a, b) { printf(fmt, a, b) ; printf("\n") ; }
#endif

#define LAPD_MSIZE(m)	(m->b_wptr - m->b_rptr)
#define LAPD_DLSIZE	sizeof(union DL_primitives)
#define BPSIZE(bp)	((uint)(bp->b_datap->db_lim - bp->b_datap->db_base))

#define LAPD_NOERROR	0	 

#define LAPD_STOCKSZ	6	/* Length of the array of stock pointers */	
#define LAPD_UPMP	0	/* and indexes into the array - one for  */
#define LAPD_DNMP	1 	/* each "stock" message type required.	 */
#define LAPD_DIMP	2	/*					 */
#define LAPD_UDMP	3	/*					 */
#define LAPD_DSRV	4
#define LAPD_RXMP	5

#define LAPD_QFIRST	1
#define LAPD_QLAST	0

#define LAPD_NEED_ACK	0x0001	/* Bitmask values for cn_flags 		 */
#define LAPD_TXSTOPPED	0x0002
#define LAPD_WCLOSED	0x0004
#define LAPD_LOC_BUSY	0x0008
#define LAPD_REM_BUSY	0x0010
#define LAPD_NEED_FBIT	0x0020
#define LAPD_NEED_PBIT	0x0080
#define LAPD_NEED_IPBIT	0x0100
#define LAPD_CONN_UP	0x0200

#define LAPD_FRAMEOK	0	/* Values for "reason for 		 */
#define LAPD_FAULTY	1	/* re-establishment" field of lapdcn_t	 */
#define LAPD_DISCARD	2
#define LAPD_IGNORE	3
#define LAPD_RESTART	4
#define LAPD_USR_RESET	5
#define LAPD_USR_CONN	6

#define NORMAL		0	/* Values for the "condition" of each	*/
#define NRM_REJ_RECOVER	1	/* connection.				*/
#define NRM_OWN_REC_BSY	2
#define NRM_REJ_BUSY	3
#define PRB_NORMAL	4
#define PRB_REJ_RECOVER	5
#define PRB_OWN_REC_BSY	6
#define PRB_REJ_BUSY	7
#define ESTABLISH	8
#define RE_ESTABLISH	9
#define PENDING_RELEASE	10
#define AWAIT_WAN_EST   11
#define PENDING_DISCARD 12

#define WAN_NOEVENT	0	/* Reasons for the WAN being activated	*/
#define WAN_POWER	1	/* Helps us decide whether a TEI should */
#define WAN_NOPOWER	2	/* be requested or not			*/
#define WAN_REM_CON	4
#define WAN_LOC_CON	3


/*
   Timers - size of, and idexes into, the timer array in each 
   DOWN table entry.
*/
#define NTIMERS		3	/* Number of timers per DOWN entry	*/
#define LAPD_T200	0	/* Acknowledgement timer		*/
#define LAPD_T203	1	/* Idle timer				*/
#define LAPD_TXD	2
#define LAPD_T202	3	/* Tei - not actually part of the array	*/
				/* but used to inded timer recovery fns	*/

/*
   Direction of a frame.
*/
#define LAPD_TX		0
#define LAPD_RX		1


/*
   Local typedefs
*/
/* typedef	unsigned char FAR 	*bufp_t;   (removed GSP) */
#define	BUFP_T			bufp_t

typedef int dev_t ;


/*
   Hash table stuff
*/
#define NHASH		32
#define HASH(X,Y)	((int)(X + Y) & (NHASH - 1))


/*
    Tei control block structure.  One of these is maintained for
    each active TEI.  This can be per subnetwork or per B-channel.
*/
typedef struct lapdtei {
    thead_t         thead;
    timer_t         T202;	 /* Timer			*/
    uint16          tei_ri;	 /* TEI message reference no	*/
    uint8           tei_value;	 /* TEI of subnetwork		*/
    uint8           tei_state;	 /* TEI state of subnetwork	*/
    uint8           tei_tx;	 /* TEI message re-tx count	*/
    struct lapddn  *dnp;	 /* DOWN side of the connection	*/
    struct lapdtei *schedq_next; /* Next tei block scheduled    */
} lapdtei_t;

/*
   Connection control structure.  One of these is maintained for every
   active connection running through lapd.
*/
typedef struct lapdcn {
    struct lapdup  *upp;		/* UP side of the connection	*/
    struct lapddn  *dnp;		/* DOWN side of the connection	*/
    struct lapdcn  *schedq_next;	/* Next connection scheduled for
					   service by the state M/C	*/
    struct lapdcn  *next;		/* Next in UP's connection list	*/
    struct lapdcn  *hnext;		/* Next in hash chain		*/

    mblk_t         *ctlq;		/* List of downstream control 
					   messages over connection	*/
    mblk_t         *ctlq_tail;		/* Tail of control msg list	*/
    mblk_t         *datq;		/* List of I frames awaiting TX */
    mblk_t         *ackq;		/* List of I frames awaiting Ack*/
    mblk_t         *adq_tail;		/* Tail of dat/ack list		*/
    lapdtei_t     *teitab;		/* Ptr to TEI control block     */
    uint16	   dat_cnt;             /* Count of messages on list    */
    uint16	   dat_waiting;         /* Data from user blocked       */

    uint16	   tack;		/* Current ack timer time	*/
    thead_t        thead;		/* List of expired timers	*/
    timer_t        tmtab[NTIMERS];	/* List of timers maintained	*/

    uint16	   cn_flags;		/* Bitmask of a set of binary
					   flags for the connection	*/
    uint8	   connid;		/* Connection identifier	*/
    uint8	   sapi;		/* SAPI for connection		*/
    uint8          tx_retry;		/* Retransmission counter	*/
    uint8          state;		/* State of the connection	*/
    uint8          vr;			/* Receive state variable	*/
    uint8          vs;			/* Send state variable		*/
    uint8          va;			/* Ack state variable		*/
    uint8          txwindow;		/* Transmit window		*/
    uint8	   rx_notacked;		/* No of I's rcvd but not ackd	*/
    uint8	   reason;		/* ...for re-establishment	*/
    uint8	   origin;		/* ...for re-establishment	*/
    uint8	   condition;		/* Condition of the transmitter */
} lapdcn_t;


/*
   UP control structure.  One of these is defined for each upper stream
   linked over lapd.
*/
typedef struct lapdup {
    queue_t       *up_readq;		/* Ptr to the upper read QUEUE	*/
    struct lapddn *up_dnp;		/* Ptr to the DOWN table entry
					   over which connection runs	*/
    struct lapdup *up_dnext;		/* Ptr to next in list of UPs
					   linked over the same DOWN	*/
    struct lapdcn *up_cnp;		/* Control structure for this
					   connection			*/
    struct lapdup *up_unext;		/* Ptr to the next entry in list
					   of UPs with UI data to send	*/
    mblk_t        *up_udatq;		/* Queue of UI messages waiting	*/
    mblk_t	  *up_udatq_tail;	/* for servive by the DOWN	*/
    lapdtei_t     *up_teitab;           /* Ptr to TEI control block     */
    uint32	  up_dlservice;		/* DLPI service bound on up int	*/
    uint16	  up_udat_cnt;		/* Count of udata msgs on queue */
    uint16	  up_udat_waiting;	/* Udata from user blocked      */
    uint8         up_sapi;		/* SAPI for upper stream	*/
    uint8         up_dlstate;  		/* DLPI state of UP interface	*/
    uint8	  up_dlmaxcon;		/* Max connection indications	*/
    uint8	  up_dlnumcon;		/* Number outsatnding		*/
    uint8	  up_dlconnmgmt;	/* Connection Management stream	*/
#if LAPD_BUFCALL_FIX
    ulong	  up_bufcall_id;        /* For untimeout in close       */
#endif
} lapdup_t;


/*
   DOWN control structure.  One of these is defined for each lower stream
   linked under lapd.
*/
typedef struct lapddn {
    queue_t       *dn_downq;		/* Ptr to lower write QUEUE	*/
    struct lapdup *dn_uplist;		/* List of attached UPs 	*/
    struct lapdcn *dn_schedq;		/* List of scheduled connections*/
    struct lapdcn *dn_schedq_tail;	/* Tail of list			*/
    struct lapdup *dn_udatq;		/* List of UPs with UIs to send	*/
    struct lapdup *dn_udatqtail;	/* Tail of list			*/
    struct lapdtei *dn_teischedq;	/* List of scheduled tei blocks */
    struct lapdtei *dn_teischedq_tail;	/* Tail of list			*/
    struct lapdcn *dn_hashtab[NHASH];	/* Hash of cnp's over this dnp	*/

    lapdtei_t     *dn_teitab;           /* Ptr to TEI control block     */

    lapd_tune_t   dn_tunetab;		/* Tuning parameters for subnet	*/
    lapd_stats_t  dn_statstab;		/* Per subnetwork statistics	*/

    uint32        dn_index;		/* I_LINK index of lower stream	*/
    uint32        dn_snid;		/* SNID of subnetwork		*/

    uint16	  dn_flags;

    uint8         dn_WAN_state;		/* State of lower WAN link	*/
    uint8 	  dn_WAN_reason;	/* Reason for WAN activation	*/
    uint8	  dn_regstage;		/* What stage has WAN reg got to*/

    uint8	  dn_sapi_rx;		/* SAPI of received frame	*/

    uint8	  dn_trace_active;	/* Set if tracing this subnet	*/
    queue_t	  *dn_trace_queue;	/* Q to send tracing on		*/
    uint8	  dn_ll_class;		/* LL class of link: DCE/DTE	*/
    uint8         dn_connect_sent;      /* Have we sent a connect yet?  */
    uint8         dn_if_state;          /* ISDN_IF_UP/ISDN_IF_DOWN      */
} lapddn_t;


/*
   External functions
*/


/*
   Lower interface states
*/
#define WAN_IDLE	0
#define WAN_CONN	1
#define WAN_ESTB	2
#define WAN_DISC	3


/*
   Internal states, as defined in Annex D to recommendation Q.921.
   These are used in conjunction with the "condition" of the connection
   to determine actions and state changes.
*/
#define TEI_OFF			0
#define TEI_UNASSIGNED		1
#define ASS_AWAITING_TEI	2
#define EST_AWAITING_TEI	3
#define TEI_ASSIGNED		4
#define AWAITING_EST		5
#define AWAITING_RELEASE	6
#define MULTIPLE_FRAME		7
#define TIMER_RECOVERY		8


/*
   TEI assignment classes.
*/
#define LAPD_AUTO_TEI		0
#define LAPD_NON_AUTO_TEI	1

/*
   Supported SAPs
*/
#define MGMT_SAPI	63


/*
   Management Entity Types
*/
#define TEI_MANAGEMENT	0x0F

/*
    TEI Management Message Types
*/
#define TEI_ID_REQUEST	0x01
#define TEI_ID_ASSIGNED	0x02
#define TEI_ID_DENIED	0x03
#define TEI_ID_CHECK	0x04
#define TEI_ID_RESPONSE	0x05
#define TEI_ID_REMOVE	0x06
#define TEI_ID_VERIFY	0x07


/*
   FRAME FORMATS...
*/


/*
   Encoding of control field (octet #4) of individual frame types.

   For supervisory frames (RR, RNR, REJ) the first octet of the control
   field is encoded as below, the second octet being encoded based on
   connection sequence numbers and flags.

   For the remaining (unnumbered) commands and responses, the encoding
   shown below assumes that the P/F bit (bit 5) is 0.  This will be set
   (as necessary) on an individual frame basis.
*/
#define RR		0x01	/* Supervisory commands and responses	*/
#define RNR		0x05
#define REJ		0x09

#define SABME		0x6F	/* Unnumbered commands and responses	*/
#define DM		0x0F
#define UI		0x03
#define DISC		0x43
#define UA		0x63
#define FRMR		0x87


#define SFRM_PFBIT	1	/* Location of Poll/Final bit in 	*/
#define IFRM_PFBIT	1	/* S, I and U frames.			*/
#define UFRM_PFBIT	5

#define MIN_PDU_SZ	3	/* Min frame size without flags & FCS	*/
#define FRMR_PDU_SZ	MIN_PDU_SZ + 5	
#define MAX_PDU_SZ	4	/* Max frame size without flags & FCS	*/
#define TEI_MSG_SZ	5	/* TEI management message size		*/

#define NET_COMMAND	1	/* Frame type - command or response	*/
#define NET_RESPONSE	0	/* from the network side -> user side	*/
#define USER_COMMAND	0	/* Frame type - command or response	*/
#define USER_RESPONSE	1	/* from the user side -> network side	*/

#define RSP_F0		0x00	/* Encoding of the frame "type" passed	*/
#define RSP_F1		0x01	/* to the state machine - constructed	*/
#define CMD_P0		0x02	/* by ORing the CR and PF bits.		*/
#define CMD_P1		0x03


/*
   State of the WAN registration process.
*/
#define REGNONE		0	/* No registration started		*/
#define REGTOWAN	1	/* Registration sent to WAN		*/
#define REGFROMWAN	2	/* Succesful reg reply from WAN		*/
#define REGDONEOK	3	/* Registratino complete		*/
#define REGFAILED	4	/* Registration failed			*/


/*
   TEI Assignment Source Point
*/
#define ASP_NETWORK	0
#define ASP_USER	1


/*
   Reasons for disconnecting a subnetwork
*/
#define LAPD_OUT_SERVICE	1    /* TEI or wire removed */
#define LAPD_UNLINK		2    /* Subnetwork unlinked */


#ifndef TRUE
#define TRUE	1
#define FALSE	0
#endif

