/* ih.h */

/* Copyright (c) 2000  James M. Westall, Dept of Computer Science,
 *                     Clemson University, Clemson SC 29634 USA
 *
 * 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.
 *
 * To obtain a copy of the GNU General Public License write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * This software is derived from software developed by the Interphase
 * corporation and released by them in September 2000. The software
 * released by Interphase carried the following copyright notice:
 *
 *
 *                          Copyright (C) 1993
 *                Interphase Corporation, Dallas, TX 75234
 *                          All Rights Reserved
 *
 * This code contains confidential information and  trade  secrets  of
 * Interphase Corporation which shall not be reproduced or transferred
 * to other programs or disclosed to others or used for  manufacturing
 * or any other purpose without prior written permission of Interphase
 * Corporation.  Use of copyright notice is precautionary and does not
 * imply publication or intent thereof.
 */

/*H
 * FILE: ia.h
 *
 * DESCRIPTION:
 *   This file contains all the general driver data structures
 *   and defines.
 *
 * FUNCTIONS:
 * EXPORTED:
 *
 * STATIC:
 *
 * GLOBAL DATA:
 *
 */

#ifndef _IA_H
#define _IA_H

#define  Vol   volatile

typedef char            i8;
typedef char            I8;
typedef char            S8;
typedef unsigned char   U8;
typedef short           i16;
typedef short           I16;
typedef short           S16;
typedef unsigned short  U16;
typedef int             i32;
typedef int             I32;
typedef int             S32;
typedef unsigned int    U32;

/*
 * General defines
 */
#define IA_SUCCESS       0
#define IA_FAIL         -1

#ifndef PCI_VENDOR_ID_IPHASE
#define PCI_VENDOR_ID_IPHASE 0x107e
#endif
#ifndef PCI_DEVICE_ID_IPHASE_5575
#define PCI_DEVICE_ID_IPHASE_5575 0x0008
#endif
#ifndef PCI_DEVICE_ID_IPHASE_5515
#define PCI_DEVICE_ID_IPHASE_5515 0x0001
#endif

#define  IADEV_MASK  0x80
#define  ROUND_UP(x, to)   (((u_int)x+(to-1)) & ~(to-1))

/*
 * Addgen ring numbers
 */
#define  NUM_LIST    2     /* Flipper lists        */
#define  TX_LIST     0     /* Packet trasnmit list */
#define  RX_LIST     1     /* Packet receive list  */

/*
 * MTU and queue watermarks
 */
#define  IA_MTU      (9*1024)

#define IAUHIWAT     (RX_BUF_SIZE  * 5)
#define IAULOWAT     (RX_BUF_SIZE  * 1)

/*
 * VC Status byte
 */

#define VC_ACTIVE   0x01
#define VC_ABR      0x02
#define VC_UBR      0x04

#define NUM_VCCS     128

/*
 * Linux ATM vcc
 */
typedef struct
{
   struct sk_buff_head tx_backlog;    /* -> backlog queue       */
   int                 tx_pending;    /* # of elements in queue */
   int                 tx_active;     /* # of elements active   */
   int                 tx_txed;       /* Packets sent           */
   int                 rx_rcvd;       /* Packets received       */
} ia_lnx_vcc_t;


/*
 * State of addgen ring
 */
typedef struct
{
   DLE   *list_start;   /* Start of DMA list       */
   DLE   *list_end;     /* End of DMA list         */
   DLE   *list_read;    /* List read pointer       */
   DLE   *list_write;   /* List write pointer      */
} ia_dle_list_t;

typedef int  Tout_t;    /* Timeout element         */

/*
 * Tx buffer control structure
 */
typedef struct
{
   caddr_t     *mp;             /* System data buffer header  */
   caddr_t     addr;            /* Host Buffer address        */
   caddr_t     baddr;           /* Controller buffer address  */
   off_t       offset;          /* To make ddi_dma_sync easy  */
   f_buf_desc  *desc;           /* Buffer descriptor pointer  */
   int         cnt;             /* Number of DVMA mappings    */
   caddr_t     daddr[MAX_SGE];  /* Dma segment phys addr      */
   size_t      dlen[MAX_SGE];   /* Dma segment length         */
   struct sk_buff *skb;         /* Pointer to socket buffer */
   struct atm_vcc *vcc;         /* Pointer to vcc           */
} ia_tx_buf_t;

