linux/drivers/atm/idt77252.c

/******************************************************************* 
 *
 * Copyright (c) 2000 ATecoM GmbH 
 *
 * The author may be reached at [email protected].
 *
 * 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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR   IMPLIED
 * WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 * NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,  INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
 * USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * 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.
 *
 *******************************************************************/

#include <linux/module.h>
#include <linux/pci.h>
#include <linux/poison.h>
#include <linux/skbuff.h>
#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/netdevice.h>
#include <linux/atmdev.h>
#include <linux/atm.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/slab.h>

#include <asm/io.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>
#include <asm/byteorder.h>

#ifdef CONFIG_ATM_IDT77252_USE_SUNI
#include "suni.h"
#endif /* CONFIG_ATM_IDT77252_USE_SUNI */


#include "idt77252.h"
#include "idt77252_tables.h"

static unsigned int vpibits =;


#define ATM_IDT77252_SEND_IDLE


/*
 * Debug HACKs.
 */
#define DEBUG_MODULE
#undef HAVE_EEPROM	/* does not work, yet. */

#ifdef CONFIG_ATM_IDT77252_DEBUG
static unsigned long debug =;
#endif


#define SAR_RX_DELAY


/*
 * SCQ Handling.
 */
static struct scq_info *alloc_scq(struct idt77252_dev *, int);
static void free_scq(struct idt77252_dev *, struct scq_info *);
static int queue_skb(struct idt77252_dev *, struct vc_map *,
		     struct sk_buff *, int oam);
static void drain_scq(struct idt77252_dev *, struct vc_map *);
static unsigned long get_free_scd(struct idt77252_dev *, struct vc_map *);
static void fill_scd(struct idt77252_dev *, struct scq_info *, int);

/*
 * FBQ Handling.
 */
static int push_rx_skb(struct idt77252_dev *,
		       struct sk_buff *, int queue);
static void recycle_rx_skb(struct idt77252_dev *, struct sk_buff *);
static void flush_rx_pool(struct idt77252_dev *, struct rx_pool *);
static void recycle_rx_pool_skb(struct idt77252_dev *,
				struct rx_pool *);
static void add_rx_skb(struct idt77252_dev *, int queue,
		       unsigned int size, unsigned int count);

/*
 * RSQ Handling.
 */
static int init_rsq(struct idt77252_dev *);
static void deinit_rsq(struct idt77252_dev *);
static void idt77252_rx(struct idt77252_dev *);

/*
 * TSQ handling.
 */
static int init_tsq(struct idt77252_dev *);
static void deinit_tsq(struct idt77252_dev *);
static void idt77252_tx(struct idt77252_dev *);


/*
 * ATM Interface.
 */
static void idt77252_dev_close(struct atm_dev *dev);
static int idt77252_open(struct atm_vcc *vcc);
static void idt77252_close(struct atm_vcc *vcc);
static int idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb);
static int idt77252_send_oam(struct atm_vcc *vcc, void *cell,
			     int flags);
static void idt77252_phy_put(struct atm_dev *dev, unsigned char value,
			     unsigned long addr);
static unsigned char idt77252_phy_get(struct atm_dev *dev, unsigned long addr);
static int idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos,
			       int flags);
static int idt77252_proc_read(struct atm_dev *dev, loff_t * pos,
			      char *page);
static void idt77252_softint(struct work_struct *work);


static const struct atmdev_ops idt77252_ops =;

static struct idt77252_dev *idt77252_chain =;
static unsigned int idt77252_sram_write_errors =;

/*****************************************************************************/
/*                                                                           */
/* I/O and Utility Bus                                                       */
/*                                                                           */
/*****************************************************************************/

static void
waitfor_idle(struct idt77252_dev *card)
{}

static u32
read_sram(struct idt77252_dev *card, unsigned long addr)
{}

static void
write_sram(struct idt77252_dev *card, unsigned long addr, u32 value)
{}

static u8
read_utility(void *dev, unsigned long ubus_addr)
{}

static void
write_utility(void *dev, unsigned long ubus_addr, u8 value)
{}

#ifdef HAVE_EEPROM
static u32 rdsrtab[] =
{
	SAR_GP_EECS | SAR_GP_EESCLK,
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	SAR_GP_EEDO,
	SAR_GP_EESCLK | SAR_GP_EEDO,	/* 1 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	SAR_GP_EEDO,
	SAR_GP_EESCLK | SAR_GP_EEDO	/* 1 */
};

static u32 wrentab[] =
{
	SAR_GP_EECS | SAR_GP_EESCLK,
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	SAR_GP_EEDO,
	SAR_GP_EESCLK | SAR_GP_EEDO,	/* 1 */
	SAR_GP_EEDO,
	SAR_GP_EESCLK | SAR_GP_EEDO,	/* 1 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK			/* 0 */
};

