📄 idt77252.c
字号:
/******************************************************************* * ident "$Id: idt77252.c,v 1.3 2001/11/17 00:30:19 ecd Exp $" * * $Author: ecd $ * $Date: 2001/11/17 00:30:19 $ * * Copyright (c) 2000 ATecoM GmbH * * The author may be reached at ecd@atecom.com. * * 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. * *******************************************************************/static char const rcsid[] ="$Id: idt77252.c,v 1.3 2001/11/17 00:30:19 ecd Exp $";#include <linux/module.h>#include <linux/config.h>#include <linux/pci.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/bitops.h>#include <linux/wait.h>#include <asm/semaphore.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/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 = 1;#define CONFIG_ATM_IDT77252_SEND_IDLE 1/* * Debug HACKs. */#define DEBUG_MODULE 1#undef HAVE_EEPROM /* does not work, yet. */#ifdef CONFIG_ATM_IDT77252_DEBUGstatic unsigned long debug = DBG_GENERAL;#endif#define SAR_RX_DELAY (SAR_CFG_RXINT_NODELAY)/* * 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, short vpi, int vci);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_interrupt(int irq, void *dev_id, struct pt_regs *regs);static void idt77252_softint(void *dev_id);static struct atmdev_ops idt77252_ops ={ dev_close: idt77252_dev_close, open: idt77252_open, close: idt77252_close, send: idt77252_send, send_oam: idt77252_send_oam, phy_put: idt77252_phy_put, phy_get: idt77252_phy_get, change_qos: idt77252_change_qos, proc_read: idt77252_proc_read};static struct idt77252_dev *idt77252_chain = NULL;static unsigned int idt77252_sram_write_errors = 0;/*****************************************************************************//* *//* I/O and Utility Bus *//* *//*****************************************************************************/static voidwaitfor_idle(struct idt77252_dev *card){ u32 stat; stat = readl(SAR_REG_STAT); while (stat & SAR_STAT_CMDBZ) stat = readl(SAR_REG_STAT);}static u32read_sram(struct idt77252_dev *card, unsigned long addr){ unsigned long flags; u32 value; spin_lock_irqsave(&card->cmd_lock, flags); writel(SAR_CMD_READ_SRAM | (addr << 2), SAR_REG_CMD); waitfor_idle(card); value = readl(SAR_REG_DR0); spin_unlock_irqrestore(&card->cmd_lock, flags); return value;}static voidwrite_sram(struct idt77252_dev *card, unsigned long addr, u32 value){ unsigned long flags; if ((idt77252_sram_write_errors == 0) && (((addr > card->tst[0] + card->tst_size - 2) && (addr < card->tst[0] + card->tst_size)) || ((addr > card->tst[1] + card->tst_size - 2) && (addr < card->tst[1] + card->tst_size)))) { printk("%s: ERROR: TST JMP section at %08lx written: %08x\n", card->name, addr, value); } spin_lock_irqsave(&card->cmd_lock, flags); writel(value, SAR_REG_DR0); writel(SAR_CMD_WRITE_SRAM | (addr << 2), SAR_REG_CMD); waitfor_idle(card); spin_unlock_irqrestore(&card->cmd_lock, flags);}static u8read_utility(void *dev, unsigned long ubus_addr){ struct idt77252_dev *card = dev; unsigned long flags; u8 value; if (!card) { printk("Error: No such device.\n"); return -1; } spin_lock_irqsave(&card->cmd_lock, flags); writel(SAR_CMD_READ_UTILITY + ubus_addr, SAR_REG_CMD); waitfor_idle(card); value = readl(SAR_REG_DR0); spin_unlock_irqrestore(&card->cmd_lock, flags); return value;}static voidwrite_utility(void *dev, unsigned long ubus_addr, u8 value){ struct idt77252_dev *card = dev; unsigned long flags; if (!card) { printk("Error: No such device.\n"); return; } spin_lock_irqsave(&card->cmd_lock, flags); writel((u32) value, SAR_REG_DR0); writel(SAR_CMD_WRITE_UTILITY + ubus_addr, SAR_REG_CMD); waitfor_idle(card); spin_unlock_irqrestore(&card->cmd_lock, flags);}#ifdef HAVE_EEPROMstatic 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 u32idt77252_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 voididt77252_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 u8idt77252_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 < sizeof(rdsrtab)/sizeof(rdsrtab[0]); 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 u8idt77252_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 < sizeof(rdtab)/sizeof(rdtab[0]); 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 voididt77252_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 < sizeof(wrentab)/sizeof(wrentab[0]); i++) { idt77252_write_gp(card, gp | wrentab[i]); udelay(5); } idt77252_write_gp(card, gp | SAR_GP_EECS); udelay(5); for (i = 0; i < sizeof(wrtab)/sizeof(wrtab[0]); 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 voididt77252_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_DEBUGstatic voiddump_tct(struct idt77252_dev *card, int index){ unsigned long tct; int i; tct = (unsigned long) (card->tct_base + index * SAR_SRAM_TCT_SIZE); printk("%s: TCT %x:", card->name, index); for (i = 0; i < 8; i++) { printk(" %08x", read_sram(card, tct + i)); } printk("\n");}static voididt77252_tx_dump(struct idt77252_dev *card){ struct atm_vcc *vcc; struct vc_map *vc; int i; printk("%s\n", __FUNCTION__); for (i = 0; i < card->tct_size; i++) { vc = card->vcs[i]; if (!vc) continue; vcc = NULL; if (vc->rx_vcc) vcc = vc->rx_vcc; else if (vc->tx_vcc) vcc = vc->tx_vcc; if (!vcc) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -