/*
 *
 * 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: Harry Bryson
 *
 * il3_defs.h of il3 module
 *
 * SpiderISDN
 * Release 3.0.0 94/12/20
 * 
 * SpiderISDN Release 3 - Official Release.
 *
 */
 
/*
 *  il3defs.h
 *
 *	- IL3 typedefs
 *	- associated #defines
 */

#define FAR

#define	VOID	void
#define	BCOPY(a, b, c)	bcopy((int8 *)(a), (int8 *)(b), c)
#define	BZERO(a, b)		bzero((int8 *)(a), (int)(b))
/*
 * Use strict checking of addresses (phone numbers)?
 */
#define	ISDIGIT(a)	TRUE	/* No */

/*
 * STATIC define allow switching on and off of 'static' behaviour
 *  for function declarations
 */
#ifndef STATIC
#define STATIC
#endif

#define Q_PTR 	queue_t *
#define	IL3_TX  0
#define	IL3_RX  1

/*
 * Defines for basic or primary rate interfaces.
 */
#define	IL3_BASIC_RATE		0
#define	IL3_PRIMARY_RATE	1

#define NIL3_BASIC_CHANS        2
#define NIL3_PRIMARY_CHANS      30

/*
 * Following defines need to be changed for a PRI.
 */
#define	MAX_B_PER_D_CHANS	2	/* BRI */
#define	MAX_D_CHANS		1	/* 1 BRI per board. */

/*
 * Now for structures and associated #defines.
 */

typedef uint32 state_t;	/* Call control state (bitmask) */
typedef struct d_chans d_chans_t ;
typedef struct chan_id_tab chan_id_tab_t ;

#define	IL3_TIMER_MASK	1	/* 1-bit mask. */
#ifdef IL3_TREF_HOLD
#define	IL3_MAX_TIMERS	12
#else
#define	IL3_MAX_TIMERS	11
#endif

#define	IL3_T301	(uint8)0
#define	IL3_T303	(uint8)1
#define	IL3_T304	(uint8)2
#define	IL3_T305	(uint8)3
#define	IL3_T308	(uint8)4
#define	IL3_T309	(uint8)5
#define	IL3_T310	(uint8)6
#define	IL3_T313	(uint8)7
#ifndef NO_DELAYED_CACTIVE
#define	IL3_TCAC	(uint8)8
#else
#define	IL3_T314	(uint8)8
#endif
#define	IL3_T316	(uint8)9
#define	IL3_T322	(uint8)10
#ifdef IL3_TREF_HOLD
#define IL3_TREF	(uint8)11
#endif

#define	IL3_TIMER_EXPIRE_1	1

#define	il3_timer_mask(t_index) (IL3_TIMER_MASK << t_index)

#define	il3_timer_expired(il3cb, t_index) \
  (((il3cb)->pctimers.expire_flag >> (t_index)) & IL3_TIMER_MASK)

typedef struct il3pctimer
{
	uint32 expire_flag;		/* Indicates if a timer has expired once */
	thead_t thead;			/* timer head. */
	timer_t timer[IL3_MAX_TIMERS];/* timer timer_t structures */
} il3pctimer_t;

typedef uint32 il3_info_t;

/*
 * Global call reference
 * il3cb.
 */

#define SENT_NONE	0x00
#define SENT_XN_CACTIVE	0x01
#define SENT_XN_CONNACK	0x02

#define IL3CB_TO_IL3GCB(x) \
                (&((d_chans_t*)(x->dlower_wq->q_ptr))->il3gcb)

typedef struct il3_bearer_cap
{
	uint8	it_cap;		/* Information transfer capability */
	uint8	it_rate;	/* Information transfer rate */
	uint8	transfer_mode;	/* Not exactly the same as call-type 
      					(bit-shifted) */
        uint8   rt_adapt;       /* Rate Adaption Standard     */
        uint8   rt_val;         /* Rate Adaption value        */
        uint8   rt_intr;        /* Intermediate rate, flow control 
                                    Octet 5b.                 */
        uint8   data_attrib;    /* data attributes Octet 5c   */
} il3_bearer_cap_t;

typedef struct {                /* Low Layer Compatibility */
        uint8   llc_len ;
        uint8   llc_elem[23] ;
} llc_t ;

typedef struct {                /* High-Layer Compatibility */
        uint8   hlc_len ;
        uint8   hlc_elem[11] ;
}hlc_t ;

 /*
  * This define contains what fields needs to be in (the same place in)
  * both il3cb and il3gcb
  */
#define	IL3CBHEAD	\
	struct il3cglob	*il3cglob;	/* "Global" data                    */ \
	cref_t		cref;		/* Call reference 		    */ \
	d_chans_t      *d_chans ;	/* D-Channel pointer                */ \
	uint32		call_type;	/* Circuit, temp, global or packet. */ \
	state_t		state;		/* Call reference state. 	    */ \
	state_t		cs;		/* State received in status message.*/ \
	uint32		codeset;	/* Current/temp codeset. 	    */ \
	uint8		last_cause_in;	/* Last cause value from network.   */ \
	uint8		last_cause_out;	/* Last cause value from IL3.       */ \
					/* (Includes internal)              */ \
	uint8		local_failure;	/* IL3 reason for failing call.     */ \
	il3_info_t	cc_info;	/* Information field.               */ \
	b_channel_no_t	b_channel;	/* B-channel number   		    */ \
	uint8		selected;	/* Indicates that the user specified*/ \
                                        /* a channel. 			    */ \
	Q_PTR		dlower_wq;	/* Where to send D-chan messages.   */ \
	uint32		charge_units;	/* Charging information. 	    */ \
	uint8		cut_through;	/* Indicates that a CHANNEL_ID IE   */ \
					/* has been received in this message*/ \
	uint8		force_null_cref;/* Used to force the next message   */ \
					/* to use a NULL call reference.    */


#define	EXCLUSIVE_B	0x80	/* Exclusive B-channel */

/*
 * Logically the following define seems sensible but don't
 * ask me to prove it mathematically... not yet anyway.
 */
#define	MULTIPLEBITS(bitmask)	((bitmask) & ((bitmask)-1))

/*
 * Hopefully do not use this mess too often.
 */
#define	IL3CB2DCHANS(il3cb)	((d_chans_t *)(il3cb)->dlower_wq->q_ptr)
#define	IL3DQ2CLNSRQ(d_q)	(((d_chans_t *)(d_q)->q_ptr)->shared->clns_rq)
#define	IL3UPQ2CLNSRQ(il3upq)	(IL3DQ2CLNSRQ((il3upq)->il3cb.dlower_wq))
#define	IL3CB2UPQ(il3cb)	((il3upq_t *)((uint8 *)il3cb-(int)&(((il3upq_t *)0)->il3cb)))

typedef struct il3gcb
{
	IL3CBHEAD
} il3gcb_t;

typedef struct il3cb
{
	IL3CBHEAD
	xisdnf_t	 calling;      /* Calling number (includes subadds) */
	xisdnf_t	 called;       /* Called number (includes subaddr)  */
	il3pctimer_t	 pctimers;     /* Per-call timer information 	    */
	Q_PTR 		 upper_rq;     /* Where to send user message 	    */
        il3_bearer_cap_t bear_serv;    /* user defined bearer services Meer */
  	llc_t            llc ;         /* Low-Layer Compatibility */
        hlc_t            hlc ;         /* High-Layer Compatibility */
        usr_call_no_t    called_ie;    /* Called Party Number Meer */
        usr_call_no_t    calling_ie;   /* Calling Party Number Meer */
} il3cb_t, *il3b_p;

#ifdef ANSIC
typedef state_t (*il3_timer_expire_t)(il3cb_t *);
#else
typedef state_t (*il3_timer_expire_t)();
#endif

typedef struct il3gtimer
{
	uint8	*timer_no;	/* Timer number as specified in refs, 	    */
				/* eg "T301". 				    */
	uint32	timeout;	/* Timeout value in seconds. 		    */
	il3_timer_expire_t 
		timer_expire[2];/* Timeout expiry routines 		    */
} il3gtimer_t;