/*
 * Rx buffer control structure
 */
typedef struct ia_rx_buf
{
   struct ia_rx_buf *next;       /* Next element in the link list */
   caddr_t      *mp;             /* Driver data buffer            */
   caddr_t     addr;             /* Buffer address                */
   off_t       offset;           /* To make ddi_dma_sync easy     */
   int         index;            /* Index of the array            */
   void        *softc;           /* State structure               */
   size_t      len;              /* CS PDU length                 */
   r_buf_desc  *desc;            /* Descriptor pointer            */
   caddr_t     daddr[MAX_SGE];   /* Dma segment phys addr         */
   size_t      dlen[MAX_SGE];    /* Dma segment length            */
   struct sk_buff *skb;          /* Pointer to socket buffer */
} ia_rx_buf_t;

#define NUM_PVCS 64

typedef struct
{
#if LINUX_VERSION_CODE >= 0x20303
   wait_queue_head_t input_wait;
#else
   struct wait_queue *input_wait;
#endif
   ia_rx_buf_t       *rdybufhead;
   ia_rx_buf_t       *rdybuftail;
}  ia_pvc_desc_t;

/*
 * Board registers
 */
typedef struct
{
   ffred_t     *ffred;          /* F FRED (Pre-Atlantic)           */
   rfred_t     *rfred;          /* R FRED (Pre-Atlantic)           */
   U32         *ctrl;           /* Control Register (pre-Atlantic) */
   ia_suni_t   *suni;           /* SUNI                            */
   suni_pm7345_t *suni_pm7345;  /* DS3  PHY                        */
   ia_flip_t   *flipper;        /* Flipper                         */
   fl_config_t *config;         /* Configuration Registers         */
   U32         *tx_tc;          /* Tx transection count            */
   U32         *rx_tc;          /* Tx transection count            */
   caddr_t     ffred_mem;       /* F FRED control memory           */
   caddr_t     rfred_mem;       /* R FRED control memory           */
} ia_brd_regs_t;
/*
 * Board registers (Physical address relative to the board)
 * These are the needed physical address of the device on
 * the controller.
 */
typedef struct
{
   u_int    buf_mem;    /* Buffer memory           */
   u_int    ffred_mem;  /* F FRED control memory   */
   u_int    rfred_mem;  /* R FRED control memory   */
} ia_brd_regs_ph_t;

/*
 * Board registers (Local copy)
 * This structure keeps a copy of the rfred and ffred registers.
 * This helps in reducing the the number of slave accesses to the
 * board. Only registers that do not change after initialization
 * or registers owned by the host are maintained.
 */
typedef struct {
   /* Pre-Atlantic */
   ffred_t     ffred;    /* F FRED         */
   rfred_t     rfred;    /* R FRED         */
} ia_brd_regs_ll_t;


/*
 * FFRED map
 */
typedef struct ia_ffred_map
{
        u_int           f_num_vc;       /* Size of Tx VC table          */
        u_int           f_abr_tbl;      /* Size of ABR table            */
        u_int           f_abr_wq;       /* Size of ABR wait queue       */
        u_int           f_ubr_tbl;      /* Size of UBR table            */
        u_int           f_ubr_wq;       /* Size of UBR wait queue       */
        u_int           f_tcq_start;    /* Transmit complete queue start*/
        u_int           f_prq_start;    /* Packet ready queue start     */
        u_int           f_abr_tbl_start;/* ABR table start              */
        u_int           f_ubr_tbl_start;/* UBR table start              */
        u_int           f_abr_wq_start; /* ABR Work Queue               */
        u_int           f_ubr_wq_start; /* UBR Work Queue               */
        u_int           f_evc_start;    /* Extended VC table start      */
        u_int           f_vc_start;     /* VC table start               */
} ia_ffred_map_t;


/*
 * RFRED map
 */
typedef struct ia_rfred_map
{
        u_int           r_num_vc;       /* Size of Rx VC table          */
        u_int           r_reassm_size;  /* Entries in reassembly table  */
        u_int           r_lfq_start;    /* Large buffer free queue start*/
        u_int           r_pcq_start;    /* Packet complete queue start  */
        u_int           r_excp_start;   /* Exception queue start        */
        u_int           r_reassm_start; /* Reassembly table start       */
        u_int           r_vc_start;     /* VC table start               */
        u_int           r_abr_vc_start; /* ABR VC table start           */
} ia_rfred_map_t;