static u32 rdtab[] =
{
	SAR_GP_EECS | SAR_GP_EESCLK,
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	SAR_GP_EEDO,
	SAR_GP_EESCLK | SAR_GP_EEDO,	/* 1 */
	SAR_GP_EEDO,
	SAR_GP_EESCLK | SAR_GP_EEDO	/* 1 */
};

static u32 wrtab[] =
{
	SAR_GP_EECS | SAR_GP_EESCLK,
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	0,
	SAR_GP_EESCLK,			/* 0 */
	SAR_GP_EEDO,
	SAR_GP_EESCLK | SAR_GP_EEDO,	/* 1 */
	0,
	SAR_GP_EESCLK			/* 0 */
};

static u32 clktab[] =
{
	0,
	SAR_GP_EESCLK,
	0,
	SAR_GP_EESCLK,
	0,
	SAR_GP_EESCLK,
	0,
	SAR_GP_EESCLK,
	0,
	SAR_GP_EESCLK,
	0,
	SAR_GP_EESCLK,
	0,
	SAR_GP_EESCLK,
	0,
	SAR_GP_EESCLK,
	0
};

static u32
idt77252_read_gp(struct idt77252_dev *card)
{
	u32 gp;

	gp = readl(SAR_REG_GP);
#if 0
	printk("RD: %s\n", gp & SAR_GP_EEDI ? "1" : "0");
#endif
	return gp;
}

static void
idt77252_write_gp(struct idt77252_dev *card, u32 value)
{
	unsigned long flags;

#if 0
	printk("WR: %s %s %s\n", value & SAR_GP_EECS ? "   " : "/CS",
	       value & SAR_GP_EESCLK ? "HIGH" : "LOW ",
	       value & SAR_GP_EEDO   ? "1" : "0");
#endif

	spin_lock_irqsave(&card->cmd_lock, flags);
	waitfor_idle(card);
	writel(value, SAR_REG_GP);
	spin_unlock_irqrestore(&card->cmd_lock, flags);
}

static u8
idt77252_eeprom_read_status(struct idt77252_dev *card)
{
	u8 byte;
	u32 gp;
	int i, j;

	gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);

	for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
		idt77252_write_gp(card, gp | rdsrtab[i]);
		udelay(5);
	}
	idt77252_write_gp(card, gp | SAR_GP_EECS);
	udelay(5);

	byte = 0;
	for (i = 0, j = 0; i < 8; i++) {
		byte <<= 1;

		idt77252_write_gp(card, gp | clktab[j++]);
		udelay(5);

		byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0;

		idt77252_write_gp(card, gp | clktab[j++]);
		udelay(5);
	}
	idt77252_write_gp(card, gp | SAR_GP_EECS);
	udelay(5);

	return byte;
}

static u8
idt77252_eeprom_read_byte(struct idt77252_dev *card, u8 offset)
{
	u8 byte;
	u32 gp;
	int i, j;

	gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);

	for (i = 0; i < ARRAY_SIZE(rdtab); i++) {
		idt77252_write_gp(card, gp | rdtab[i]);
		udelay(5);
	}
	idt77252_write_gp(card, gp | SAR_GP_EECS);
	udelay(5);

	for (i = 0, j = 0; i < 8; i++) {
		idt77252_write_gp(card, gp | clktab[j++] |
					(offset & 1 ? SAR_GP_EEDO : 0));
		udelay(5);

		idt77252_write_gp(card, gp | clktab[j++] |
					(offset & 1 ? SAR_GP_EEDO : 0));
		udelay(5);

		offset >>= 1;
	}
	idt77252_write_gp(card, gp | SAR_GP_EECS);
	udelay(5);

	byte = 0;
	for (i = 0, j = 0; i < 8; i++) {
		byte <<= 1;

		idt77252_write_gp(card, gp | clktab[j++]);
		udelay(5);

		byte |= idt77252_read_gp(card) & SAR_GP_EEDI ? 1 : 0;

		idt77252_write_gp(card, gp | clktab[j++]);
		udelay(5);
	}
	idt77252_write_gp(card, gp | SAR_GP_EECS);
	udelay(5);

	return byte;
}