#define is_PRI()		(il3cglob.rate == IL3_PRIMARY_RATE)
#define	is_1TR6(il3cglob)	((il3cglob)->nationality & NAT_GERMAN)
#define	is_VN3(il3cglob)	((il3cglob)->nationality & NAT_FRENCH)
#define	is_VN2(il3cglob)	FALSE	/* Use VN3 for just now. */
#define	is_UK(il3cglob)		((il3cglob)->nationality & NAT_BRITISH)
#define	is_NI_1(il3cglob)	((il3cglob)->nationality & NAT_NATIONAL_ISDN_1)
#define	is_NI_2(il3cglob)	((il3cglob)->nationality & NAT_NATIONAL_ISDN_2)
#define	is_NI_1or2(il3cglob)	( is_NI_1(il3cglob) || is_NI_2(il3cglob) )
#define is_41449(il3cglob)      ((il3cglob)->nationality & NAT_ATT_41449)
#define is_DMS100(il3cglob)     ((il3cglob)->nationality & NAT_DMS100)
#define is_NTT(il3cglob)        ((il3cglob)->nationality & NAT_NTT)
#define is_AUSTEL(il3cglob)     ((il3cglob)->nationality & NAT_AUSTEL)
#define is_ETSI(il3cglob)     ((il3cglob)->nationality & NAT_ETSI)

#define	NATIONALITY(x)		(x(il3cb->il3cglob))
#define	CHECK_NATIONALITY(y,x)	(x(y->il3cglob))

typedef struct il3cglob
{
	state_t state;		/* Global call reference state. Not used yet*/ 
	uint8	rate;		/* IL3_BASIC_RATE or IL3_PRIMARY_RATE 	    */
	uint32	nationality;	/* Hopefully can be runtime dependent	    */
	uint8	transfer_rate;	
	uint16	options;	/* Allow different options to be used. User?*/
	uint32	options_extra;	/* More user options - trying to avoid prev */
				/* variable as it is over used already.	    */
	xisdnf_t listenaddr;	/* Our address 				    */
	uint8	type_address;	/* Type of address.			    */
	uint8	num_plan;	/* Numbering plan. 			    */
	uint8	type_subaddress;/* Type of subaddress. 			    */
	uint8	info_tc_in;	/* Information transfer capability (in)	    */
	uint8	info_tc_out;	/* Information transfer capability (out)    */
	uint8	nostock;	/* Bufcall outstanding? 		    */
	uint16	datalink_delay_ack; 
				/* Delay after link coming down, to 	    */
			    	/* receive acknowledgements.		    */
	il3gtimer_t *gtimers;	/* Global timer information 		    */
	mblk_t	*g_arg;		/* Argument buffer. 			    */ 
				/* Initialised by init function.	    */
	mblk_t	*g_enc;		/* Encoder buffer. Initialised by 	    */
				/* init function. 			    */
	mblk_t	*u_msg;		/* Pointer to (pre-alloced) message 	    */
				/* to send to user. 			    */
	mblk_t	*d_msg;		/* Pointer to (pre-alloced) LAP-D message.  */
	mblk_t	*w_msg;		/* Pointer to (pre-alloced) WAN message.    */
	Q_PTR	*bfq;		/* Bufcall queue. 			    */
	uint32	bfqsize;	/* Number of Q's waiting to bufcall	    */

} il3cglob_t;

/*
 * Used as indexes into arrays - do not change these values.
 */
#define	IL3_UPPER_STREAM_UNUSED	0	/* Open but not in use. */
#define	IL3_UPPER_STREAM_ACTIVE	1	/* Outgoing call type of upper stream */
#define	IL3_UPPER_STREAM_LISTEN	2	/* Listening upper stream */

/*
 * If BUFCALLED set, outstanding bufcall in progress.
 * If BORD_QING set, message(s) queued.
 */
#define	BUFCALLED	1
#define	BORD_QING	2

/*
 * Header structure for all upper stream structures.
 */
typedef struct il3upq_head
{
	uint8	type;		/* Type of il3upq			*/
	uint8	flags;		/* Bufcall, flow-control, etc bits.	*/
	uint8	pad[2];		/* Padding to 4 byte boundary 		*/
	int	minor_dev;	/* Minor device number of this entry 	*/
				/* - indexes into il3_dev[] array	*/
	Q_PTR	this_rq;	/* Read queue associated with this 	*/
				/* structure.				*/
	mblk_t	*mp;		/* Message block pointer. 		*/

} il3upq_head_t, il3upq_unused_t;