/*
 *  This structure manages a dma-able buffer pool.
 */
typedef struct
{
   caddr_t     taddr;            /* Unaligned true address     */
   caddr_t     addr;             /* Aligned address            */
   size_t      len;              /* Requested Length of memory */
   size_t      real_len;         /* Length of aligned memory   */
   int         alloc_handle_done;
   int         mem_alloc_done;
} ia_dma_t;


/*
 * Rate Q control elements
 * Only used for PVC driver
 * (Pre-Atlantic only)
 */
typedef struct
{
   u_long      lbolt;      /* Last time this RQ was used         */
   u_int       rq_info;    /* Bits 0-7 RQ_PRELOAD, 8-9 PRESCALER */
} ia_rq_cntl_t;

#define  NUM_RATE_Q  4     /* Number of settable rate Qs       */

/* for ABR software workaround */

typedef struct testTable
{
   u_short lastTime;
   u_short fract;
} testTable_t;

/* Driver statistics */

typedef struct
{
   int interrupts;       /* Number of interrupts   */
   int rfred_intr;       /* Rfred ints             */
   int tfred_intr;       /* Tfred ints             */
   int addgen_intr;      /* Recvd packet DLE int   */
   int suni_intr;        /* SUNI ints              */
   int rx_buf_on_dma_q;  /* Rx buf queued for DMA  */
   int tcq_empty;
   int tx_packets;
   int tx_bytes;
   int tx_drops;
   int tx_waits;
   int rx_packets;
   int rx_bytes;
   int tx_skb_consumed;
   int tx_skb_returned;
} ia_driver_stat_t;

/* Ffred statistics */

typedef struct
{
   int cc_flush;
   int ce_delink;

}  ia_ffred_stat_t;

/* Rfred statistics */

typedef struct
{
  int drop_rxpkt;         /* Dropped packet counter */
  int drop_cell;          /* Dropped cell counter   */
  int drop_cbr;           /* Dropped cbr cells      */
  int rx_cell;            /* Received cells         */
  int large_freeqmt;      /* LFQ Empty count        */
  int small_freeqmt;      /* SFQ Empty count        */
  int excp_full;          /* ExceptionQ empty count */
  int cf;
  int cce;
  int cse;
  int sqe;
  int eof;
  int pte;
  int cer;
  int ofl;
  int pep;
  int cng;
  int baddesc;
  int rx_no_host_buf;
  int oos_com;
  int oos_eom;
  int nsld;
  int nld;
  int last_inv_vc;
  int invalid_vc;
  int last_inv_vp;
  int invalid_vp;
} ia_rfred_stat_t;

#ifdef __SNMP__
#define LI_ADDRL                (6)
#define LLC_ADDRL               (sizeof (u_short) + LI_ADDRL)
#define NUM_INTERFACE   3

#define ATM_INTERFACE   0
#define SONETLINE_INTERFACE     1
#define SONETPATH_INTERFACE 2

#endif __SNMP__
/*
 * The entire state of each device.
 */