static void
idt77252_eeprom_write_byte(struct idt77252_dev *card, u8 offset, u8 data)
{
	u32 gp;
	int i, j;

	gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);

	for (i = 0; i < ARRAY_SIZE(wrentab); i++) {
		idt77252_write_gp(card, gp | wrentab[i]);
		udelay(5);
	}
	idt77252_write_gp(card, gp | SAR_GP_EECS);
	udelay(5);

	for (i = 0; i < ARRAY_SIZE(wrtab); i++) {
		idt77252_write_gp(card, gp | wrtab[i]);
		udelay(5);
	}
	idt77252_write_gp(card, gp | SAR_GP_EECS);
	udelay(5);

	for (i = 0, j = 0; i < 8; i++) {
		idt77252_write_gp(card, gp | clktab[j++] |
					(offset & 1 ? SAR_GP_EEDO : 0));
		udelay(5);

		idt77252_write_gp(card, gp | clktab[j++] |
					(offset & 1 ? SAR_GP_EEDO : 0));
		udelay(5);

		offset >>= 1;
	}
	idt77252_write_gp(card, gp | SAR_GP_EECS);
	udelay(5);

	for (i = 0, j = 0; i < 8; i++) {
		idt77252_write_gp(card, gp | clktab[j++] |
					(data & 1 ? SAR_GP_EEDO : 0));
		udelay(5);

		idt77252_write_gp(card, gp | clktab[j++] |
					(data & 1 ? SAR_GP_EEDO : 0));
		udelay(5);

		data >>= 1;
	}
	idt77252_write_gp(card, gp | SAR_GP_EECS);
	udelay(5);
}

static void
idt77252_eeprom_init(struct idt77252_dev *card)
{
	u32 gp;

	gp = idt77252_read_gp(card) & ~(SAR_GP_EESCLK|SAR_GP_EECS|SAR_GP_EEDO);

	idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK);
	udelay(5);
	idt77252_write_gp(card, gp | SAR_GP_EECS);
	udelay(5);
	idt77252_write_gp(card, gp | SAR_GP_EECS | SAR_GP_EESCLK);
	udelay(5);
	idt77252_write_gp(card, gp | SAR_GP_EECS);
	udelay(5);
}
#endif /* HAVE_EEPROM */


#ifdef CONFIG_ATM_IDT77252_DEBUG
static void
dump_tct(struct idt77252_dev *card, int index)
{}

static void
idt77252_tx_dump(struct idt77252_dev *card)
{}
#endif


/*****************************************************************************/
/*                                                                           */
/* SCQ Handling                                                              */
/*                                                                           */
/*****************************************************************************/

static int
sb_pool_add(struct idt77252_dev *card, struct sk_buff *skb, int queue)
{}

static void
sb_pool_remove(struct idt77252_dev *card, struct sk_buff *skb)
{}

static struct sk_buff *
sb_pool_skb(struct idt77252_dev *card, u32 handle)
{}

static struct scq_info *
alloc_scq(struct idt77252_dev *card, int class)
{}

static void
free_scq(struct idt77252_dev *card, struct scq_info *scq)
{}


static int
push_on_scq(struct idt77252_dev *card, struct vc_map *vc, struct sk_buff *skb)
{}


static void
drain_scq(struct idt77252_dev *card, struct vc_map *vc)
{}

static int
queue_skb(struct idt77252_dev *card, struct vc_map *vc,
	  struct sk_buff *skb, int oam)
{}

static unsigned long
get_free_scd(struct idt77252_dev *card, struct vc_map *vc)
{}

static void
fill_scd(struct idt77252_dev *card, struct scq_info *scq, int class)
{}

static void
clear_scd(struct idt77252_dev *card, struct scq_info *scq, int class)
{}

/*****************************************************************************/
/*                                                                           */
/* RSQ Handling                                                              */
/*                                                                           */
/*****************************************************************************/

static int
init_rsq(struct idt77252_dev *card)
{}

static void
deinit_rsq(struct idt77252_dev *card)
{}

static void
dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
{}

static void
idt77252_rx(struct idt77252_dev *card)
{}

static void
idt77252_rx_raw(struct idt77252_dev *card)
{}


/*****************************************************************************/
/*                                                                           */
/* TSQ Handling                                                              */
/*                                                                           */
/*****************************************************************************/

static int
init_tsq(struct idt77252_dev *card)
{}

static void
deinit_tsq(struct idt77252_dev *card)
{}

static void
idt77252_tx(struct idt77252_dev *card)
{}


static void
tst_timer(struct timer_list *t)
{}

static int
__fill_tst(struct idt77252_dev *card, struct vc_map *vc,
	   int n, unsigned int opc)
{}

static int
fill_tst(struct idt77252_dev *card, struct vc_map *vc, int n, unsigned int opc)
{}

static int
__clear_tst(struct idt77252_dev *card, struct vc_map *vc)
{}

static int
clear_tst(struct idt77252_dev *card, struct vc_map *vc)
{}

static int
change_tst(struct idt77252_dev *card, struct vc_map *vc,
	   int n, unsigned int opc)
{}


static int
set_tct(struct idt77252_dev *card, struct vc_map *vc)
{}

/*****************************************************************************/
/*                                                                           */
/* FBQ Handling                                                              */
/*                                                                           */
/*****************************************************************************/