/*
 * Used by upper streams to make calls. Upper q->q_ptr attached to this.
 */
typedef struct il3upq
{
	il3upq_head_t head;	/* Common il3upq structure head. */
	struct	il3cb il3cb;	/* Call control block associated with stream. */
	Q_PTR	blower_wq;	/* If actively involved with B-channel */
} il3upq_t;

typedef struct il3upq_listen
{
	il3upq_head_t head; /* Common il3upq structure head. */
	xisdnf_t address;	/* Called address (+subaddress) */
} il3upq_listen_t;

/*
 *        Registration             Connecting         Disconnecting
 * B: NULL->UNSNID->UNREG->UNUSED, ->CONNECTING->CON, ->DISCONNECTING->UNUSED
 *
 *    Registration          Connecting         Disconnecting
 * D: NULL->UN_REG->UNUSED, ->CON,             ->DISCONNECTING->UNUSED
 */

#define	IL3_LOWER_STATE_NULL			0
#define	IL3_LOWER_STATE_UNSNID			1
#define	IL3_LOWER_STATE_UNREG			2
#define	IL3_LOWER_STATE_UNUSED			3
			/* Wanting to use a B-channel (& got ok from NT) */
#define	IL3_LOWER_STATE_WANT			4	
#define	IL3_LOWER_STATE_CONNECTING		5
#define	IL3_LOWER_STATE_CON			6
#define	IL3_LOWER_STATE_DISCONNECTING		7
			/* Prefer to use a B-channel */
#define	IL3_LOWER_STATE_PREFER			8	
			/* User Wants to use a B-channel */ 
#define	IL3_LOWER_STATE_USERWANT		9	

typedef struct bdhead
{
	uint8	type;		/* B/D-channel 			*/
	uint8	flags;		/* Control block bits up	*/
	uint8	state;		/* Channel state		*/
	uint8	pad;		/* Padding			*/
	Q_PTR   this_wq;	/* Write queue associated with	*/
				/* this structure. 		*/
	int	muxid;		/* Used for streams linkage.	*/
} bdhead_t;

#define	IL3_CHAN_TYPE_NULL	0	/* Not defined. */

/*
 * 1 per B-channel available. Lower q->q_ptr attached to this.
 */
typedef struct b_chans
{
	bdhead_t *bdhead;	/* Header structure. Must be first!         */
	Q_PTR	upper_rq;	/* upper queue if active - NULL => inactive */
	il3upq_t *il3upq;	/* Pointer to upper stream structure.       */
        chan_id_tab_t *chan_id_ptr; /* Pointer to chan_id_tab_array     */
} b_chans_t;

/*
 * Struct to hold chan-id number
 */
struct chan_id_tab
{
	b_chans_t *b_chans_ptr ;
        uint32    chan_state;
        uint32    chan_id;
        uint32    chan_map;
};
/*
 * Will be use for H0 Channel for loops
 * Try keeping up with macro   Meer
 */
#define CHAN_ARR_SIZE 32

#define	IL3_NO_INFO	1
#define	IL3_INFO_PEND	2
#define	IL3_INFO_GOT	3

typedef struct il3_dlpi
{
	uint8 state;
	uint8 info_state;
	uint8 pad[2];
	uint32 snid;
	uint32 sapi;
	uint32 mode;
	uint32 correlation;
} il3_dlpi_t;

#include "il3_shared.h"

/*
 * 1 per D-channel available. Lower q->q_ptr attached to this.
 * b_chans needs to be a pointer
 * to keep d_chans structure size constant.
 * It actually points to a dynamically created array of B-channel
 * structures.
 */
struct d_chans
{
	bdhead_t	* bdhead;	/* Header structure. Must be first!  */
	il3_dlpi_t	dlpi_cons;	/* CONS DLPI information.	     */
	il3gcb_t	il3gcb;		/* Global call reference for this    */
					/* interface 			     */
	thead_t		dlthead;	/* Delayed datalink drop timer head. */
	timer_t		dltimer;	/* Delayed datalink drop timer.	     */