typedef struct ia_softc
{
   struct atm_dev   *atmdev;             /* Link to linux atm stack    */
   int              instance;            /* controller number          */
   int              atlantic;            /* ATLANTIC ?                 */
   uchar_t          mac_addr[6];         /* Our mac address            */
   struct pci_dev   *ia_dev;             /* PCI control structure      */
   struct timeval   *tod;                /* -> xtime                   */
   struct timeval   tv;                  /* -> xtime                   */
   int              irq;                 /* Interrupt number           */
   ulong_t          real_base;
   caddr_t          pci_base_v;          /* Our physical PCI base vir  */
   int              pci_map_size;
   ia_dle_list_t    list[NUM_LIST];      /* Flipper DMA list           */
   ia_dma_t         tx_list_dma;         /* Tx DMA control             */
   ia_dma_t         rx_list_dma;         /* Rx DMA control             */
   ia_brd_regs_t    brd_regs;            /* Board registers            */
   ia_brd_regs_ph_t brd_regs_ph;         /* Board regs, Phy addr       */
   ia_brd_regs_ll_t brd_regs_ll;         /* Board regs, local copy     */
   ia_dma_t         tx_dma;              /* TX DMA control             */
   ia_tx_buf_t      tx_buf[NUM_TX_BUFS]; /* Tx buffer control          */
   ia_dma_t         rx_dma;              /* Rx DMA control             */
   ia_rx_buf_t      rx_buf[NUM_RX_BUFS]; /* Rx buffer control          */
   ia_rx_buf_t      *rx_buf_free;        /* Rx free buffer list        */
   ia_rx_buf_t      *rx_buf_freetail;    /* Rx free buffer list tail   */
   ia_rx_buf_t      *rx_buf_dmahead;     /* Rx buf list on addgen      */
   ia_rx_buf_t      *rx_buf_dmatail;     /* Rx buf list on addgen      */
   u_int            rx_state;            /* Receive side state         */
   spinlock_t       ia_misc_mutex;       /* Driver misc. mutex         */
   spinlock_t       xramlock;            /* Driver Control mutex       */
   spinlock_t       xmitlock;            /* Driver Tx mutex            */
   spinlock_t       recvlock;            /* Driver Rx Mutex            */
   int              attach_flags;        /* See below                  */
   ia_ffred_stat_t  ffred_stat;          /* F-Fred/FE stats            */
   ia_rfred_stat_t  rfred_stat;          /* R-Fred stats               */
   ia_driver_stat_t driver_stat;         /* Driver stats               */
/* ia_suni_stat_t   suni_stat;              SUNI stats                 */
   ia_ffred_map_t   ffred_map;           /* FFRED map                  */
   ia_rfred_map_t   rfred_map;           /* RFRED map                  */
   Tout_t           led_timeout;         /* LED timeout                */
   Tout_t           suni_timeout;        /* SUNI timeout               */
   int              suni_carrier;        /* SUNI carrier               */
   int              phy_type;            /* PHY type                   */
   u_int            line_crs;            /* LINE Cell Rate             */
   ia_rq_cntl_t     ia_rq_cntl[4];       /* Rate q info                */
   freg_t           last_tcq_wr_ptr;     /* Used to free SKBs          */
   int              tx_delay;            /* Delay when no Tx resources */
   int              tx_retries;          /* Number of retries          */
   int              tx_low_water;
   int              tx_high_water;

   int              num_tx_desc;
   int              num_rx_desc;
   int              num_tx_bufs;
   int              ram_size;
   int              rx_packet_ram;

   u_char           vc_status[F_NUM_VC]; /* each VC status on this card*/

   u_int            sum_mcr;
   u_int            n_abr;

#ifdef __SNMP__
   u_int            ia_rbytes[NUM_INTERFACE];
   u_int            ia_obytes[NUM_INTERFACE];
   u_int            ia_norcvbuf[NUM_INTERFACE];
   u_int            ia_noxmtbuf[NUM_INTERFACE];
   u_int            ia_ierrors[NUM_INTERFACE];
   u_int            ia_oerrors[NUM_INTERFACE];
   u_int            ia_ipackets[NUM_INTERFACE];
   u_int            ia_opackets[NUM_INTERFACE];
   u_int            ia_brdcstrcv[NUM_INTERFACE];
   u_int            ia_brdcstxmt[NUM_INTERFACE];
   u_int            ia_multircv[NUM_INTERFACE];
   u_int            ia_multixmt[NUM_INTERFACE];
#endif __SNMP__
   u_int            tx_backlog;
   u_int            last_tx_vcc;       /* Used for fair queueing */
   ia_lnx_vcc_t     vcctab[NUM_VCCS];
   ia_pvc_desc_t    pvctab[NUM_PVCS];
   int              logtx;
   int              logrx;
   struct timeval   lastrx;
} ia_softc_t;

typedef struct vcstatus {
   u_char active:  1;
   u_char abr:     1;
   u_char ubr:     1;
   u_char cnt:     5;
} vcstatus_t;

/*
 * Rx state flags
 */
#define  RX_BLOCKED     0x01  /* Receive blocked canput failed      */
#define  RX_NO_BUFS     0x02  /* No free host receive buffers       */

/*
 * Attach flags
 */
#define  INTERRUPT_ADDED      0x01
#define  MUTEX_ADDED    0x02
#define  PCI_CONFIG_ADDED  0x04


/*
 * Stream private data structure
 */

#ifdef __SNMP__

