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

 @(#) $Id: ss7link.h,v 0.7.2.3 2000/10/09 02:40:44 brian Exp $

 -----------------------------------------------------------------------------

 Copyright (C) 1997, 1998, 1999, 2000  Brian Bidulock <bidulock@dallas.net>

 All Rights Reserved.

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 675 Mass
 Ave, Cambridge, MA 02139, USA.

 Last Modified $Date: 2000/10/09 02:40:44 $ by $Author: brian $

 -----------------------------------------------------------------------------

 $Log: ss7link.h,v $
 Revision 0.7.2.3  2000/10/09 02:40:44  brian
 Pre-release 1.

 Revision 0.7.2.2  2000/09/24 06:30:52  brian
 Committing changes.

 Revision 0.7.2.1  2000/09/07 12:49:16  brian
 Got ss7link interface support for drivers compiling.

 Revision 0.7  2000/09/07 11:17:16  brian
 Initial import of OpenSS7 stack.

 Revision 1.2  2000/09/07 10:51:51  brian
 Got these files going.

 Revision 1.1.1.1  2000/09/05 11:00:20  brian
 Initial import of new OpenSS7 stack for Linux.

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

#ifndef __LINUX_SS7LINK_H__
#define __LINUX_SS7LINK_H__

#ifdef __KERNEL__

struct ss7if_timer {
    int duration;                           /* the duration for the timer */
    struct tq_struct taskq;                 /* a task queue for this timer */
    struct ss7_iface *iface;                /* what interface invoked this timer? */
    struct timer_list kernel_timer;         /* kernel timer for this timer */
};


struct sni {
    signed char bib;
    signed char bsn;
    signed char fib;
    signed char fsn;
};

struct tx_sni {
    struct sni      N;   /* Normal           */
    struct sni      F;   /* First RTB        */
    struct sni      L;   /* Last  RTB        */
    struct sni      C;   /* RTB clear        */
    struct sni      X;   /* Expected         */
    struct sni      R;   /* Received         */
    unsigned char   sio; /* SIO for LSSU     */
    int             len; /* len for Tx       */
};

struct rx_sni {
    struct sni      X;   /* Expected        */
    struct sni      F;   /* F????           */
    struct sni      R;   /* Received        */
    struct sni      T;   /* Transmited      */
    unsigned char   sio; /* SIO for LSSU    */
    int             len; /* len for Rx      */
};

#ifndef __DRIVER_SS7IF_H__
struct ss7if_reg 
{
    void (*destructor)(struct device *dev);
    int (*open)(struct device *dev);
    int (*stop)(struct device *dev);
    int (*hard_start_xmit)(struct sk_buff *skb, struct device *dev);
    int (*do_ioctl)(struct device *dev, struct ifreq *ifr, int cmd);
};
#endif

struct ss7if_stats {
    struct {
        unsigned bytes;     /* number of bytes received */
        unsigned sus;       /* number of signal units received */
        unsigned discard;   /* number of signal units discarded */
        unsigned compress;  /* number of signal units compressed */

        unsigned sync;      /* number of flag detection transitions */
        unsigned idle;      /* number of mark idle transitions */
        unsigned abort;     /* number of breaks or aborts received */
        unsigned crc;       /* number of crc errors */
        unsigned frame;     /* number of frame errors */
        unsigned small;     /* number of frame too short errors */
        unsigned big;       /* number of frame too long errors */
        unsigned residue;   /* number of residue errors */
        unsigned overrun;   /* number of receive overruns */
        unsigned overflow;  /* number of receive overflows */
    } rx;

    struct {
        unsigned bytes;     /* number of bytes transmitted */
        unsigned sus;       /* number of signal units transmitted */
        unsigned retry;     /* number of signal units discarded */
        unsigned discard;   /* number of signal units discarded */
        unsigned repeat;    /* number of repeated sus */

        unsigned underruns; /* number of times transmitter underran */
        unsigned aborts;    /* number of tx aborts sent */
    } tx;

    /*  FIXME: put the SS7 statistics from Q.752 here.  */
    /*  FIXME: may of the above overlap with those below */

    struct net_device_stats dev_stats;
};

struct ss7_iface
{
    struct device *dev;     /* pointer to the device */
    struct ss7_link link;   /* link object in routing tables */
    /*
     *  `Real' device interface service routines.
     */
    struct ss7if_reg  calls; /* real device calls */
#define if_kill       calls.destructor
#define if_open       calls.open
#define if_stop       calls.stop
#define if_xmit       calls.hard_start_xmit
#define if_ioctl      calls.do_ioctl
    /*
     *  Other SS7 Link state machine variables and such...
     */
    struct ss7if_stats ifstats; /* SS7 statistics */

    /*
     *  Tx/Rx sequence numbers and indicator bits...
     */

    struct tx_sni tx;
    struct rx_sni rx;

#define LSSU_SIO    0x0
#define LSSU_SIN    0x1
#define LSSU_SIE    0x2
#define LSSU_SIOS   0x3
#define LSSU_SIPO   0x4
#define LSSU_SIB    0x5

#define SN_OUTSIDE(lower,middle,upper) \
    (  ( lower < upper ) \
       ? ( ( middle < lower ) || ( middle > upper ) ) \
       : ( ( middle < lower ) && ( middle > upper ) ) \
       )

    /*
     *  Tx/Rx Queues...
     */

    struct tq_struct tx_taskq;          /* Output bottom-half */
    struct tq_struct rx_taskq;          /* Input  bottom-half */

    struct sk_buff_head writ_q;         /* Output queue */
    struct sk_buff_head read_q;         /* Input  queue */

    volatile int Octets_Counted;        /* for taskq overlap */
    volatile int SUs_Repeated;          /* for taskq overlap */

    /*
     *  Tx/Rx buffers
     */
    int retrans_cycle;          /* a flag to indicate retransmission */

    struct sk_buff_head xmit_q; /* TB - Transmit Buffer */
    struct sk_buff_head rexm_q; /* RTB - Re-Transmit Buffer */

    struct sk_buff *comp_skb;    /* a compression buffer for reception */
    struct sk_buff *fisu_skb;    /* a fisu buffer for transmittion */
    struct sk_buff *lssu_skb;    /* a lssu buffer for transmission */
    struct sk_buff * msu_skb;    /* a  msu buffer for transmission */
    struct sk_buff * tsu_skb;    /* an  su buffer for transmission */
    struct sk_buff * rsu_skb;    /* an  su buffer for reception    */

#define  TB_Q_MAX_SIZE   127
#define RTB_Q_MAX_SIZE   127
#define  RB_Q_MAX_SIZE   127

    /*
     *  L2 State Machine timers...  Straighten this out a bit so that these
     *  can be represented in proc and with sysctls.  Also so that we can
     *  access the structure with ioctls and display them with the proc
     *  file system.
     */

#define SS7LINK_TIMERS 7

    struct ss7if_timer timers[SS7LINK_TIMERS]; /* state machine timers */

    enum {
        TIMER_T1 = 0,
        TIMER_T2,
        TIMER_T3,
        TIMER_T4,
        TIMER_T5,
        TIMER_T6,
        TIMER_T7
    };
    
#define TIMER_T1V   ( 1300 * HZ/100 ) /* 13-30 */
#define TIMER_T2V   ( 1150 * HZ/100 ) /*  5-14 */
#define TIMER_T3V   ( 1150 * HZ/100 ) /*  5-14 */
#define TIMER_T4EV  (   60 * HZ/100 ) /* 0.54-0.66 */
#define TIMER_T4NV  (  230 * HZ/100 ) /* 2.07-2.53 */
#define TIMER_T5V   (   10 * HZ/100 ) /* .080 -.120 */
#define TIMER_T6V   (  450 * HZ/100 ) /* 1-6 */
#define TIMER_T7V   (  100 * HZ/100 ) /* .5-2 */

    /*
     *  L2 State Machine primary variables...
     */

    enum {
        DAEDT_STATE_Power_On = 0,
        DAEDT_STATE_Active,
        DAEDT_STATE_Sleeping
    };
    int DAEDT_state;        /* is the DAEDT running? */

    enum {
        DAEDR_STATE_Power_On = 0,
        DAEDR_STATE_Active
    };
    int DAEDR_state;        /* is the DAEDR running? */
    int Octet_Counting_Mode;/* in Octet counting mode */
    enum {
        SS7LINK_COMPRESSING_NONE = 0,
        SS7LINK_COMPRESSING_FISU,
        SS7LINK_COMPRESSING_LSSU,
        SS7LINK_COMPRESSING_LSS2
    };
    int Compressing_SU;     /* compressing an SU */

    enum {
        TXC_STATE_Power_On = 0,
        TXC_STATE_Active
    };
    int TXC_state;          /* is the TXC running? */
    int MSU_Inhibited;      /* are we inhibiting MSUs? */
    int LSSU_Available;     /* is an LSSU available for transmission? */
    int RTB_Full;           /* is the retransmission buffer full? */
    int Clear_RTB;          /* is the RTB to be cleared? */
    int SIB_Received;       /* was an SIB recevied? */
    int MSU_Incomplete;     /* are we still sending? */

    enum {
        RC_STATE_Power_On = 0,
        RC_STATE_Active
    };
    int RC_state;           /* is the RC running? */
    int rtr;                /* Retransmission indicator */
    int unb;                /* Unreasonable BSNs received */
    int unf;                /* Unreasonable FSNs received */
    int MSU_FISU_Accepted;
    int Abnormal_BSNR;
    int Abnormal_FIBR;
    int Congestion_Discard;
    int Congestion_Accept;
    int L2_Congestion_Detect;   /* detected by L2 */
    int L3_Congestion_Detect;   /* detected by L3 */

    int LSC_state;
    int Local_Processor_Outage;
    int Remote_Processor_Outage;
    int Emergency;

    enum {
        LSC_STATE_Power_On = 0,
        LSC_STATE_Out_of_Service,
        LSC_STATE_Initial_Alignment,
        LSC_STATE_Aligned_Ready,
        LSC_STATE_Aligned_Not_Ready,
        LSC_STATE_In_Service,
        LSC_STATE_Processor_Outage
    };

    int IAC_state;
    int t4;
    int Cp;
    int Further_Proving;

    enum {
        IAC_STATE_Idle = 0,
        IAC_STATE_Not_Aligned,
        IAC_STATE_Aligned,
        IAC_STATE_Proving
    };

    enum {
        AERM_STATE_Idle = 0,
        AERM_STATE_Active
    };
    int AERM_state;
    int Ca;
    int Ti;
    int Tin;
    int Tie;

#define AERM_TIE_VALUE 1
#define AERM_TIN_VALUE 4

    enum {
        SUERM_STATE_Idle = 0,
        SUERM_STATE_Active
    };
    int SUERM_state;
    int Cs;
    int Ns;
    int T;

    enum {
        CC_STATE_Normal = 0,
        CC_STATE_Congested
    };
    int CC_state;
    int cong_level;

    unsigned char l3_bsnt;

};

/* ss7if_sm.c */
int ss7if_output(struct sk_buff *skb, struct device *dev);

void ss7if_rx(struct sk_buff *skb);
void ss7if_oct(struct device *device);
void ss7if_los(struct device *device);
void ss7if_err(struct device *device);
void ss7if_rpt(struct device *device);


#define SS7_SKB_16_OCTETS (struct sk_buff *)0
#define SS7_SKB_LOST_SYNC (struct sk_buff *)1
#define SS7_SKB_BAD_FRAME (struct sk_buff *)2

/* ss7_dev.c */
int ss7if_l3_output(struct sk_buff *skb, struct device *dev);

extern int ss7sm_l3_primitive(struct ss7_iface *iface, unsigned char cmd);

#endif

/*
 *  Should make this accessible to proc as well.
 */

#define SIF_MAX 272
#define SS7_MTU SIF_MAX

/*
 *  Should have been defined by now!
 */

#ifndef ETH_P_SS7
#define ETH_P_SS7       0x0018
#define ETH_P_SS7LINK   0x0019
#endif

#ifndef ARPHRD_SS7
#define ARPHRD_SS7      600
#endif

#ifndef ss7_ptr
#define ss7_ptr dn_ptr
#endif

#endif  __LINUX_SS7LINK_H__