	struct d_chan_shared
			* shared;	/* Structure shared between D-chans. */

	int		spid_index;	/* The SPID index given to this	     */
					/* D-channel.			     */
	int		spid_allocated;	/* Is the spid_index a valid one?    */
	int		dn_index;	/* The DN index given to this	     */
					/* D-channel.			     */
	int		dn_allocated;	/* Is the dn a valid one?            */

	int		sub_index;	/* The sub-address index given to    */
					/* this D-channel.		     */
	int		sub_allocated;	/* Is the sub-address a valid one?   */
} ;

/*
 * Horrible define to translate from il3cb pointer -> dlpi pointer
 */
#define	IL3DLPI(il3cb)	(&(((d_chans_t *)(il3cb)->dlower_wq->q_ptr)->dlpi_cons))

/*
 * IE processing
 */
typedef uint8 ie_id_coding_t;
typedef il3_info_t ie_info_t;
#ifdef ANSIC
typedef uint8 (*ie_encoder_t)(il3cb_t *il3cb, mblk_t *mp_enc);
typedef uint8 (*ie_decoder_t)(il3cb_t *il3cb, mblk_t **mp, uint8 ielen);
#else
typedef uint8 (*ie_encoder_t)();
typedef uint8 (*ie_decoder_t)();
#endif

#define	ie_enc_NULL ((ie_encoder_t)NULL)
#define	ie_dec_NULL ((ie_decoder_t)NULL)
#ifdef ATNT
#define ie_enc_41449_change_status ((ie_encoder_t)NULL)
#define ie_enc_41449_channel_id ((ie_encoder_t)NULL)
#endif

typedef struct ie {
	ie_encoder_t ie_encoder;	/* Information element encoder */
	ie_decoder_t ie_decoder;	/* Information element decoder */
	ie_id_coding_t	ie_id_coding;	/* Identifier coding */
#define	IEDI2IEIC(iedi)	(ied[iedi].ie_id_coding)
	ie_info_t ie_info;      	/* Nationality, applicability, etc */
	uint8 iedarg_min;		/* Min length of ied TLV. */
	uint8 iedarg_max;		/* Max length of ied TLV. */
} ie_t;

/*
 * State Machine
 */
#ifdef ANSIC
typedef state_t (*il3_func_sm_t)(il3cb_t *il3cb);
#else
typedef state_t (*il3_func_sm_t)();
#endif

/*
 * Message processing
 */
typedef uint8 mt_val_t;
typedef il3_func_sm_t mt_sm_t;
typedef il3_info_t mt_info_t;
#define	mt_ie_null	((mt_ie_t *)NULL)
#define	mt_sm_null	((mt_sm_t)NULL)

typedef uint8	mt_ie_t;

typedef struct mt {
	mt_ie_t *mt_ie;		/* Pointer to IE chain */
	mt_sm_t mt_sm;		/* State machine function upon receiving */
	mt_val_t mt_val;	/* Message type */
	mt_info_t mt_info;	/* Nationality, applicability, etc */
	state_t mt_valids;	/* Valid states for receiving this message. */
	uint8 pad;			/* Pad byte(s) */
} mt_t;

extern mt_t mtd[];
extern mt_t mtd_41449[];
/*
 * User interface.
 */
#ifdef ANSIC
typedef uint8 (*ue_enc_t)(il3cb_t *il3cb);
#else
typedef uint8 (*ue_enc_t)();
#endif
/*
 * Needs queue pointer for CONNECT and CONNACK
 */
#ifdef ANSIC
typedef uint8 (*ue_dec_t)(queue_t *q, mblk_t *mp, il3cb_t **il3cb);
#else
typedef uint8 (*ue_dec_t)();
#endif
/*
 * Returns new state or 0 if failed preprocessing.
 */
typedef il3_func_sm_t ue_sm_t;

#define ue_enc_null ((ue_enc_t)NULL)
#define ue_dec_null ((ue_dec_t)NULL)
#define	u_null_ue_sm ((ue_sm_t)NULL)