struct ia_addr{
   u_char medaddr[LI_ADDRL];
};
struct iadladdr{
   struct ia_addr dl_phys;
   u_short dl_sap;
};
#endif __SNMP__
/*
 * Front End Control Register Bits
 * (Pre-Atlantic only).
 */
#define  FECR_LED 0x04     /* 0 = LED On              */
#define  FECR_RESET  0x02     /* 0 = Reset active           */
#define  FECR_MLT 0x01     /* 1 = MLT              */

#define  swaps(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))

#define MIN(x, y)       ((x) < (y)) ? (x) : (y)

/*
** ABR Parameter limits and etc..
*/
#define LINE_CELL_RATE_155 352768
/* 155 Mb/sec = ((155.52*1024*1024)/(8))*(1/53)*(26/27) = 370365 cells/sec
            ( 26/27 = Sonet overhead)
            But, per Les Zshohar the value that fits
            the Float respresentation is 352768
   155 Mb/sec = 352768 cells/sec
*/
#define LINE_CELL_RATE_25     59200
#define LINE_CELL_RATE_T3_ADM           104269
#define LINE_CELL_RATE_T3_PLCP          96000
#define LINE_CELL_RATE_E3_832_ADM       80000
#define LINE_CELL_RATE_E3_751_ADM       79698
#define LINE_CELL_RATE_E3_751_PLCP      72000
#define MAX_TBE         16777215        /* ((2**24) -1) */
#define MIN_TBE         1
#define MAX_FRTT        16777215        /* ((2**24) -1) */
#define MIN_FRTT        1
#define MAX_NRM         7               /* Encoded NRM  */
#define MAX_TRM         7               /* Encoded TRM  */
#define MAX_ADTF        1023            /* Encoded ADTF */
#define MIN_ADTF        1               /* Encoded ADTF */
#define MAX_CDF         7               /* Encoded CDF  */
#define MAX_RIF         15              /* Encoded RIF  */
#define MAX_RDF         15              /* Encoded RDF  */

#define MRM             0x3

#define swap32(x)   (((x & 0xff) << 24) | ((x & 0xff00) << 8) | \
                   ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24))
#define swap(x)   (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
#if 1
#define  swaps_be(x)  swap(x)
#define  swaps_le(x)  (x)
#define  swapl_be(x)  swap32(x)
#define  swapl_le(x)  (x)
#define  swap32_be(x) swap32(x)
#define  swap32_le(x)   (x)
#else /* SPARC */
#define  swaps_be(x) (x)
#define  swaps_le(x) swaps(x)
#define  swapl_be(x) (x)
#define  swapl_le(x) swapL(x)
#define  swap32_be(x)   (x)
#define  swap32_le(x)   swap32(x)
#endif /* SPARC */


/*
 * Short IO macros
 */
#define  ia_getw(addr)        readw((u16 *)addr)
#define  ia_putw(addr, val)   writew(val, (u16 *)addr)
#define  ia_orw(addr, val) { \
               ushort_t s; \
               s = ia_getw(addr); \
               s |= val; \
               ia_putw(addr, s); \
            }
#define  ia_andw(addr, val)   { \
               ushort_t s; \
               s = ia_getw(addr); \
               s &= val; \
               ia_putw(addr, s); \
            }

/*
 * Long IO macros
 */
#define  ia_get32(addr)       readl((u32 *)addr)
#define  ia_put32(addr, val)  writel(val, (u32 *)addr)
#define  ia_or32(addr, val)   { \
               ulong_t l; \
               l = ia_get32(addr); \
               l |= val; \
               ia_put32(addr, l); \
            }
#define  ia_and32(addr, val)  { \
               ulong_t l; \
               l = ia_get32(addr); \
               l &= val; \
               ia_put32(addr, l); \
            }

#define  ia_getl(addr)       readl((u32 *)addr)
#define  ia_putl(addr, val)  writel(val, (u32*)addr)
#define  ia_orl(addr, val) { \
               ulong_t l; \
               l = ia_getl(addr); \
               l |= val; \
               ia_putl(addr, l); \
            }
#define  ia_andl(addr, val)   { \
               ulong_t l; \
               l = ia_getl(addr); \
               l &= val; \
               ia_putl(addr, l); \
            }

#define pci_config_putl(a, b) \
          pci_write_config_dword(softc->ia_dev, a, b)

#define pci_config_getl(a, b) \
          pci_read_config_dword(softc->ia_dev, a, b)

#endif /* _IA_H */