static __inline__ int
idt77252_fbq_full(struct idt77252_dev *card, int queue)
{}

static int
push_rx_skb(struct idt77252_dev *card, struct sk_buff *skb, int queue)
{}

static void
add_rx_skb(struct idt77252_dev *card, int queue,
	   unsigned int size, unsigned int count)
{}


static void
recycle_rx_skb(struct idt77252_dev *card, struct sk_buff *skb)
{}

static void
flush_rx_pool(struct idt77252_dev *card, struct rx_pool *rpp)
{}

static void
recycle_rx_pool_skb(struct idt77252_dev *card, struct rx_pool *rpp)
{}

/*****************************************************************************/
/*                                                                           */
/* ATM Interface                                                             */
/*                                                                           */
/*****************************************************************************/

static void
idt77252_phy_put(struct atm_dev *dev, unsigned char value, unsigned long addr)
{}

static unsigned char
idt77252_phy_get(struct atm_dev *dev, unsigned long addr)
{}

static inline int
idt77252_send_skb(struct atm_vcc *vcc, struct sk_buff *skb, int oam)
{}

static int idt77252_send(struct atm_vcc *vcc, struct sk_buff *skb)
{}

static int
idt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags)
{}

static __inline__ unsigned int
idt77252_fls(unsigned int x)
{}

static u16
idt77252_int_to_atmfp(unsigned int rate)
{}

static u8
idt77252_rate_logindex(struct idt77252_dev *card, int pcr)
{}

static void
idt77252_est_timer(struct timer_list *t)
{}

static struct rate_estimator *
idt77252_init_est(struct vc_map *vc, int pcr)
{}

static int
idt77252_init_cbr(struct idt77252_dev *card, struct vc_map *vc,
		  struct atm_vcc *vcc, struct atm_qos *qos)
{}

static int
idt77252_init_ubr(struct idt77252_dev *card, struct vc_map *vc,
		  struct atm_vcc *vcc, struct atm_qos *qos)
{}

static int
idt77252_init_tx(struct idt77252_dev *card, struct vc_map *vc,
		 struct atm_vcc *vcc, struct atm_qos *qos)
{}

static int
idt77252_init_rx(struct idt77252_dev *card, struct vc_map *vc,
		 struct atm_vcc *vcc, struct atm_qos *qos)
{}

static int
idt77252_open(struct atm_vcc *vcc)
{}

static void
idt77252_close(struct atm_vcc *vcc)
{}

static int
idt77252_change_qos(struct atm_vcc *vcc, struct atm_qos *qos, int flags)
{}

static int
idt77252_proc_read(struct atm_dev *dev, loff_t * pos, char *page)
{}

/*****************************************************************************/
/*                                                                           */
/* Interrupt handler                                                         */
/*                                                                           */
/*****************************************************************************/

static void
idt77252_collect_stat(struct idt77252_dev *card)
{}

static irqreturn_t
idt77252_interrupt(int irq, void *dev_id)
{}

static void
idt77252_softint(struct work_struct *work)
{}


static int
open_card_oam(struct idt77252_dev *card)
{}

static void
close_card_oam(struct idt77252_dev *card)
{}

static int
open_card_ubr0(struct idt77252_dev *card)
{}

static void
close_card_ubr0(struct idt77252_dev *card)
{}

static int
idt77252_dev_open(struct idt77252_dev *card)
{}

static void idt77252_dev_close(struct atm_dev *dev)
{}


/*****************************************************************************/
/*                                                                           */
/* Initialisation and Deinitialization of IDT77252                           */
/*                                                                           */
/*****************************************************************************/


static void
deinit_card(struct idt77252_dev *card)
{}


static void init_sram(struct idt77252_dev *card)
{}

static int init_card(struct atm_dev *dev)
{}


/*****************************************************************************/
/*                                                                           */
/* Probing of IDT77252 ABR SAR                                               */
/*                                                                           */
/*****************************************************************************/


static int idt77252_preset(struct idt77252_dev *card)
{}


static unsigned long probe_sram(struct idt77252_dev *card)
{}

static int idt77252_init_one(struct pci_dev *pcidev,
			     const struct pci_device_id *id)
{}

static const struct pci_device_id idt77252_pci_tbl[] =;

MODULE_DEVICE_TABLE(pci, idt77252_pci_tbl);

static struct pci_driver idt77252_driver =;

static int __init idt77252_init(void)
{}

static void __exit idt77252_exit(void)
{}

module_init();
module_exit(idt77252_exit);

MODULE_LICENSE();

module_param(vpibits, uint, 0);
MODULE_PARM_DESC();
#ifdef CONFIG_ATM_IDT77252_DEBUG
module_param(debug, ulong, 0644);
MODULE_PARM_DESC();
#endif

MODULE_AUTHOR();
MODULE_DESCRIPTION();