typedef struct ue {
	ue_enc_t ue_enc;/* Encode user message. */
	ue_dec_t ue_dec;/* Decode/parse user message. */
	ue_sm_t ue_sm;	/* State machine function to call. */
	state_t u_valids;	/* Valid states for receiving this message. */
} ue_t;

typedef struct tlv
{
	uint8 type;
	uint8 length;
	uint8 val[1];	/* Valid? MUST BE UINT8 */
	
} tlv_t, *tlv_p;

/*
 * These values are also returned by the state-machine functions
 * which usually return the new state. They are not allowed to clash
 * with the state-values and hence the reason they are multiple bit
 * patterns (states are single bits) - they also must fit into a byte!
 */
#define	IL3_OK				0
#define	IL3_FAIL			0x03
#define	IL3_DELAY			0x07
#define	IL3_E_BUG			0x0F

#define	IL3_ENCODE_SUCCESS	IL3_OK
#define	IL3_ENCODE_FAIL		IL3_FAIL
#define	IL3_ENCODE_DELAY	IL3_DELAY
#define	IL3_ENCODE_E_BUG	IL3_E_BUG

/*
 * IE TLV typedefs
 */
typedef struct il3_ie_cause
{
	uint8	location;
	uint8	cause;
	uint8	diagnostic[1];

} il3_ie_cause_t;

struct il3_ie_endpoint
{
	uint8	usid;

	/*
	 * Terminal identifier
	 */
	uint8	tid;

	uint8	tid_present;
};

struct il3_ie_info_req
{
	uint8	type;
};

#define SELECT_B_CHANNEL    1
#define SELECT_H0_CHANNEL   2
#define SELECT_H11_CHANNEL  3
#define SELECT_H12_CHANNEL  4
#define SELECT_MULT_CHANNEL 5
#define SELECT_ANY_CHANNEL  6
#define SELECT_NO_CHANNEL   7

#define H0_CHANNEL_1_MAPNUM   0x0000003F
#define H0_CHANNEL_2_MAPNUM   0x00000FC0
#define H0_CHANNEL_3_MAPNUM   0x0003F000
#define H0_CHANNEL_4_MAPNUM   0x00FC0000
#define H0_CHANNEL_5_MAPNUM   0x3F000000

typedef struct il3_ie_channel_id
{
        uint8   chan_type ;/* Bit 8==1 for exclusive. 0 for any channel */
        uint8   chan_num ;
        uint8   mult_num ;
        uint32   map_num ;
} il3_ie_channel_id_t;

typedef struct il3_ie_channel_id_41449
{
        uint8   chan_type ;          /* Bit 0x40 for exclusive. */
	uint8	chan_num ;
	uint8 	mult_num ;
	uint32	map_num ;
} il3_ie_channel_id_41449_t;

#define	END_OF_CHANNEL_IDS	((uint8) -1)	/* Do not clash with B-channel number */

typedef struct il3_progress_ind
{
	uint8 location;
	uint8 description;
} il3_progress_ind_t;

typedef struct il3_fac_charge_info
{
	uint8 facility_type;
	uint8 charging_units[4];
} il3_fac_charge_info_t;

typedef struct il3_ie_change_status_41449
{
        uint8 status ;

} il3_ie_change_status_t ;


/*
 * Message block sizes
 */
#define	G_ARG_SIZE	128
#define	G_ENC_SIZE	G_ARG_SIZE	/* Best same size as argument buffer */
#define	U_MSG_SIZE	sizeof(union ISDN_primitives)
#define	D_MSG_SIZE	sizeof(union DL_primitives)
#define	W_MSG_SIZE	sizeof(union WAN_primitives)

/*
 *	IL3 STREAMS logging defines.
 */

/*
 * strlog macros
 */
#define STRACE_GCR	1	/* level for global call ref tracing */
#define STRACE_CALL	2	/* level for call setup tracing */
#define STRACE_RELEASE	3	/* level for release tracing */
#define STRACE_ALL	4	/* level for tracing all state changes */
#define STRACE_QUEUE	5	/* level for tracing general info */

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

#define IL3_INFO(snid,level,fmt) \
		strlog(IL3_STID, snid, level, SL_TRACE, fmt);

#define IL3_INFO1(snid,level,fmt,a) \
		strlog(IL3_STID, snid, level, SL_TRACE, fmt, a);

#define IL3_INFO2(snid,level,fmt,a,b) \
		strlog(IL3_STID, snid, level, SL_TRACE, fmt, a, b);

#define IL3_INFO3(snid,level,fmt,a,b,c) \
		strlog(IL3_STID, snid, level, SL_TRACE, fmt, a, b, c);

#ifdef IL3_NO_ERRLOG
#define IL3_QUEUE_STRLOG(snid,fmt) 
#define IL3_QUEUE_STRLOG1(snid,fmt,a) 
#define IL3_QUEUE_STRLOG2(snid,fmt,a,b) 
#define IL3_QUEUE_STRLOG3(snid,fmt,a,b,c) 
#define IL3_ERR(snid,fmt) 
#define IL3_ERR1(snid,fmt,a) 
#define IL3_ERR2(snid,fmt,a, b) 
#define IL3_ERR3(snid,fmt,a, b, c) 
#else
#define IL3_QUEUE_STRLOG(snid,fmt) \
		queue_strlog(IL3_STID,snid,STRACE_QUEUE,SL_TRACE,fmt)

#define IL3_QUEUE_STRLOG1(snid,fmt,a) \
		queue_strlog(IL3_STID,snid,STRACE_QUEUE,SL_TRACE,fmt,a)

#define IL3_QUEUE_STRLOG2(snid,fmt,a,b) \
		queue_strlog(IL3_STID,snid,STRACE_QUEUE,SL_TRACE,fmt,a,b)

#define IL3_QUEUE_STRLOG3(snid,fmt,a,b,c) \
		queue_strlog(IL3_STID,snid,STRACE_QUEUE,SL_TRACE,fmt,a,b,c)

#define IL3_ERR(snid,fmt) \
		strlog(IL3_STID, snid, SERROR_LEVEL, SL_ERROR, fmt);

#define IL3_ERR1(snid,fmt,a) \
		strlog(IL3_STID, snid, SERROR_LEVEL, SL_ERROR, fmt, a);

#define IL3_ERR2(snid,fmt,a, b) \
		strlog(IL3_STID, snid, SERROR_LEVEL, SL_ERROR, fmt, a, b);

#define IL3_ERR3(snid,fmt,a, b, c) \
		strlog(IL3_STID, snid, SERROR_LEVEL, SL_ERROR, fmt, a, b, c);
#endif

/*
 * Unfortunately we use SNID as strlog SID which is 16 bits (not 32).
 * Shouldn't be a problem until we need more than 2^16 subnetworks.
 */
#define SNID_TO_STRLOG(snid)	( (uint16)(snid) )

/*
 * The following structure is filled in when a decoding routine decides
 * that it wants to use a strlog. This is required to prevent a message
 * being printed twice - this happens in the following case:
 *
 * 1. decode message - print STRLOG
 * 2. message delayed
 * 3. re-decode message - secode STRLOG #!#
 *
 * Instead, the strlog shall be done after all elements in a message
 * have been processed.
 */

void	queue_strlog();
void	empty_log_queue();

#define MAX_STRLOG_LEN	120

struct log
{
	int     id;
	uint32  snid;
	int     level;
	int     error;
	char    * message[MAX_STRLOG_LEN];
	int     param1;
	int     param2;
        int     param3;

};

#define MAX_STRLOGS	4

#ifdef STRLOG_MAIN
struct log		log_queue[MAX_STRLOGS];
#endif

/*
 * This de-activates the B-channel
 */
#define IL3_DISCONNECT_B_CHANNEL(il3cb) \
{ \
	uint8 err; \
	if ((err = il3_disconnect_b_channel(il3cb)) != IL3_OK) \
		return err; \
}

/*
 * This activates the B-channel
 */
#define	IL3_CONNECT_B_CHANNEL(il3cb) \
{ \
	uint8 err; \
	if ((err = il3_connect_b_channel(il3cb)) != IL3_OK) \
		return err; \
}
