From: Christoph Hellwig <hch@lst.de>
To: netdev@oss.sgi.com
Subject: [PATCH] remove comx drivers from tree
Date: Fri, 7 May 2004 13:17:25 +0200 [thread overview]
Message-ID: <20040507111725.GA11575@lst.de> (raw)
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=unknown-8bit, Size: 275453 bytes --]
the drivers have been broken since pre-2.4.0, like referencing a symbol
that was made procfs-internal in 2.3.x, haven't received maintainer
updates for about the same period and MOD_{INC,DEC}_USE_COUNT usage that
pretty much unfixable (inside warts of _horrible_ procfs abuse).
I'd say just kill them.
--- 1.21/drivers/net/wan/Kconfig Thu Feb 19 04:42:35 2004
+++ edited/drivers/net/wan/Kconfig Fri May 7 13:06:20 2004
@@ -57,119 +57,6 @@
The driver will be compiled as a module: the
module will be called cosa.
-#
-# COMX drivers
-#
-# Not updated to 2.6.
-config COMX
- tristate "MultiGate (COMX) synchronous serial boards support"
- depends on WAN && (ISA || PCI) && BROKEN
- ---help---
- Drivers for the PC synchronous serial adapters by
- ITConsult-Pro Co, Hungary.
-
- Read <file:Documentation/networking/comx.txt> for help on configuring
- and using COMX interfaces. Further info on these cards can be found
- at <http://www.itc.hu/> or <info@itc.hu>.
-
- Say Y if you want to use any board from the MultiGate (COMX)
- family, you must also say Y to "/proc file system support"
- (CONFIG_PROC_FS) in order to use these drivers.
-
- To compile this driver as a module, choose M here: the
- module will be called comx.
-
-config COMX_HW_COMX
- tristate "Support for COMX/CMX/HiCOMX boards"
- depends on COMX
- help
- Driver for the 'CMX', 'COMX' and 'HiCOMX' boards.
-
- You will need additional firmware to use these cards, which are
- downloadable from <ftp://ftp.itc.hu/>.
-
- Say Y if you have a board like this.
-
- To compile this driver as a module, choose M here: the
- module will be called comx-hw-comx.
-
-config COMX_HW_LOCOMX
- tristate "Support for LoCOMX board"
- depends on COMX
- help
- Driver for the 'LoCOMX' board.
-
- Say Y if you have a board like this.
-
- To compile this driver as a module, choose M here: the
- module will be called comx-hw-locomx.
-
-config COMX_HW_MIXCOM
- tristate "Support for MixCOM board"
- depends on COMX
- ---help---
- Driver for the 'MixCOM' board.
-
- If you want to use the watchdog device on this card, you should
- select it in the Watchdog Cards section of the Character Devices
- configuration. The ISDN interface of this card is Teles 16.3
- compatible, you should enable it in the ISDN configuration menu. The
- driver for the flash ROM of this card is available separately on
- <ftp://ftp.itc.hu/>.
-
- Say Y if you have a board like this.
-
- To compile this driver as a module, choose M here: the
- module will be called comx-hw-mixcom.
-
-config COMX_HW_MUNICH
- tristate "Support for MUNICH based boards: SliceCOM, PCICOM (WelCOM)"
- depends on COMX
- ---help---
- Driver for the 'SliceCOM' (channelized E1) and 'PciCOM' (X21) boards.
-
- Read <file:Documentation/networking/slicecom.txt> for help on
- configuring and using SliceCOM interfaces. Further info on these
- cards can be found at <http://www.itc.hu> or <info@itc.hu>.
-
- Say Y if you have a board like this.
-
- To compile this driver as a module, choose M here: the
- module will be called comx-hw-munich.
-
-config COMX_PROTO_PPP
- tristate "Support for HDLC and syncPPP protocols on MultiGate boards"
- depends on COMX
- help
- Cisco-HDLC and synchronous PPP protocol driver.
-
- Say Y if you want to use either protocol.
-
- To compile this as a module, choose M here: the
- module will be called comx-proto-ppp.
-
-config COMX_PROTO_LAPB
- tristate "Support for LAPB protocol on MultiGate boards"
- depends on WAN && (COMX!=n && LAPB=m && LAPB || LAPB=y && COMX)
- help
- LAPB protocol driver.
-
- Say Y if you want to use this protocol.
-
- To compile this as a module, choose M here: the
- module will be called comx-proto-lapb.
-
-config COMX_PROTO_FR
- tristate "Support for Frame Relay on MultiGate boards"
- depends on COMX
- help
- Frame Relay protocol driver.
-
- Say Y if you want to use this protocol.
-
- To compile this as a module, choose M here: the
- module will be called comx-proto-fr.
-
config DSCC4
tristate "Etinc PCISYNC serial board support"
depends on WAN && PCI && m
===== drivers/net/wan/Makefile 1.18 vs edited =====
--- 1.18/drivers/net/wan/Makefile Sat Jan 10 17:14:26 2004
+++ edited/drivers/net/wan/Makefile Fri May 7 13:06:05 2004
@@ -32,14 +32,6 @@
obj-$(CONFIG_HOSTESS_SV11) += z85230.o syncppp.o hostess_sv11.o
obj-$(CONFIG_SEALEVEL_4021) += z85230.o syncppp.o sealevel.o
-obj-$(CONFIG_COMX) += comx.o
-obj-$(CONFIG_COMX_HW_COMX) += comx-hw-comx.o
-obj-$(CONFIG_COMX_HW_LOCOMX) += z85230.o syncppp.o comx-hw-locomx.o
-obj-$(CONFIG_COMX_HW_MIXCOM) += comx-hw-mixcom.o
-obj-$(CONFIG_COMX_HW_MUNICH) += comx-hw-munich.o
-obj-$(CONFIG_COMX_PROTO_PPP) += syncppp.o comx-proto-ppp.o
-obj-$(CONFIG_COMX_PROTO_LAPB) += comx-proto-lapb.o
-obj-$(CONFIG_COMX_PROTO_FR) += comx-proto-fr.o
obj-$(CONFIG_COSA) += syncppp.o cosa.o
obj-$(CONFIG_FARSYNC) += syncppp.o farsync.o
obj-$(CONFIG_DSCC4) += dscc4.o
===== drivers/net/wan/comx-hw-comx.c 1.13 vs edited =====
--- 1.13/drivers/net/wan/comx-hw-comx.c Thu Sep 11 19:40:53 2003
+++ edited/drivers/net/wan/comx-hw-comx.c Fri May 7 13:05:52 2004
@@ -1,1450 +1 @@
-/*
- * Hardware-level driver for the COMX and HICOMX cards
- * for Linux kernel 2.2.X
- *
- * Original authors: Arpad Bakay <bakay.arpad@synergon.hu>,
- * Peter Bajan <bajan.peter@synergon.hu>,
- * Rewritten by: Tivadar Szemethy <tiv@itc.hu>
- * Currently maintained by: Gergely Madarasz <gorgo@itc.hu>
- *
- * Copyright (C) 1995-2000 ITConsult-Pro Co. <info@itc.hu>
- *
- * Contributors:
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 0.86
- * Daniele Bellucci <bellucda@tiscali.it> - 0.87
- *
- * 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.
- *
- * Version 0.80 (99/06/11):
- * - port back to kernel, add support builtin driver
- * - cleaned up the source code a bit
- *
- * Version 0.81 (99/06/22):
- * - cleaned up the board load functions, no more long reset
- * timeouts
- * - lower modem lines on close
- * - some interrupt handling fixes
- *
- * Version 0.82 (99/08/24):
- * - fix multiple board support
- *
- * Version 0.83 (99/11/30):
- * - interrupt handling and locking fixes during initalization
- * - really fix multiple board support
- *
- * Version 0.84 (99/12/02):
- * - some workarounds for problematic hardware/firmware
- *
- * Version 0.85 (00/01/14):
- * - some additional workarounds :/
- * - printk cleanups
- * Version 0.86 (00/08/15):
- * - resource release on failure at COMX_init
- *
- * Version 0.87 (03/07/09)
- * - audit copy_from_user in comxhw_write_proc
- */
-#define VERSION "0.87"
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#include "comx.h"
-#include "comxhw.h"
-
-MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>, Tivadar Szemethy <tiv@itc.hu>, Arpad Bakay");
-MODULE_DESCRIPTION("Hardware-level driver for the COMX and HICOMX adapters\n");
-MODULE_LICENSE("GPL");
-
-#define COMX_readw(dev, offset) (readw(dev->mem_start + offset + \
- (unsigned int)(((struct comx_privdata *)\
- ((struct comx_channel *)dev->priv)->HW_privdata)->channel) \
- * COMX_CHANNEL_OFFSET))
-
-#define COMX_WRITE(dev, offset, value) (writew(value, dev->mem_start + offset \
- + (unsigned int)(((struct comx_privdata *) \
- ((struct comx_channel *)dev->priv)->HW_privdata)->channel) \
- * COMX_CHANNEL_OFFSET))
-
-#define COMX_CMD(dev, cmd) (COMX_WRITE(dev, OFF_A_L2_CMD, cmd))
-
-struct comx_firmware {
- int len;
- unsigned char *data;
-};
-
-struct comx_privdata {
- struct comx_firmware *firmware;
- u16 clock;
- char channel; // channel no.
- int memory_size;
- short io_extent;
- u_long histogram[5];
-};
-
-static struct net_device *memory_used[(COMX_MEM_MAX - COMX_MEM_MIN) / 0x10000];
-extern struct comx_hardware hicomx_hw;
-extern struct comx_hardware comx_hw;
-extern struct comx_hardware cmx_hw;
-
-static irqreturn_t COMX_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-
-static void COMX_board_on(struct net_device *dev)
-{
- outb_p( (byte) (((dev->mem_start & 0xf0000) >> 16) |
- COMX_ENABLE_BOARD_IT | COMX_ENABLE_BOARD_MEM), dev->base_addr);
-}
-
-static void COMX_board_off(struct net_device *dev)
-{
- outb_p( (byte) (((dev->mem_start & 0xf0000) >> 16) |
- COMX_ENABLE_BOARD_IT), dev->base_addr);
-}
-
-static void HICOMX_board_on(struct net_device *dev)
-{
- outb_p( (byte) (((dev->mem_start & 0xf0000) >> 12) |
- HICOMX_ENABLE_BOARD_MEM), dev->base_addr);
-}
-
-static void HICOMX_board_off(struct net_device *dev)
-{
- outb_p( (byte) (((dev->mem_start & 0xf0000) >> 12) |
- HICOMX_DISABLE_BOARD_MEM), dev->base_addr);
-}
-
-static void COMX_set_clock(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw = ch->HW_privdata;
-
- COMX_WRITE(dev, OFF_A_L1_CLKINI, hw->clock);
-}
-
-static struct net_device *COMX_access_board(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct net_device *ret;
- int mempos = (dev->mem_start - COMX_MEM_MIN) >> 16;
- unsigned long flags;
-
-
- save_flags(flags); cli();
-
- ret = memory_used[mempos];
-
- if(ret == dev) {
- goto out;
- }
-
- memory_used[mempos] = dev;
-
- if (!ch->twin || ret != ch->twin) {
- if (ret) ((struct comx_channel *)ret->priv)->HW_board_off(ret);
- ch->HW_board_on(dev);
- }
-out:
- restore_flags(flags);
- return ret;
-}
-
-static void COMX_release_board(struct net_device *dev, struct net_device *savep)
-{
- unsigned long flags;
- int mempos = (dev->mem_start - COMX_MEM_MIN) >> 16;
- struct comx_channel *ch = dev->priv;
-
- save_flags(flags); cli();
-
- if (memory_used[mempos] == savep) {
- goto out;
- }
-
- memory_used[mempos] = savep;
- if (!ch->twin || ch->twin != savep) {
- ch->HW_board_off(dev);
- if (savep) ((struct comx_channel*)savep->priv)->HW_board_on(savep);
- }
-out:
- restore_flags(flags);
-}
-
-static int COMX_txe(struct net_device *dev)
-{
- struct net_device *savep;
- struct comx_channel *ch = dev->priv;
- int rc = 0;
-
- savep = ch->HW_access_board(dev);
- if (COMX_readw(dev,OFF_A_L2_LINKUP) == LINKUP_READY) {
- rc = COMX_readw(dev,OFF_A_L2_TxEMPTY);
- }
- ch->HW_release_board(dev,savep);
- if(rc==0xffff) {
- printk(KERN_ERR "%s, OFF_A_L2_TxEMPTY is %d\n",dev->name, rc);
- }
- return rc;
-}
-
-static int COMX_send_packet(struct net_device *dev, struct sk_buff *skb)
-{
- struct net_device *savep;
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw = ch->HW_privdata;
- int ret = FRAME_DROPPED;
- word tmp;
-
- savep = ch->HW_access_board(dev);
-
- if (ch->debug_flags & DEBUG_HW_TX) {
- comx_debug_bytes(dev, skb->data, skb->len,"COMX_send packet");
- }
-
- if (skb->len > COMX_MAX_TX_SIZE) {
- ret=FRAME_DROPPED;
- goto out;
- }
-
- tmp=COMX_readw(dev, OFF_A_L2_TxEMPTY);
- if ((ch->line_status & LINE_UP) && tmp==1) {
- int lensave = skb->len;
- int dest = COMX_readw(dev, OFF_A_L2_TxBUFP);
- word *data = (word *)skb->data;
-
- if(dest==0xffff) {
- printk(KERN_ERR "%s: OFF_A_L2_TxBUFP is %d\n", dev->name, dest);
- ret=FRAME_DROPPED;
- goto out;
- }
-
- writew((unsigned short)skb->len, dev->mem_start + dest);
- dest += 2;
- while (skb->len > 1) {
- writew(*data++, dev->mem_start + dest);
- dest += 2; skb->len -= 2;
- }
- if (skb->len == 1) {
- writew(*((byte *)data), dev->mem_start + dest);
- }
- writew(0, dev->mem_start + (int)hw->channel *
- COMX_CHANNEL_OFFSET + OFF_A_L2_TxEMPTY);
- ch->stats.tx_packets++;
- ch->stats.tx_bytes += lensave;
- ret = FRAME_ACCEPTED;
- } else {
- ch->stats.tx_dropped++;
- printk(KERN_INFO "%s: frame dropped\n",dev->name);
- if(tmp) {
- printk(KERN_ERR "%s: OFF_A_L2_TxEMPTY is %d\n",dev->name,tmp);
- }
- }
-
-out:
- ch->HW_release_board(dev, savep);
- dev_kfree_skb(skb);
- return ret;
-}
-
-static inline int comx_read_buffer(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- word rbuf_offs;
- struct sk_buff *skb;
- word len;
- int i=0;
- word *writeptr;
-
- i = 0;
- rbuf_offs = COMX_readw(dev, OFF_A_L2_RxBUFP);
- if(rbuf_offs == 0xffff) {
- printk(KERN_ERR "%s: OFF_A_L2_RxBUFP is %d\n",dev->name,rbuf_offs);
- return 0;
- }
- len = readw(dev->mem_start + rbuf_offs);
- if(len > COMX_MAX_RX_SIZE) {
- printk(KERN_ERR "%s: packet length is %d\n",dev->name,len);
- return 0;
- }
- if ((skb = dev_alloc_skb(len + 16)) == NULL) {
- ch->stats.rx_dropped++;
- COMX_WRITE(dev, OFF_A_L2_DAV, 0);
- return 0;
- }
- rbuf_offs += 2;
- skb_reserve(skb, 16);
- skb_put(skb, len);
- skb->dev = dev;
- writeptr = (word *)skb->data;
- while (i < len) {
- *writeptr++ = readw(dev->mem_start + rbuf_offs);
- rbuf_offs += 2;
- i += 2;
- }
- COMX_WRITE(dev, OFF_A_L2_DAV, 0);
- ch->stats.rx_packets++;
- ch->stats.rx_bytes += len;
- if (ch->debug_flags & DEBUG_HW_RX) {
- comx_debug_skb(dev, skb, "COMX_interrupt receiving");
- }
- ch->LINE_rx(dev, skb);
- return 1;
-}
-
-static inline char comx_line_change(struct net_device *dev, char linestat)
-{
- struct comx_channel *ch=dev->priv;
- char idle=1;
-
-
- if (linestat & LINE_UP) { /* Vonal fol */
- if (ch->lineup_delay) {
- if (!test_and_set_bit(0, &ch->lineup_pending)) {
- ch->lineup_timer.function = comx_lineup_func;
- ch->lineup_timer.data = (unsigned long)dev;
- ch->lineup_timer.expires = jiffies +
- HZ*ch->lineup_delay;
- add_timer(&ch->lineup_timer);
- idle=0;
- }
- } else {
- idle=0;
- ch->LINE_status(dev, ch->line_status |= LINE_UP);
- }
- } else { /* Vonal le */
- idle=0;
- if (test_and_clear_bit(0, &ch->lineup_pending)) {
- del_timer(&ch->lineup_timer);
- } else {
- ch->line_status &= ~LINE_UP;
- if (ch->LINE_status) {
- ch->LINE_status(dev, ch->line_status);
- }
- }
- }
- return idle;
-}
-
-
-
-static irqreturn_t COMX_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct net_device *dev = dev_id;
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw = ch->HW_privdata;
- struct net_device *interrupted;
- unsigned long jiffs;
- char idle = 0;
- int count = 0;
- word tmp;
-
- if (dev == NULL) {
- printk(KERN_ERR "COMX_interrupt: irq %d for unknown device\n", irq);
- return IRQ_NONE;
- }
-
- jiffs = jiffies;
-
- interrupted = ch->HW_access_board(dev);
-
- while (!idle && count < 5000) {
- char channel = 0;
- idle = 1;
-
- while (channel < 2) {
- char linestat = 0;
- char buffers_emptied = 0;
-
- if (channel == 1) {
- if (ch->twin) {
- dev = ch->twin;
- ch = dev->priv;
- hw = ch->HW_privdata;
- } else {
- break;
- }
- } else {
- COMX_WRITE(dev, OFF_A_L1_REPENA,
- COMX_readw(dev, OFF_A_L1_REPENA) & 0xFF00);
- }
- channel++;
-
- if ((ch->init_status & (HW_OPEN | LINE_OPEN)) !=
- (HW_OPEN | LINE_OPEN)) {
- continue;
- }
-
- /* Collect stats */
- tmp = COMX_readw(dev, OFF_A_L1_ABOREC);
- COMX_WRITE(dev, OFF_A_L1_ABOREC, 0);
- if(tmp==0xffff) {
- printk(KERN_ERR "%s: OFF_A_L1_ABOREC is %d\n",dev->name,tmp);
- break;
- } else {
- ch->stats.rx_missed_errors += (tmp >> 8) & 0xff;
- ch->stats.rx_over_errors += tmp & 0xff;
- }
- tmp = COMX_readw(dev, OFF_A_L1_CRCREC);
- COMX_WRITE(dev, OFF_A_L1_CRCREC, 0);
- if(tmp==0xffff) {
- printk(KERN_ERR "%s: OFF_A_L1_CRCREC is %d\n",dev->name,tmp);
- break;
- } else {
- ch->stats.rx_crc_errors += (tmp >> 8) & 0xff;
- ch->stats.rx_missed_errors += tmp & 0xff;
- }
-
- if ((ch->line_status & LINE_UP) && ch->LINE_rx) {
- tmp=COMX_readw(dev, OFF_A_L2_DAV);
- while (tmp==1) {
- idle=0;
- buffers_emptied+=comx_read_buffer(dev);
- tmp=COMX_readw(dev, OFF_A_L2_DAV);
- }
- if(tmp) {
- printk(KERN_ERR "%s: OFF_A_L2_DAV is %d\n", dev->name, tmp);
- break;
- }
- }
-
- tmp=COMX_readw(dev, OFF_A_L2_TxEMPTY);
- if (tmp==1 && ch->LINE_tx) {
- ch->LINE_tx(dev);
- }
- if(tmp==0xffff) {
- printk(KERN_ERR "%s: OFF_A_L2_TxEMPTY is %d\n", dev->name, tmp);
- break;
- }
-
- if (COMX_readw(dev, OFF_A_L1_PBUFOVR) >> 8) {
- linestat &= ~LINE_UP;
- } else {
- linestat |= LINE_UP;
- }
-
- if ((linestat & LINE_UP) != (ch->line_status & LINE_UP)) {
- ch->stats.tx_carrier_errors++;
- idle &= comx_line_change(dev,linestat);
- }
-
- hw->histogram[(int)buffers_emptied]++;
- }
- count++;
- }
-
- if(count==5000) {
- printk(KERN_WARNING "%s: interrupt stuck\n",dev->name);
- }
-
- ch->HW_release_board(dev, interrupted);
- return IRQ_HANDLED;
-}
-
-static int COMX_open(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw = ch->HW_privdata;
- struct proc_dir_entry *procfile = ch->procdir->subdir;
- unsigned long jiffs;
- int twin_open=0;
- int retval;
- struct net_device *savep;
-
- if (!dev->base_addr || !dev->irq || !dev->mem_start) {
- return -ENODEV;
- }
-
- if (ch->twin && (((struct comx_channel *)(ch->twin->priv))->init_status & HW_OPEN)) {
- twin_open=1;
- }
-
- if (!twin_open) {
- if (!request_region(dev->base_addr, hw->io_extent, dev->name)) {
- return -EAGAIN;
- }
- if (request_irq(dev->irq, COMX_interrupt, 0, dev->name,
- (void *)dev)) {
- printk(KERN_ERR "comx-hw-comx: unable to obtain irq %d\n", dev->irq);
- release_region(dev->base_addr, hw->io_extent);
- return -EAGAIN;
- }
- ch->init_status |= IRQ_ALLOCATED;
- if (!ch->HW_load_board || ch->HW_load_board(dev)) {
- ch->init_status &= ~IRQ_ALLOCATED;
- retval=-ENODEV;
- goto error;
- }
- }
-
- savep = ch->HW_access_board(dev);
- COMX_WRITE(dev, OFF_A_L2_LINKUP, 0);
-
- if (ch->HW_set_clock) {
- ch->HW_set_clock(dev);
- }
-
- COMX_CMD(dev, COMX_CMD_INIT);
- jiffs = jiffies;
- while (COMX_readw(dev, OFF_A_L2_LINKUP) != 1 && time_before(jiffies, jiffs + HZ)) {
- schedule_timeout(1);
- }
-
- if (time_after_eq(jiffies, jiffs + HZ)) {
- printk(KERN_ERR "%s: board timeout on INIT command\n", dev->name);
- ch->HW_release_board(dev, savep);
- retval=-EIO;
- goto error;
- }
- udelay(1000);
-
- COMX_CMD(dev, COMX_CMD_OPEN);
-
- jiffs = jiffies;
- while (COMX_readw(dev, OFF_A_L2_LINKUP) != 3 && time_before(jiffies, jiffs + HZ)) {
- schedule_timeout(1);
- }
-
- if (time_after_eq(jiffies, jiffs + HZ)) {
- printk(KERN_ERR "%s: board timeout on OPEN command\n", dev->name);
- ch->HW_release_board(dev, savep);
- retval=-EIO;
- goto error;
- }
-
- ch->init_status |= HW_OPEN;
-
- /* Ez eleg ciki, de ilyen a rendszer */
- if (COMX_readw(dev, OFF_A_L1_PBUFOVR) >> 8) {
- ch->line_status &= ~LINE_UP;
- } else {
- ch->line_status |= LINE_UP;
- }
-
- if (ch->LINE_status) {
- ch->LINE_status(dev, ch->line_status);
- }
-
- ch->HW_release_board(dev, savep);
-
- for ( ; procfile ; procfile = procfile->next) {
- if (strcmp(procfile->name, FILENAME_IRQ) == 0
- || strcmp(procfile->name, FILENAME_IO) == 0
- || strcmp(procfile->name, FILENAME_MEMADDR) == 0
- || strcmp(procfile->name, FILENAME_CHANNEL) == 0
- || strcmp(procfile->name, FILENAME_FIRMWARE) == 0
- || strcmp(procfile->name, FILENAME_CLOCK) == 0) {
- procfile->mode = S_IFREG | 0444;
-
- }
- }
-
- return 0;
-
-error:
- if(!twin_open) {
- release_region(dev->base_addr, hw->io_extent);
- free_irq(dev->irq, (void *)dev);
- }
- return retval;
-
-}
-
-static int COMX_close(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct proc_dir_entry *procfile = ch->procdir->subdir;
- struct comx_privdata *hw = ch->HW_privdata;
- struct comx_channel *twin_ch;
- struct net_device *savep;
-
- savep = ch->HW_access_board(dev);
-
- COMX_CMD(dev, COMX_CMD_CLOSE);
- udelay(1000);
- COMX_CMD(dev, COMX_CMD_EXIT);
-
- ch->HW_release_board(dev, savep);
-
- if (ch->init_status & IRQ_ALLOCATED) {
- free_irq(dev->irq, (void *)dev);
- ch->init_status &= ~IRQ_ALLOCATED;
- }
- release_region(dev->base_addr, hw->io_extent);
-
- if (ch->twin && (twin_ch = ch->twin->priv) &&
- (twin_ch->init_status & HW_OPEN)) {
- /* Pass the irq to the twin */
- if (request_irq(dev->irq, COMX_interrupt, 0, ch->twin->name,
- (void *)ch->twin) == 0) {
- twin_ch->init_status |= IRQ_ALLOCATED;
- }
- }
-
- for ( ; procfile ; procfile = procfile->next) {
- if (strcmp(procfile->name, FILENAME_IRQ) == 0
- || strcmp(procfile->name, FILENAME_IO) == 0
- || strcmp(procfile->name, FILENAME_MEMADDR) == 0
- || strcmp(procfile->name, FILENAME_CHANNEL) == 0
- || strcmp(procfile->name, FILENAME_FIRMWARE) == 0
- || strcmp(procfile->name, FILENAME_CLOCK) == 0) {
- procfile->mode = S_IFREG | 0644;
- }
- }
-
- ch->init_status &= ~HW_OPEN;
- return 0;
-}
-
-static int COMX_statistics(struct net_device *dev, char *page)
-{
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw = ch->HW_privdata;
- struct net_device *savep;
- int len = 0;
-
- savep = ch->HW_access_board(dev);
-
- len += sprintf(page + len, "Board data: %s %s %s %s\nPBUFOVR: %02x, "
- "MODSTAT: %02x, LINKUP: %02x, DAV: %02x\nRxBUFP: %02x, "
- "TxEMPTY: %02x, TxBUFP: %02x\n",
- (ch->init_status & HW_OPEN) ? "HW_OPEN" : "",
- (ch->init_status & LINE_OPEN) ? "LINE_OPEN" : "",
- (ch->init_status & FW_LOADED) ? "FW_LOADED" : "",
- (ch->init_status & IRQ_ALLOCATED) ? "IRQ_ALLOCATED" : "",
- COMX_readw(dev, OFF_A_L1_PBUFOVR) & 0xff,
- (COMX_readw(dev, OFF_A_L1_PBUFOVR) >> 8) & 0xff,
- COMX_readw(dev, OFF_A_L2_LINKUP) & 0xff,
- COMX_readw(dev, OFF_A_L2_DAV) & 0xff,
- COMX_readw(dev, OFF_A_L2_RxBUFP) & 0xff,
- COMX_readw(dev, OFF_A_L2_TxEMPTY) & 0xff,
- COMX_readw(dev, OFF_A_L2_TxBUFP) & 0xff);
-
- len += sprintf(page + len, "hist[0]: %8lu hist[1]: %8lu hist[2]: %8lu\n"
- "hist[3]: %8lu hist[4]: %8lu\n",hw->histogram[0],hw->histogram[1],
- hw->histogram[2],hw->histogram[3],hw->histogram[4]);
-
- ch->HW_release_board(dev, savep);
-
- return len;
-}
-
-static int COMX_load_board(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw = ch->HW_privdata;
- struct comx_firmware *fw = hw->firmware;
- word board_segment = dev->mem_start >> 16;
- int mempos = (dev->mem_start - COMX_MEM_MIN) >> 16;
- unsigned long flags;
- unsigned char id1, id2;
- struct net_device *saved;
- int retval;
- int loopcount;
- int len;
- byte *COMX_address;
-
- if (!fw || !fw->len) {
- struct comx_channel *twin_ch = ch->twin ? ch->twin->priv : NULL;
- struct comx_privdata *twin_hw;
-
- if (!twin_ch || !(twin_hw = twin_ch->HW_privdata)) {
- return -EAGAIN;
- }
-
- if (!(fw = twin_hw->firmware) || !fw->len) {
- return -EAGAIN;
- }
- }
-
- id1 = fw->data[OFF_FW_L1_ID];
- id2 = fw->data[OFF_FW_L1_ID + 1];
-
- if (id1 != FW_L1_ID_1 || id2 != FW_L1_ID_2_COMX) {
- printk(KERN_ERR "%s: incorrect firmware, load aborted\n",
- dev->name);
- return -EAGAIN;
- }
-
- printk(KERN_INFO "%s: Loading COMX Layer 1 firmware %s\n", dev->name,
- (char *)(fw->data + OFF_FW_L1_ID + 2));
-
- id1 = fw->data[OFF_FW_L2_ID];
- id2 = fw->data[OFF_FW_L2_ID + 1];
- if (id1 == FW_L2_ID_1 && (id2 == 0xc0 || id2 == 0xc1 || id2 == 0xc2)) {
- printk(KERN_INFO "with Layer 2 code %s\n",
- (char *)(fw->data + OFF_FW_L2_ID + 2));
- }
-
- outb_p(board_segment | COMX_BOARD_RESET, dev->base_addr);
- /* 10 usec should be enough here */
- udelay(100);
-
- save_flags(flags); cli();
- saved=memory_used[mempos];
- if(saved) {
- ((struct comx_channel *)saved->priv)->HW_board_off(saved);
- }
- memory_used[mempos]=dev;
-
- outb_p(board_segment | COMX_ENABLE_BOARD_MEM, dev->base_addr);
-
- writeb(0, dev->mem_start + COMX_JAIL_OFFSET);
-
- loopcount=0;
- while(loopcount++ < 10000 &&
- readb(dev->mem_start + COMX_JAIL_OFFSET) != COMX_JAIL_VALUE) {
- udelay(100);
- }
-
- if (readb(dev->mem_start + COMX_JAIL_OFFSET) != COMX_JAIL_VALUE) {
- printk(KERN_ERR "%s: Can't reset board, JAIL value is %02x\n",
- dev->name, readb(dev->mem_start + COMX_JAIL_OFFSET));
- retval=-ENODEV;
- goto out;
- }
-
- writeb(0x55, dev->mem_start + 0x18ff);
-
- loopcount=0;
- while(loopcount++ < 10000 && readb(dev->mem_start + 0x18ff) != 0) {
- udelay(100);
- }
-
- if(readb(dev->mem_start + 0x18ff) != 0) {
- printk(KERN_ERR "%s: Can't reset board, reset timeout\n",
- dev->name);
- retval=-ENODEV;
- goto out;
- }
-
- len = 0;
- COMX_address = (byte *)dev->mem_start;
- while (fw->len > len) {
- writeb(fw->data[len++], COMX_address++);
- }
-
- len = 0;
- COMX_address = (byte *)dev->mem_start;
- while (len != fw->len && readb(COMX_address++) == fw->data[len]) {
- len++;
- }
-
- if (len != fw->len) {
- printk(KERN_ERR "%s: error loading firmware: [%d] is 0x%02x "
- "instead of 0x%02x\n", dev->name, len,
- readb(COMX_address - 1), fw->data[len]);
- retval=-EAGAIN;
- goto out;
- }
-
- writeb(0, dev->mem_start + COMX_JAIL_OFFSET);
-
- loopcount = 0;
- while ( loopcount++ < 10000 && COMX_readw(dev, OFF_A_L2_LINKUP) != 1 ) {
- udelay(100);
- }
-
- if (COMX_readw(dev, OFF_A_L2_LINKUP) != 1) {
- printk(KERN_ERR "%s: error starting firmware, linkup word is %04x\n",
- dev->name, COMX_readw(dev, OFF_A_L2_LINKUP));
- retval=-EAGAIN;
- goto out;
- }
-
-
- ch->init_status |= FW_LOADED;
- retval=0;
-
-out:
- outb_p(board_segment | COMX_DISABLE_ALL, dev->base_addr);
- if(saved) {
- ((struct comx_channel *)saved->priv)->HW_board_on(saved);
- }
- memory_used[mempos]=saved;
- restore_flags(flags);
- return retval;
-}
-
-static int CMX_load_board(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw = ch->HW_privdata;
- struct comx_firmware *fw = hw->firmware;
- word board_segment = dev->mem_start >> 16;
- int mempos = (dev->mem_start - COMX_MEM_MIN) >> 16;
- #if 0
- unsigned char id1, id2;
- #endif
- struct net_device *saved;
- unsigned long flags;
- int retval;
- int loopcount;
- int len;
- byte *COMX_address;
-
- if (!fw || !fw->len) {
- struct comx_channel *twin_ch = ch->twin ? ch->twin->priv : NULL;
- struct comx_privdata *twin_hw;
-
- if (!twin_ch || !(twin_hw = twin_ch->HW_privdata)) {
- return -EAGAIN;
- }
-
- if (!(fw = twin_hw->firmware) || !fw->len) {
- return -EAGAIN;
- }
- }
-
- /* Ide kell olyat tenni, hogy ellenorizze az ID-t */
-
- if (inb_p(dev->base_addr) != CMX_ID_BYTE) {
- printk(KERN_ERR "%s: CMX id byte is invalid(%02x)\n", dev->name,
- inb_p(dev->base_addr));
- return -ENODEV;
- }
-
- printk(KERN_INFO "%s: Loading CMX Layer 1 firmware %s\n", dev->name,
- (char *)(fw->data + OFF_FW_L1_ID + 2));
-
- save_flags(flags); cli();
- saved=memory_used[mempos];
- if(saved) {
- ((struct comx_channel *)saved->priv)->HW_board_off(saved);
- }
- memory_used[mempos]=dev;
-
- outb_p(board_segment | COMX_ENABLE_BOARD_MEM | COMX_BOARD_RESET,
- dev->base_addr);
-
- len = 0;
- COMX_address = (byte *)dev->mem_start;
- while (fw->len > len) {
- writeb(fw->data[len++], COMX_address++);
- }
-
- len = 0;
- COMX_address = (byte *)dev->mem_start;
- while (len != fw->len && readb(COMX_address++) == fw->data[len]) {
- len++;
- }
-
- outb_p(board_segment | COMX_ENABLE_BOARD_MEM, dev->base_addr);
-
- if (len != fw->len) {
- printk(KERN_ERR "%s: error loading firmware: [%d] is 0x%02x "
- "instead of 0x%02x\n", dev->name, len,
- readb(COMX_address - 1), fw->data[len]);
- retval=-EAGAIN;
- goto out;
- }
-
- loopcount=0;
- while( loopcount++ < 10000 && COMX_readw(dev, OFF_A_L2_LINKUP) != 1 ) {
- udelay(100);
- }
-
- if (COMX_readw(dev, OFF_A_L2_LINKUP) != 1) {
- printk(KERN_ERR "%s: error starting firmware, linkup word is %04x\n",
- dev->name, COMX_readw(dev, OFF_A_L2_LINKUP));
- retval=-EAGAIN;
- goto out;
- }
-
- ch->init_status |= FW_LOADED;
- retval=0;
-
-out:
- outb_p(board_segment | COMX_DISABLE_ALL, dev->base_addr);
- if(saved) {
- ((struct comx_channel *)saved->priv)->HW_board_on(saved);
- }
- memory_used[mempos]=saved;
- restore_flags(flags);
- return retval;
-}
-
-static int HICOMX_load_board(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw = ch->HW_privdata;
- struct comx_firmware *fw = hw->firmware;
- word board_segment = dev->mem_start >> 12;
- int mempos = (dev->mem_start - COMX_MEM_MIN) >> 16;
- struct net_device *saved;
- unsigned char id1, id2;
- unsigned long flags;
- int retval;
- int loopcount;
- int len;
- word *HICOMX_address;
- char id = 1;
-
- if (!fw || !fw->len) {
- struct comx_channel *twin_ch = ch->twin ? ch->twin->priv : NULL;
- struct comx_privdata *twin_hw;
-
- if (!twin_ch || !(twin_hw = twin_ch->HW_privdata)) {
- return -EAGAIN;
- }
-
- if (!(fw = twin_hw->firmware) || !fw->len) {
- return -EAGAIN;
- }
- }
-
- while (id != 4) {
- if (inb_p(dev->base_addr + id++) != HICOMX_ID_BYTE) {
- break;
- }
- }
-
- if (id != 4) {
- printk(KERN_ERR "%s: can't find HICOMX at 0x%04x, id[%d] = %02x\n",
- dev->name, (unsigned int)dev->base_addr, id - 1,
- inb_p(dev->base_addr + id - 1));
- return -1;
- }
-
- id1 = fw->data[OFF_FW_L1_ID];
- id2 = fw->data[OFF_FW_L1_ID + 1];
- if (id1 != FW_L1_ID_1 || id2 != FW_L1_ID_2_HICOMX) {
- printk(KERN_ERR "%s: incorrect firmware, load aborted\n", dev->name);
- return -EAGAIN;
- }
-
- printk(KERN_INFO "%s: Loading HICOMX Layer 1 firmware %s\n", dev->name,
- (char *)(fw->data + OFF_FW_L1_ID + 2));
-
- id1 = fw->data[OFF_FW_L2_ID];
- id2 = fw->data[OFF_FW_L2_ID + 1];
- if (id1 == FW_L2_ID_1 && (id2 == 0xc0 || id2 == 0xc1 || id2 == 0xc2)) {
- printk(KERN_INFO "with Layer 2 code %s\n",
- (char *)(fw->data + OFF_FW_L2_ID + 2));
- }
-
- outb_p(board_segment | HICOMX_BOARD_RESET, dev->base_addr);
- udelay(10);
-
- save_flags(flags); cli();
- saved=memory_used[mempos];
- if(saved) {
- ((struct comx_channel *)saved->priv)->HW_board_off(saved);
- }
- memory_used[mempos]=dev;
-
- outb_p(board_segment | HICOMX_ENABLE_BOARD_MEM, dev->base_addr);
- outb_p(HICOMX_PRG_MEM, dev->base_addr + 1);
-
- len = 0;
- HICOMX_address = (word *)dev->mem_start;
- while (fw->len > len) {
- writeb(fw->data[len++], HICOMX_address++);
- }
-
- len = 0;
- HICOMX_address = (word *)dev->mem_start;
- while (len != fw->len && (readw(HICOMX_address++) & 0xff) == fw->data[len]) {
- len++;
- }
-
- if (len != fw->len) {
- printk(KERN_ERR "%s: error loading firmware: [%d] is 0x%02x "
- "instead of 0x%02x\n", dev->name, len,
- readw(HICOMX_address - 1) & 0xff, fw->data[len]);
- retval=-EAGAIN;
- goto out;
- }
-
- outb_p(board_segment | HICOMX_BOARD_RESET, dev->base_addr);
- outb_p(HICOMX_DATA_MEM, dev->base_addr + 1);
-
- outb_p(board_segment | HICOMX_ENABLE_BOARD_MEM, dev->base_addr);
-
- loopcount=0;
- while(loopcount++ < 10000 && COMX_readw(dev, OFF_A_L2_LINKUP) != 1) {
- udelay(100);
- }
-
- if ( COMX_readw(dev, OFF_A_L2_LINKUP) != 1 ) {
- printk(KERN_ERR "%s: error starting firmware, linkup word is %04x\n",
- dev->name, COMX_readw(dev, OFF_A_L2_LINKUP));
- retval=-EAGAIN;
- goto out;
- }
-
- ch->init_status |= FW_LOADED;
- retval=0;
-
-out:
- outb_p(board_segment | HICOMX_DISABLE_ALL, dev->base_addr);
- outb_p(HICOMX_DATA_MEM, dev->base_addr + 1);
-
- if(saved) {
- ((struct comx_channel *)saved->priv)->HW_board_on(saved);
- }
- memory_used[mempos]=saved;
- restore_flags(flags);
- return retval;
-}
-
-static struct net_device *comx_twin_check(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct proc_dir_entry *procfile = ch->procdir->parent->subdir;
- struct comx_privdata *hw = ch->HW_privdata;
-
- struct net_device *twin;
- struct comx_channel *ch_twin;
- struct comx_privdata *hw_twin;
-
-
- for ( ; procfile ; procfile = procfile->next) {
-
- if(!S_ISDIR(procfile->mode)) {
- continue;
- }
-
- twin=procfile->data;
- ch_twin=twin->priv;
- hw_twin=ch_twin->HW_privdata;
-
-
- if (twin != dev && dev->irq && dev->base_addr && dev->mem_start &&
- dev->irq == twin->irq && dev->base_addr == twin->base_addr &&
- dev->mem_start == twin->mem_start &&
- hw->channel == (1 - hw_twin->channel) &&
- ch->hardware == ch_twin->hardware) {
- return twin;
- }
- }
- return NULL;
-}
-
-static int comxhw_write_proc(struct file *file, const char *buffer,
- u_long count, void *data)
-{
- struct proc_dir_entry *entry = (struct proc_dir_entry *)data;
- struct net_device *dev = entry->parent->data;
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw = ch->HW_privdata;
- char *page;
-
-
- if(ch->init_status & HW_OPEN) {
- return -EAGAIN;
- }
-
- if (strcmp(FILENAME_FIRMWARE, entry->name) != 0) {
- if (!(page = (char *)__get_free_page(GFP_KERNEL))) {
- return -ENOMEM;
- }
- if(copy_from_user(page, buffer, count = (min_t(int, count, PAGE_SIZE))))
- {
- count = -EFAULT;
- goto out;
- }
- if (page[count-1] == '\n')
- page[count-1] = '\0';
- else if (count < PAGE_SIZE)
- page[count] = '\0';
- else if (page[count]) {
- count = -EINVAL;
- goto out;
- }
- page[count]=0; /* Null terminate */
- } else {
- byte *tmp;
-
- if (!hw->firmware) {
- if ((hw->firmware = kmalloc(sizeof(struct comx_firmware),
- GFP_KERNEL)) == NULL) {
- return -ENOMEM;
- }
- hw->firmware->len = 0;
- hw->firmware->data = NULL;
- }
-
- if ((tmp = kmalloc(count + file->f_pos, GFP_KERNEL)) == NULL) {
- return -ENOMEM;
- }
-
- /* Ha nem 0 a fpos, akkor meglevo file-t irunk. Gyenge trukk. */
- if (hw->firmware && hw->firmware->len && file->f_pos
- && hw->firmware->len < count + file->f_pos) {
- memcpy(tmp, hw->firmware->data, hw->firmware->len);
- }
- if (hw->firmware->data) {
- kfree(hw->firmware->data);
- }
- if (copy_from_user(tmp + file->f_pos, buffer, count))
- return -EFAULT;
- hw->firmware->len = entry->size = file->f_pos + count;
- hw->firmware->data = tmp;
- file->f_pos += count;
- return count;
- }
-
- if (strcmp(entry->name, FILENAME_CHANNEL) == 0) {
- hw->channel = simple_strtoul(page, NULL, 0);
- if (hw->channel >= MAX_CHANNELNO) {
- printk(KERN_ERR "Invalid channel number\n");
- hw->channel = 0;
- }
- if ((ch->twin = comx_twin_check(dev)) != NULL) {
- struct comx_channel *twin_ch = ch->twin->priv;
- twin_ch->twin = dev;
- }
- } else if (strcmp(entry->name, FILENAME_IRQ) == 0) {
- dev->irq = simple_strtoul(page, NULL, 0);
- if (dev->irq == 2) {
- dev->irq = 9;
- }
- if (dev->irq < 3 || dev->irq > 15) {
- printk(KERN_ERR "comxhw: Invalid irq number\n");
- dev->irq = 0;
- }
- if ((ch->twin = comx_twin_check(dev)) != NULL) {
- struct comx_channel *twin_ch = ch->twin->priv;
- twin_ch->twin = dev;
- }
- } else if (strcmp(entry->name, FILENAME_IO) == 0) {
- dev->base_addr = simple_strtoul(page, NULL, 0);
- if ((dev->base_addr & 3) != 0 || dev->base_addr < 0x300
- || dev->base_addr > 0x3fc) {
- printk(KERN_ERR "Invalid io value\n");
- dev->base_addr = 0;
- }
- if ((ch->twin = comx_twin_check(dev)) != NULL) {
- struct comx_channel *twin_ch = ch->twin->priv;
-
- twin_ch->twin = dev;
- }
- } else if (strcmp(entry->name, FILENAME_MEMADDR) == 0) {
- dev->mem_start = simple_strtoul(page, NULL, 0);
- if (dev->mem_start <= 0xf000 && dev->mem_start >= 0xa000) {
- dev->mem_start *= 16;
- }
- if ((dev->mem_start & 0xfff) != 0 || dev->mem_start < COMX_MEM_MIN
- || dev->mem_start + hw->memory_size > COMX_MEM_MAX) {
- printk(KERN_ERR "Invalid memory page\n");
- dev->mem_start = 0;
- }
- dev->mem_end = dev->mem_start + hw->memory_size;
- if ((ch->twin = comx_twin_check(dev)) != NULL) {
- struct comx_channel *twin_ch = ch->twin->priv;
-
- twin_ch->twin = dev;
- }
- } else if (strcmp(entry->name, FILENAME_CLOCK) == 0) {
- if (strncmp("ext", page, 3) == 0) {
- hw->clock = 0;
- } else {
- int kbps;
-
- kbps = simple_strtoul(page, NULL, 0);
- hw->clock = kbps ? COMX_CLOCK_CONST/kbps : 0;
- }
- }
-out:
- free_page((unsigned long)page);
- return count;
-}
-
-static int comxhw_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct proc_dir_entry *file = (struct proc_dir_entry *)data;
- struct net_device *dev = file->parent->data;
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw = ch->HW_privdata;
- int len = 0;
-
-
- if (strcmp(file->name, FILENAME_IO) == 0) {
- len = sprintf(page, "0x%03x\n", (unsigned int)dev->base_addr);
- } else if (strcmp(file->name, FILENAME_IRQ) == 0) {
- len = sprintf(page, "0x%02x\n", dev->irq == 9 ? 2 : dev->irq);
- } else if (strcmp(file->name, FILENAME_CHANNEL) == 0) {
- len = sprintf(page, "%01d\n", hw->channel);
- } else if (strcmp(file->name, FILENAME_MEMADDR) == 0) {
- len = sprintf(page, "0x%05x\n", (unsigned int)dev->mem_start);
- } else if (strcmp(file->name, FILENAME_TWIN) == 0) {
- len = sprintf(page, "%s\n", ch->twin ? ch->twin->name : "none");
- } else if (strcmp(file->name, FILENAME_CLOCK) == 0) {
- if (hw->clock) {
- len = sprintf(page, "%-8d\n", COMX_CLOCK_CONST/hw->clock);
- } else {
- len = sprintf(page, "external\n");
- }
- } else if (strcmp(file->name, FILENAME_FIRMWARE) == 0) {
- len = min_t(int, FILE_PAGESIZE,
- min_t(int, count,
- hw->firmware ?
- (hw->firmware->len - off) : 0));
- if (len < 0) {
- len = 0;
- }
- *start = hw->firmware ? (hw->firmware->data + off) : NULL;
- if (off + len >= (hw->firmware ? hw->firmware->len : 0) || len == 0) {
- *eof = 1;
- }
- return len;
- }
-
- if (off >= len) {
- *eof = 1;
- return 0;
- }
-
- *start = page + off;
- if (count >= len - off) {
- *eof = 1;
- }
- return min_t(int, count, len - off);
-}
-
-/* Called on echo comx >boardtype */
-static int COMX_init(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw;
- struct proc_dir_entry *new_file;
-
- if ((ch->HW_privdata = kmalloc(sizeof(struct comx_privdata),
- GFP_KERNEL)) == NULL) {
- return -ENOMEM;
- }
- memset(hw = ch->HW_privdata, 0, sizeof(struct comx_privdata));
-
- if (ch->hardware == &comx_hw || ch->hardware == &cmx_hw) {
- hw->memory_size = COMX_MEMORY_SIZE;
- hw->io_extent = COMX_IO_EXTENT;
- dev->base_addr = COMX_DEFAULT_IO;
- dev->irq = COMX_DEFAULT_IRQ;
- dev->mem_start = COMX_DEFAULT_MEMADDR;
- dev->mem_end = COMX_DEFAULT_MEMADDR + COMX_MEMORY_SIZE;
- } else if (ch->hardware == &hicomx_hw) {
- hw->memory_size = HICOMX_MEMORY_SIZE;
- hw->io_extent = HICOMX_IO_EXTENT;
- dev->base_addr = HICOMX_DEFAULT_IO;
- dev->irq = HICOMX_DEFAULT_IRQ;
- dev->mem_start = HICOMX_DEFAULT_MEMADDR;
- dev->mem_end = HICOMX_DEFAULT_MEMADDR + HICOMX_MEMORY_SIZE;
- } else {
- printk(KERN_ERR "SERIOUS INTERNAL ERROR in %s, line %d\n", __FILE__, __LINE__);
- }
-
- if ((new_file = create_proc_entry(FILENAME_IO, S_IFREG | 0644, ch->procdir))
- == NULL) {
- goto cleanup_HW_privdata;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &comxhw_read_proc;
- new_file->write_proc = &comxhw_write_proc;
- new_file->size = 6;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_IRQ, S_IFREG | 0644, ch->procdir))
- == NULL) {
- goto cleanup_filename_io;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &comxhw_read_proc;
- new_file->write_proc = &comxhw_write_proc;
- new_file->size = 5;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_CHANNEL, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_filename_irq;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &comxhw_read_proc;
- new_file->write_proc = &comxhw_write_proc;
- new_file->size = 2; // Ezt tudjuk
- new_file->nlink = 1;
-
- if (ch->hardware == &hicomx_hw || ch->hardware == &cmx_hw) {
- if ((new_file = create_proc_entry(FILENAME_CLOCK, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_filename_channel;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &comxhw_read_proc;
- new_file->write_proc = &comxhw_write_proc;
- new_file->size = 9;
- new_file->nlink = 1;
- }
-
- if ((new_file = create_proc_entry(FILENAME_MEMADDR, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_filename_clock;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &comxhw_read_proc;
- new_file->write_proc = &comxhw_write_proc;
- new_file->size = 8;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_TWIN, S_IFREG | 0444,
- ch->procdir)) == NULL) {
- goto cleanup_filename_memaddr;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &comxhw_read_proc;
- new_file->write_proc = NULL;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_FIRMWARE, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_filename_twin;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &comxhw_read_proc;
- new_file->write_proc = &comxhw_write_proc;
- new_file->nlink = 1;
-
- if (ch->hardware == &comx_hw) {
- ch->HW_board_on = COMX_board_on;
- ch->HW_board_off = COMX_board_off;
- ch->HW_load_board = COMX_load_board;
- } else if (ch->hardware == &cmx_hw) {
- ch->HW_board_on = COMX_board_on;
- ch->HW_board_off = COMX_board_off;
- ch->HW_load_board = CMX_load_board;
- ch->HW_set_clock = COMX_set_clock;
- } else if (ch->hardware == &hicomx_hw) {
- ch->HW_board_on = HICOMX_board_on;
- ch->HW_board_off = HICOMX_board_off;
- ch->HW_load_board = HICOMX_load_board;
- ch->HW_set_clock = COMX_set_clock;
- } else {
- printk(KERN_ERR "SERIOUS INTERNAL ERROR in %s, line %d\n", __FILE__, __LINE__);
- }
-
- ch->HW_access_board = COMX_access_board;
- ch->HW_release_board = COMX_release_board;
- ch->HW_txe = COMX_txe;
- ch->HW_open = COMX_open;
- ch->HW_close = COMX_close;
- ch->HW_send_packet = COMX_send_packet;
- ch->HW_statistics = COMX_statistics;
-
- if ((ch->twin = comx_twin_check(dev)) != NULL) {
- struct comx_channel *twin_ch = ch->twin->priv;
-
- twin_ch->twin = dev;
- }
-
- MOD_INC_USE_COUNT;
- return 0;
-
-cleanup_filename_twin:
- remove_proc_entry(FILENAME_TWIN, ch->procdir);
-cleanup_filename_memaddr:
- remove_proc_entry(FILENAME_MEMADDR, ch->procdir);
-cleanup_filename_clock:
- if (ch->hardware == &hicomx_hw || ch->hardware == &cmx_hw)
- remove_proc_entry(FILENAME_CLOCK, ch->procdir);
-cleanup_filename_channel:
- remove_proc_entry(FILENAME_CHANNEL, ch->procdir);
-cleanup_filename_irq:
- remove_proc_entry(FILENAME_IRQ, ch->procdir);
-cleanup_filename_io:
- remove_proc_entry(FILENAME_IO, ch->procdir);
-cleanup_HW_privdata:
- kfree(ch->HW_privdata);
- return -EIO;
-}
-
-/* Called on echo valami >boardtype */
-static int COMX_exit(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct comx_privdata *hw = ch->HW_privdata;
-
- if (hw->firmware) {
- if (hw->firmware->data) kfree(hw->firmware->data);
- kfree(hw->firmware);
- } if (ch->twin) {
- struct comx_channel *twin_ch = ch->twin->priv;
-
- twin_ch->twin = NULL;
- }
-
- kfree(ch->HW_privdata);
- remove_proc_entry(FILENAME_IO, ch->procdir);
- remove_proc_entry(FILENAME_IRQ, ch->procdir);
- remove_proc_entry(FILENAME_CHANNEL, ch->procdir);
- remove_proc_entry(FILENAME_MEMADDR, ch->procdir);
- remove_proc_entry(FILENAME_FIRMWARE, ch->procdir);
- remove_proc_entry(FILENAME_TWIN, ch->procdir);
- if (ch->hardware == &hicomx_hw || ch->hardware == &cmx_hw) {
- remove_proc_entry(FILENAME_CLOCK, ch->procdir);
- }
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static int COMX_dump(struct net_device *dev)
-{
- printk(KERN_INFO "%s: COMX_dump called, why ?\n", dev->name);
- return 0;
-}
-
-static struct comx_hardware comx_hw = {
- "comx",
- VERSION,
- COMX_init,
- COMX_exit,
- COMX_dump,
- NULL
-};
-
-static struct comx_hardware cmx_hw = {
- "cmx",
- VERSION,
- COMX_init,
- COMX_exit,
- COMX_dump,
- NULL
-};
-
-static struct comx_hardware hicomx_hw = {
- "hicomx",
- VERSION,
- COMX_init,
- COMX_exit,
- COMX_dump,
- NULL
-};
-
-static int __init comx_hw_comx_init(void)
-{
- comx_register_hardware(&comx_hw);
- comx_register_hardware(&cmx_hw);
- comx_register_hardware(&hicomx_hw);
- return 0;
-}
-
-static void __exit comx_hw_comx_exit(void)
-{
- comx_unregister_hardware("comx");
- comx_unregister_hardware("cmx");
- comx_unregister_hardware("hicomx");
-}
-
-module_init(comx_hw_comx_init);
-module_exit(comx_hw_comx_exit);
===== drivers/net/wan/comx-hw-locomx.c 1.10 vs edited =====
--- 1.10/drivers/net/wan/comx-hw-locomx.c Wed Mar 3 18:42:59 2004
+++ edited/drivers/net/wan/comx-hw-locomx.c Fri May 7 13:05:52 2004
@@ -1,496 +1 @@
-/*
- * Hardware driver for the LoCOMX card, using the generic z85230
- * functions
- *
- * Author: Gergely Madarasz <gorgo@itc.hu>
- *
- * Based on skeleton code and old LoCOMX driver by Tivadar Szemethy <tiv@itc.hu>
- * and the hostess_sv11 driver
- *
- * Contributors:
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br> (0.14)
- *
- * Copyright (C) 1999 ITConsult-Pro Co. <info@itc.hu>
- *
- * 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.
- *
- * Version 0.10 (99/06/17):
- * - rewritten for the z85230 layer
- *
- * Version 0.11 (99/06/21):
- * - some printk's fixed
- * - get rid of a memory leak (it was impossible though :))
- *
- * Version 0.12 (99/07/07):
- * - check CTS for modem lines, not DCD (which is always high
- * in case of this board)
- * Version 0.13 (99/07/08):
- * - Fix the transmitter status check
- * - Handle the net device statistics better
- * Version 0.14 (00/08/15):
- * - resource release on failure at LOCOMX_init
- */
-#define VERSION "0.14"
-
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-
-#include <asm/types.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include "comx.h"
-#include "z85230.h"
-
-MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>");
-MODULE_DESCRIPTION("Hardware driver for the LoCOMX board");
-MODULE_LICENSE("GPL");
-
-#define RX_DMA 3
-#define TX_DMA 1
-#define LOCOMX_ID 0x33
-#define LOCOMX_IO_EXTENT 8
-#define LOCOMX_DEFAULT_IO 0x368
-#define LOCOMX_DEFAULT_IRQ 7
-
-u8 z8530_locomx[] = {
- 11, TCRTxCP,
- 14, DTRREQ,
- 255
-};
-
-struct locomx_data {
- int io_extent;
- struct z8530_dev board;
- struct timer_list status_timer;
-};
-
-static int LOCOMX_txe(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct locomx_data *hw = ch->HW_privdata;
-
- return (!hw->board.chanA.tx_next_skb);
-}
-
-
-static void locomx_rx(struct z8530_channel *c, struct sk_buff *skb)
-{
- struct net_device *dev = c->netdevice;
- struct comx_channel *ch = netdev_priv(dev);
-
- if (ch->debug_flags & DEBUG_HW_RX) {
- comx_debug_skb(dev, skb, "locomx_rx receiving");
- }
- ch->LINE_rx(dev,skb);
-}
-
-static int LOCOMX_send_packet(struct net_device *dev, struct sk_buff *skb)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct locomx_data *hw = ch->HW_privdata;
-
- if (ch->debug_flags & DEBUG_HW_TX) {
- comx_debug_bytes(dev, skb->data, skb->len, "LOCOMX_send_packet");
- }
-
- if (!(ch->line_status & LINE_UP)) {
- return FRAME_DROPPED;
- }
-
- if(z8530_queue_xmit(&hw->board.chanA,skb)) {
- printk(KERN_WARNING "%s: FRAME_DROPPED\n",dev->name);
- return FRAME_DROPPED;
- }
-
- if (ch->debug_flags & DEBUG_HW_TX) {
- comx_debug(dev, "%s: LOCOMX_send_packet was successful\n\n", dev->name);
- }
-
- if(!hw->board.chanA.tx_next_skb) {
- return FRAME_QUEUED;
- } else {
- return FRAME_ACCEPTED;
- }
-}
-
-static void locomx_status_timerfun(unsigned long d)
-{
- struct net_device *dev = (struct net_device *)d;
- struct comx_channel *ch = netdev_priv(dev);
- struct locomx_data *hw = ch->HW_privdata;
-
- if(!(ch->line_status & LINE_UP) &&
- (hw->board.chanA.status & CTS)) {
- ch->LINE_status(dev, ch->line_status | LINE_UP);
- }
- if((ch->line_status & LINE_UP) &&
- !(hw->board.chanA.status & CTS)) {
- ch->LINE_status(dev, ch->line_status & ~LINE_UP);
- }
- mod_timer(&hw->status_timer,jiffies + ch->lineup_delay * HZ);
-}
-
-
-static int LOCOMX_open(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct locomx_data *hw = ch->HW_privdata;
- struct proc_dir_entry *procfile = ch->procdir->subdir;
- unsigned long flags;
- int ret;
-
- if (!dev->base_addr || !dev->irq) {
- return -ENODEV;
- }
-
- if (!request_region(dev->base_addr, hw->io_extent, dev->name)) {
- return -EAGAIN;
- }
-
- hw->board.chanA.ctrlio=dev->base_addr + 5;
- hw->board.chanA.dataio=dev->base_addr + 7;
-
- hw->board.irq=dev->irq;
- hw->board.chanA.netdevice=dev;
- hw->board.chanA.dev=&hw->board;
- hw->board.name=dev->name;
- hw->board.chanA.txdma=TX_DMA;
- hw->board.chanA.rxdma=RX_DMA;
- hw->board.chanA.irqs=&z8530_nop;
- hw->board.chanB.irqs=&z8530_nop;
-
- if(request_irq(dev->irq, z8530_interrupt, SA_INTERRUPT,
- dev->name, &hw->board)) {
- printk(KERN_ERR "%s: unable to obtain irq %d\n", dev->name,
- dev->irq);
- ret=-EAGAIN;
- goto irq_fail;
- }
- if(request_dma(TX_DMA,"LoCOMX (TX)")) {
- printk(KERN_ERR "%s: unable to obtain TX DMA (DMA channel %d)\n",
- dev->name, TX_DMA);
- ret=-EAGAIN;
- goto dma1_fail;
- }
-
- if(request_dma(RX_DMA,"LoCOMX (RX)")) {
- printk(KERN_ERR "%s: unable to obtain RX DMA (DMA channel %d)\n",
- dev->name, RX_DMA);
- ret=-EAGAIN;
- goto dma2_fail;
- }
-
- save_flags(flags);
- cli();
-
- if(z8530_init(&hw->board)!=0)
- {
- printk(KERN_ERR "%s: Z8530 device not found.\n",dev->name);
- ret=-ENODEV;
- goto z8530_fail;
- }
-
- hw->board.chanA.dcdcheck=CTS;
-
- z8530_channel_load(&hw->board.chanA, z8530_hdlc_kilostream_85230);
- z8530_channel_load(&hw->board.chanA, z8530_locomx);
- z8530_channel_load(&hw->board.chanB, z8530_dead_port);
-
- z8530_describe(&hw->board, "I/O", dev->base_addr);
-
- if((ret=z8530_sync_dma_open(dev, &hw->board.chanA))!=0) {
- goto z8530_fail;
- }
-
- restore_flags(flags);
-
-
- hw->board.active=1;
- hw->board.chanA.rx_function=locomx_rx;
-
- ch->init_status |= HW_OPEN;
- if (hw->board.chanA.status & DCD) {
- ch->line_status |= LINE_UP;
- } else {
- ch->line_status &= ~LINE_UP;
- }
-
- comx_status(dev, ch->line_status);
-
- init_timer(&hw->status_timer);
- hw->status_timer.function=locomx_status_timerfun;
- hw->status_timer.data=(unsigned long)dev;
- hw->status_timer.expires=jiffies + ch->lineup_delay * HZ;
- add_timer(&hw->status_timer);
-
- for (; procfile ; procfile = procfile->next) {
- if (strcmp(procfile->name, FILENAME_IO) == 0 ||
- strcmp(procfile->name, FILENAME_IRQ) == 0) {
- procfile->mode = S_IFREG | 0444;
- }
- }
- return 0;
-
-z8530_fail:
- restore_flags(flags);
- free_dma(RX_DMA);
-dma2_fail:
- free_dma(TX_DMA);
-dma1_fail:
- free_irq(dev->irq, &hw->board);
-irq_fail:
- release_region(dev->base_addr, hw->io_extent);
- return ret;
-}
-
-static int LOCOMX_close(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct locomx_data *hw = ch->HW_privdata;
- struct proc_dir_entry *procfile = ch->procdir->subdir;
-
- hw->board.chanA.rx_function=z8530_null_rx;
- netif_stop_queue(dev);
- z8530_sync_dma_close(dev, &hw->board.chanA);
-
- z8530_shutdown(&hw->board);
-
- del_timer(&hw->status_timer);
- free_dma(RX_DMA);
- free_dma(TX_DMA);
- free_irq(dev->irq,&hw->board);
- release_region(dev->base_addr,8);
-
- for (; procfile ; procfile = procfile->next) {
- if (strcmp(procfile->name, FILENAME_IO) == 0 ||
- strcmp(procfile->name, FILENAME_IRQ) == 0) {
- procfile->mode = S_IFREG | 0644;
- }
- }
-
- ch->init_status &= ~HW_OPEN;
- return 0;
-}
-
-static int LOCOMX_statistics(struct net_device *dev,char *page)
-{
- int len = 0;
-
- len += sprintf(page + len, "Hello\n");
-
- return len;
-}
-
-static int LOCOMX_dump(struct net_device *dev) {
- printk(KERN_INFO "LOCOMX_dump called\n");
- return(-1);
-}
-
-static int locomx_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct proc_dir_entry *file = (struct proc_dir_entry *)data;
- struct net_device *dev = file->parent->data;
- int len = 0;
-
- if (strcmp(file->name, FILENAME_IO) == 0) {
- len = sprintf(page, "0x%x\n", (unsigned int)dev->base_addr);
- } else if (strcmp(file->name, FILENAME_IRQ) == 0) {
- len = sprintf(page, "%d\n", (unsigned int)dev->irq);
- } else {
- printk(KERN_ERR "hw_read_proc: internal error, filename %s\n",
- file->name);
- return -EBADF;
- }
-
- if (off >= len) {
- *eof = 1;
- return 0;
- }
-
- *start = page + off;
- if (count >= len - off) {
- *eof = 1;
- }
- return min_t(int, count, len - off);
-}
-
-static int locomx_write_proc(struct file *file, const char *buffer,
- u_long count, void *data)
-{
- struct proc_dir_entry *entry = (struct proc_dir_entry *)data;
- struct net_device *dev = (struct net_device *)entry->parent->data;
- int val;
- char *page;
-
- if (!(page = (char *)__get_free_page(GFP_KERNEL))) {
- return -ENOMEM;
- }
-
- if (copy_from_user(page, buffer, count = min_t(unsigned long, count, PAGE_SIZE))) {
- free_page((unsigned long)page);
- return -EBADF;
- }
- if (*(page + count - 1) == '\n') {
- *(page + count - 1) = 0;
- }
-
- if (strcmp(entry->name, FILENAME_IO) == 0) {
- val = simple_strtoul(page, NULL, 0);
- if (val != 0x360 && val != 0x368 && val != 0x370 &&
- val != 0x378) {
- printk(KERN_ERR "LoCOMX: incorrect io address!\n");
- } else {
- dev->base_addr = val;
- }
- } else if (strcmp(entry->name, FILENAME_IRQ) == 0) {
- val = simple_strtoul(page, NULL, 0);
- if (val != 3 && val != 4 && val != 5 && val != 6 && val != 7) {
- printk(KERN_ERR "LoCOMX: incorrect irq value!\n");
- } else {
- dev->irq = val;
- }
- } else {
- printk(KERN_ERR "locomx_write_proc: internal error, filename %s\n",
- entry->name);
- free_page((unsigned long)page);
- return -EBADF;
- }
-
- free_page((unsigned long)page);
- return count;
-}
-
-
-
-static int LOCOMX_init(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct locomx_data *hw;
- struct proc_dir_entry *new_file;
-
- /* Alloc data for private structure */
- if ((ch->HW_privdata = kmalloc(sizeof(struct locomx_data),
- GFP_KERNEL)) == NULL) {
- return -ENOMEM;
- }
-
- memset(hw = ch->HW_privdata, 0, sizeof(struct locomx_data));
- hw->io_extent = LOCOMX_IO_EXTENT;
-
- /* Register /proc files */
- if ((new_file = create_proc_entry(FILENAME_IO, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_HW_privdata;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &locomx_read_proc;
- new_file->write_proc = &locomx_write_proc;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_IRQ, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_filename_io;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &locomx_read_proc;
- new_file->write_proc = &locomx_write_proc;
- new_file->nlink = 1;
-
-/* No clock yet */
-/*
- if ((new_file = create_proc_entry(FILENAME_CLOCK, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- return -EIO;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &locomx_read_proc;
- new_file->write_proc = &locomx_write_proc;
- new_file->nlink = 1;
-*/
-
- ch->HW_access_board = NULL;
- ch->HW_release_board = NULL;
- ch->HW_txe = LOCOMX_txe;
- ch->HW_open = LOCOMX_open;
- ch->HW_close = LOCOMX_close;
- ch->HW_send_packet = LOCOMX_send_packet;
- ch->HW_statistics = LOCOMX_statistics;
- ch->HW_set_clock = NULL;
-
- ch->current_stats = &hw->board.chanA.stats;
- memcpy(ch->current_stats, &ch->stats, sizeof(struct net_device_stats));
-
- dev->base_addr = LOCOMX_DEFAULT_IO;
- dev->irq = LOCOMX_DEFAULT_IRQ;
-
-
- /* O.K. Count one more user on this module */
- MOD_INC_USE_COUNT;
- return 0;
-cleanup_filename_io:
- remove_proc_entry(FILENAME_IO, ch->procdir);
-cleanup_HW_privdata:
- kfree(ch->HW_privdata);
- return -EIO;
-}
-
-
-static int LOCOMX_exit(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
-
- ch->HW_access_board = NULL;
- ch->HW_release_board = NULL;
- ch->HW_txe = NULL;
- ch->HW_open = NULL;
- ch->HW_close = NULL;
- ch->HW_send_packet = NULL;
- ch->HW_statistics = NULL;
- ch->HW_set_clock = NULL;
- memcpy(&ch->stats, ch->current_stats, sizeof(struct net_device_stats));
- ch->current_stats = &ch->stats;
-
- kfree(ch->HW_privdata);
-
- remove_proc_entry(FILENAME_IO, ch->procdir);
- remove_proc_entry(FILENAME_IRQ, ch->procdir);
-// remove_proc_entry(FILENAME_CLOCK, ch->procdir);
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static struct comx_hardware locomx_hw = {
- "locomx",
- VERSION,
- LOCOMX_init,
- LOCOMX_exit,
- LOCOMX_dump,
- NULL
-};
-
-static int __init comx_hw_locomx_init(void)
-{
- comx_register_hardware(&locomx_hw);
- return 0;
-}
-
-static void __exit comx_hw_locomx_exit(void)
-{
- comx_unregister_hardware("locomx");
-}
-
-module_init(comx_hw_locomx_init);
-module_exit(comx_hw_locomx_exit);
===== drivers/net/wan/comx-hw-mixcom.c 1.12 vs edited =====
--- 1.12/drivers/net/wan/comx-hw-mixcom.c Thu Sep 11 19:40:53 2003
+++ edited/drivers/net/wan/comx-hw-mixcom.c Fri May 7 13:05:52 2004
@@ -1,960 +1 @@
-/*
- * Hardware driver for the MixCom synchronous serial board
- *
- * Author: Gergely Madarasz <gorgo@itc.hu>
- *
- * based on skeleton driver code and a preliminary hscx driver by
- * Tivadar Szemethy <tiv@itc.hu>
- *
- * Copyright (C) 1998-1999 ITConsult-Pro Co. <info@itc.hu>
- *
- * Contributors:
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br> (0.65)
- *
- * 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.
- *
- * Version 0.60 (99/06/11):
- * - ported to the kernel, now works as builtin code
- *
- * Version 0.61 (99/06/11):
- * - recognize the one-channel MixCOM card (id byte = 0x13)
- * - printk fixes
- *
- * Version 0.62 (99/07/15):
- * - fixes according to the new hw docs
- * - report line status when open
- *
- * Version 0.63 (99/09/21):
- * - line status report fixes
- *
- * Version 0.64 (99/12/01):
- * - some more cosmetical fixes
- *
- * Version 0.65 (00/08/15)
- * - resource release on failure at MIXCOM_init
- */
-#define VERSION "0.65"
-
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-
-#include <asm/types.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#include "comx.h"
-#include "mixcom.h"
-#include "hscx.h"
-
-MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>");
-MODULE_DESCRIPTION("Hardware-level driver for the serial port of the MixCom board");
-MODULE_LICENSE("GPL");
-
-#define MIXCOM_DATA(d) ((struct mixcom_privdata *)(COMX_CHANNEL(d)-> \
- HW_privdata))
-
-#define MIXCOM_BOARD_BASE(d) (d->base_addr - MIXCOM_SERIAL_OFFSET - \
- (1 - MIXCOM_DATA(d)->channel) * MIXCOM_CHANNEL_OFFSET)
-
-#define MIXCOM_DEV_BASE(port,channel) (port + MIXCOM_SERIAL_OFFSET + \
- (1 - channel) * MIXCOM_CHANNEL_OFFSET)
-
-/* Values used to set the IRQ line */
-static unsigned char mixcom_set_irq[]={0xFF, 0xFF, 0xFF, 0x0, 0xFF, 0x2, 0x4, 0x6, 0xFF, 0xFF, 0x8, 0xA, 0xC, 0xFF, 0xE, 0xFF};
-
-static unsigned char* hscx_versions[]={"A1", NULL, "A2", NULL, "A3", "2.1"};
-
-struct mixcom_privdata {
- u16 clock;
- char channel;
- long txbusy;
- struct sk_buff *sending;
- unsigned tx_ptr;
- struct sk_buff *recving;
- unsigned rx_ptr;
- unsigned char status;
- char card_has_status;
-};
-
-static inline void wr_hscx(struct net_device *dev, int reg, unsigned char val)
-{
- outb(val, dev->base_addr + reg);
-}
-
-static inline unsigned char rd_hscx(struct net_device *dev, int reg)
-{
- return inb(dev->base_addr + reg);
-}
-
-static inline void hscx_cmd(struct net_device *dev, int cmd)
-{
- unsigned long jiffs = jiffies;
- unsigned char cec;
- unsigned delay = 0;
-
- while ((cec = (rd_hscx(dev, HSCX_STAR) & HSCX_CEC) != 0) &&
- time_before(jiffies, jiffs + HZ)) {
- udelay(1);
- if (++delay > (100000 / HZ)) break;
- }
- if (cec) {
- printk(KERN_WARNING "%s: CEC stuck, probably no clock!\n",dev->name);
- } else {
- wr_hscx(dev, HSCX_CMDR, cmd);
- }
-}
-
-static inline void hscx_fill_fifo(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct mixcom_privdata *hw = ch->HW_privdata;
- register word to_send = hw->sending->len - hw->tx_ptr;
-
-
- outsb(dev->base_addr + HSCX_FIFO,
- &(hw->sending->data[hw->tx_ptr]), min_t(unsigned int, to_send, 32));
- if (to_send <= 32) {
- hscx_cmd(dev, HSCX_XTF | HSCX_XME);
- kfree_skb(hw->sending);
- hw->sending = NULL;
- hw->tx_ptr = 0;
- } else {
- hscx_cmd(dev, HSCX_XTF);
- hw->tx_ptr += 32;
- }
-}
-
-static inline void hscx_empty_fifo(struct net_device *dev, int cnt)
-{
- struct comx_channel *ch = dev->priv;
- struct mixcom_privdata *hw = ch->HW_privdata;
-
- if (hw->recving == NULL) {
- if (!(hw->recving = dev_alloc_skb(HSCX_MTU + 16))) {
- ch->stats.rx_dropped++;
- hscx_cmd(dev, HSCX_RHR);
- } else {
- skb_reserve(hw->recving, 16);
- skb_put(hw->recving, HSCX_MTU);
- }
- hw->rx_ptr = 0;
- }
- if (cnt > 32 || !cnt || hw->recving == NULL) {
- printk(KERN_ERR "hscx_empty_fifo: cnt is %d, hw->recving %p\n",
- cnt, (void *)hw->recving);
- return;
- }
-
- insb(dev->base_addr + HSCX_FIFO, &(hw->recving->data[hw->rx_ptr]),cnt);
- hw->rx_ptr += cnt;
- hscx_cmd(dev, HSCX_RMC);
-}
-
-
-static int MIXCOM_txe(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct mixcom_privdata *hw = ch->HW_privdata;
-
- return !test_bit(0, &hw->txbusy);
-}
-
-static int mixcom_probe(struct net_device *dev)
-{
- unsigned long flags;
- int id, vstr, ret=0;
-
- save_flags(flags); cli();
-
- id=inb_p(MIXCOM_BOARD_BASE(dev) + MIXCOM_ID_OFFSET) & 0x7f;
-
- if (id != MIXCOM_ID ) {
- ret=-ENODEV;
- printk(KERN_WARNING "%s: no MixCOM board found at 0x%04lx\n",dev->name, dev->base_addr);
- goto out;
- }
-
- vstr=inb_p(dev->base_addr + HSCX_VSTR) & 0x0f;
- if(vstr>=sizeof(hscx_versions)/sizeof(char*) ||
- hscx_versions[vstr]==NULL) {
- printk(KERN_WARNING "%s: board found but no HSCX chip detected at 0x%4lx (vstr = 0x%1x)\n",dev->name,dev->base_addr,vstr);
- ret = -ENODEV;
- } else {
- printk(KERN_INFO "%s: HSCX chip version %s\n",dev->name,hscx_versions[vstr]);
- ret = 0;
- }
-
-out:
-
- restore_flags(flags);
- return ret;
-}
-
-#if 0
-static void MIXCOM_set_clock(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct mixcom_privdata *hw = ch->HW_privdata;
-
- if (hw->clock) {
- ;
- } else {
- ;
- }
-}
-#endif
-
-static void mixcom_board_on(struct net_device *dev)
-{
- outb_p(MIXCOM_OFF , MIXCOM_BOARD_BASE(dev) + MIXCOM_IT_OFFSET);
- udelay(1000);
- outb_p(mixcom_set_irq[dev->irq] | MIXCOM_ON,
- MIXCOM_BOARD_BASE(dev) + MIXCOM_IT_OFFSET);
- udelay(1000);
-}
-
-static void mixcom_board_off(struct net_device *dev)
-{
- outb_p(MIXCOM_OFF , MIXCOM_BOARD_BASE(dev) + MIXCOM_IT_OFFSET);
- udelay(1000);
-}
-
-static void mixcom_off(struct net_device *dev)
-{
- wr_hscx(dev, HSCX_CCR1, 0x0);
-}
-
-static void mixcom_on(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
-
- wr_hscx(dev, HSCX_CCR1, HSCX_PU | HSCX_ODS | HSCX_ITF); // power up, push-pull
- wr_hscx(dev, HSCX_CCR2, HSCX_CIE /* | HSCX_RIE */ );
- wr_hscx(dev, HSCX_MODE, HSCX_TRANS | HSCX_ADM8 | HSCX_RAC | HSCX_RTS );
- wr_hscx(dev, HSCX_RLCR, HSCX_RC | 47); // 1504 bytes
- wr_hscx(dev, HSCX_MASK, HSCX_RSC | HSCX_TIN );
- hscx_cmd(dev, HSCX_XRES | HSCX_RHR);
-
- if (ch->HW_set_clock) ch->HW_set_clock(dev);
-
-}
-
-static int MIXCOM_send_packet(struct net_device *dev, struct sk_buff *skb)
-{
- struct comx_channel *ch = dev->priv;
- struct mixcom_privdata *hw = ch->HW_privdata;
- unsigned long flags;
-
- if (ch->debug_flags & DEBUG_HW_TX) {
- comx_debug_bytes(dev, skb->data, skb->len, "MIXCOM_send_packet");
- }
-
- if (!(ch->line_status & LINE_UP)) {
- return FRAME_DROPPED;
- }
-
- if (skb->len > HSCX_MTU) {
- ch->stats.tx_errors++;
- return FRAME_ERROR;
- }
-
- save_flags(flags); cli();
-
- if (test_and_set_bit(0, &hw->txbusy)) {
- printk(KERN_ERR "%s: transmitter called while busy... dropping frame (length %d)\n", dev->name, skb->len);
- restore_flags(flags);
- return FRAME_DROPPED;
- }
-
-
- hw->sending = skb;
- hw->tx_ptr = 0;
- hw->txbusy = 1;
-// atomic_inc(&skb->users); // save it
- hscx_fill_fifo(dev);
- restore_flags(flags);
-
- ch->stats.tx_packets++;
- ch->stats.tx_bytes += skb->len;
-
- if (ch->debug_flags & DEBUG_HW_TX) {
- comx_debug(dev, "MIXCOM_send_packet was successful\n\n");
- }
-
- return FRAME_ACCEPTED;
-}
-
-static inline void mixcom_receive_frame(struct net_device *dev)
-{
- struct comx_channel *ch=dev->priv;
- struct mixcom_privdata *hw=ch->HW_privdata;
- register byte rsta;
- register word length;
-
- rsta = rd_hscx(dev, HSCX_RSTA) & (HSCX_VFR | HSCX_RDO |
- HSCX_CRC | HSCX_RAB);
- length = ((rd_hscx(dev, HSCX_RBCH) & 0x0f) << 8) |
- rd_hscx(dev, HSCX_RBCL);
-
- if ( length > hw->rx_ptr ) {
- hscx_empty_fifo(dev, length - hw->rx_ptr);
- }
-
- if (!(rsta & HSCX_VFR)) {
- ch->stats.rx_length_errors++;
- }
- if (rsta & HSCX_RDO) {
- ch->stats.rx_over_errors++;
- }
- if (!(rsta & HSCX_CRC)) {
- ch->stats.rx_crc_errors++;
- }
- if (rsta & HSCX_RAB) {
- ch->stats.rx_frame_errors++;
- }
- ch->stats.rx_packets++;
- ch->stats.rx_bytes += length;
-
- if (rsta == (HSCX_VFR | HSCX_CRC) && hw->recving) {
- skb_trim(hw->recving, hw->rx_ptr - 1);
- if (ch->debug_flags & DEBUG_HW_RX) {
- comx_debug_skb(dev, hw->recving,
- "MIXCOM_interrupt receiving");
- }
- hw->recving->dev = dev;
- if (ch->LINE_rx) {
- ch->LINE_rx(dev, hw->recving);
- }
- }
- else if(hw->recving) {
- kfree_skb(hw->recving);
- }
- hw->recving = NULL;
- hw->rx_ptr = 0;
-}
-
-
-static inline void mixcom_extended_interrupt(struct net_device *dev)
-{
- struct comx_channel *ch=dev->priv;
- struct mixcom_privdata *hw=ch->HW_privdata;
- register byte exir;
-
- exir = rd_hscx(dev, HSCX_EXIR) & (HSCX_XDU | HSCX_RFO | HSCX_CSC );
-
- if (exir & HSCX_RFO) {
- ch->stats.rx_over_errors++;
- if (hw->rx_ptr) {
- kfree_skb(hw->recving);
- hw->recving = NULL; hw->rx_ptr = 0;
- }
- printk(KERN_ERR "MIXCOM: rx overrun\n");
- hscx_cmd(dev, HSCX_RHR);
- }
-
- if (exir & HSCX_XDU) { // xmit underrun
- ch->stats.tx_errors++;
- ch->stats.tx_aborted_errors++;
- if (hw->tx_ptr) {
- kfree_skb(hw->sending);
- hw->sending = NULL;
- hw->tx_ptr = 0;
- }
- hscx_cmd(dev, HSCX_XRES);
- clear_bit(0, &hw->txbusy);
- if (ch->LINE_tx) {
- ch->LINE_tx(dev);
- }
- printk(KERN_ERR "MIXCOM: tx underrun\n");
- }
-
- if (exir & HSCX_CSC) {
- ch->stats.tx_carrier_errors++;
- if ((rd_hscx(dev, HSCX_STAR) & HSCX_CTS) == 0) { // Vonal le
- if (test_and_clear_bit(0, &ch->lineup_pending)) {
- del_timer(&ch->lineup_timer);
- } else if (ch->line_status & LINE_UP) {
- ch->line_status &= ~LINE_UP;
- if (ch->LINE_status) {
- ch->LINE_status(dev,ch->line_status);
- }
- }
- }
- if (!(ch->line_status & LINE_UP) && (rd_hscx(dev, HSCX_STAR) &
- HSCX_CTS)) { // Vonal fol
- if (!test_and_set_bit(0,&ch->lineup_pending)) {
- ch->lineup_timer.function = comx_lineup_func;
- ch->lineup_timer.data = (unsigned long)dev;
- ch->lineup_timer.expires = jiffies + HZ *
- ch->lineup_delay;
- add_timer(&ch->lineup_timer);
- hscx_cmd(dev, HSCX_XRES);
- clear_bit(0, &hw->txbusy);
- if (hw->sending) {
- kfree_skb(hw->sending);
- }
- hw->sending=NULL;
- hw->tx_ptr = 0;
- }
- }
- }
-}
-
-
-static irqreturn_t MIXCOM_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned long flags;
- struct net_device *dev = (struct net_device *)dev_id;
- struct comx_channel *ch, *twin_ch;
- struct mixcom_privdata *hw, *twin_hw;
- register unsigned char ista;
-
- if (dev==NULL) {
- printk(KERN_ERR "comx_interrupt: irq %d for unknown device\n",irq);
- return IRQ_NONE;
- }
-
- ch = dev->priv;
- hw = ch->HW_privdata;
-
- save_flags(flags); cli();
-
- while((ista = (rd_hscx(dev, HSCX_ISTA) & (HSCX_RME | HSCX_RPF |
- HSCX_XPR | HSCX_EXB | HSCX_EXA | HSCX_ICA)))) {
- register byte ista2 = 0;
-
- if (ista & HSCX_RME) {
- mixcom_receive_frame(dev);
- }
- if (ista & HSCX_RPF) {
- hscx_empty_fifo(dev, 32);
- }
- if (ista & HSCX_XPR) {
- if (hw->tx_ptr) {
- hscx_fill_fifo(dev);
- } else {
- clear_bit(0, &hw->txbusy);
- ch->LINE_tx(dev);
- }
- }
-
- if (ista & HSCX_EXB) {
- mixcom_extended_interrupt(dev);
- }
-
- if ((ista & HSCX_EXA) && ch->twin) {
- mixcom_extended_interrupt(ch->twin);
- }
-
- if ((ista & HSCX_ICA) && ch->twin &&
- (ista2 = rd_hscx(ch->twin, HSCX_ISTA) &
- (HSCX_RME | HSCX_RPF | HSCX_XPR ))) {
- if (ista2 & HSCX_RME) {
- mixcom_receive_frame(ch->twin);
- }
- if (ista2 & HSCX_RPF) {
- hscx_empty_fifo(ch->twin, 32);
- }
- if (ista2 & HSCX_XPR) {
- twin_ch=ch->twin->priv;
- twin_hw=twin_ch->HW_privdata;
- if (twin_hw->tx_ptr) {
- hscx_fill_fifo(ch->twin);
- } else {
- clear_bit(0, &twin_hw->txbusy);
- ch->LINE_tx(ch->twin);
- }
- }
- }
- }
-
- restore_flags(flags);
- return IRQ_HANDLED;
-}
-
-static int MIXCOM_open(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct mixcom_privdata *hw = ch->HW_privdata;
- struct proc_dir_entry *procfile = ch->procdir->subdir;
- unsigned long flags;
- int ret = -ENODEV;
-
- if (!dev->base_addr || !dev->irq)
- goto err_ret;
-
-
- if(hw->channel==1) {
- if(!TWIN(dev) || !(COMX_CHANNEL(TWIN(dev))->init_status &
- IRQ_ALLOCATED)) {
- printk(KERN_ERR "%s: channel 0 not yet initialized\n",dev->name);
- ret = -EAGAIN;
- goto err_ret;
- }
- }
-
-
- /* Is our hw present at all ? Not checking for channel 0 if it is already
- open */
- if(hw->channel!=0 || !(ch->init_status & IRQ_ALLOCATED)) {
- if (!request_region(dev->base_addr, MIXCOM_IO_EXTENT, dev->name)) {
- ret = -EAGAIN;
- goto err_ret;
- }
- if (mixcom_probe(dev)) {
- ret = -ENODEV;
- goto err_release_region;
- }
- }
-
- if(hw->channel==0 && !(ch->init_status & IRQ_ALLOCATED)) {
- if (request_irq(dev->irq, MIXCOM_interrupt, 0,
- dev->name, (void *)dev)) {
- printk(KERN_ERR "MIXCOM: unable to obtain irq %d\n", dev->irq);
- ret = -EAGAIN;
- goto err_release_region;
- }
- }
-
- save_flags(flags); cli();
-
- if(hw->channel==0 && !(ch->init_status & IRQ_ALLOCATED)) {
- ch->init_status|=IRQ_ALLOCATED;
- mixcom_board_on(dev);
- }
-
- mixcom_on(dev);
-
-
- hw->status=inb(MIXCOM_BOARD_BASE(dev) + MIXCOM_STATUS_OFFSET);
- if(hw->status != 0xff) {
- printk(KERN_DEBUG "%s: board has status register, good\n", dev->name);
- hw->card_has_status=1;
- }
-
- hw->txbusy = 0;
- ch->init_status |= HW_OPEN;
-
- if (rd_hscx(dev, HSCX_STAR) & HSCX_CTS) {
- ch->line_status |= LINE_UP;
- } else {
- ch->line_status &= ~LINE_UP;
- }
-
- restore_flags(flags);
-
- ch->LINE_status(dev, ch->line_status);
-
- for (; procfile ; procfile = procfile->next) {
- if (strcmp(procfile->name, FILENAME_IO) == 0 ||
- strcmp(procfile->name, FILENAME_CHANNEL) == 0 ||
- strcmp(procfile->name, FILENAME_CLOCK) == 0 ||
- strcmp(procfile->name, FILENAME_IRQ) == 0) {
- procfile->mode = S_IFREG | 0444;
- }
- }
-
- return 0;
-
-err_release_region:
- release_region(dev->base_addr, MIXCOM_IO_EXTENT);
-err_ret:
- return ret;
-}
-
-static int MIXCOM_close(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct mixcom_privdata *hw = ch->HW_privdata;
- struct proc_dir_entry *procfile = ch->procdir->subdir;
- unsigned long flags;
-
-
- save_flags(flags); cli();
-
- mixcom_off(dev);
-
- /* This is channel 0, twin is not open, we can safely turn off everything */
- if(hw->channel==0 && (!(TWIN(dev)) ||
- !(COMX_CHANNEL(TWIN(dev))->init_status & HW_OPEN))) {
- mixcom_board_off(dev);
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, MIXCOM_IO_EXTENT);
- ch->init_status &= ~IRQ_ALLOCATED;
- }
-
- /* This is channel 1, channel 0 has already been shutdown, we can release
- this one too */
- if(hw->channel==1 && !(COMX_CHANNEL(TWIN(dev))->init_status & HW_OPEN)) {
- if(COMX_CHANNEL(TWIN(dev))->init_status & IRQ_ALLOCATED) {
- mixcom_board_off(TWIN(dev));
- free_irq(TWIN(dev)->irq, TWIN(dev));
- release_region(TWIN(dev)->base_addr, MIXCOM_IO_EXTENT);
- COMX_CHANNEL(TWIN(dev))->init_status &= ~IRQ_ALLOCATED;
- }
- }
-
- /* the ioports for channel 1 can be safely released */
- if(hw->channel==1) {
- release_region(dev->base_addr, MIXCOM_IO_EXTENT);
- }
-
- restore_flags(flags);
-
- /* If we don't hold any hardware open */
- if(!(ch->init_status & IRQ_ALLOCATED)) {
- for (; procfile ; procfile = procfile->next) {
- if (strcmp(procfile->name, FILENAME_IO) == 0 ||
- strcmp(procfile->name, FILENAME_CHANNEL) == 0 ||
- strcmp(procfile->name, FILENAME_CLOCK) == 0 ||
- strcmp(procfile->name, FILENAME_IRQ) == 0) {
- procfile->mode = S_IFREG | 0644;
- }
- }
- }
-
- /* channel 0 was only waiting for us to close channel 1
- close it completely */
-
- if(hw->channel==1 && !(COMX_CHANNEL(TWIN(dev))->init_status & HW_OPEN)) {
- for (procfile=COMX_CHANNEL(TWIN(dev))->procdir->subdir;
- procfile ; procfile = procfile->next) {
- if (strcmp(procfile->name, FILENAME_IO) == 0 ||
- strcmp(procfile->name, FILENAME_CHANNEL) == 0 ||
- strcmp(procfile->name, FILENAME_CLOCK) == 0 ||
- strcmp(procfile->name, FILENAME_IRQ) == 0) {
- procfile->mode = S_IFREG | 0644;
- }
- }
- }
-
- ch->init_status &= ~HW_OPEN;
- return 0;
-}
-
-static int MIXCOM_statistics(struct net_device *dev,char *page)
-{
- struct comx_channel *ch = dev->priv;
- // struct mixcom_privdata *hw = ch->HW_privdata;
- int len = 0;
-
- if(ch->init_status && IRQ_ALLOCATED) {
- len += sprintf(page + len, "Mixcom board: hardware open\n");
- }
-
- return len;
-}
-
-static int MIXCOM_dump(struct net_device *dev) {
- return 0;
-}
-
-static int mixcom_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct proc_dir_entry *file = (struct proc_dir_entry *)data;
- struct net_device *dev = file->parent->data;
- struct comx_channel *ch = dev->priv;
- struct mixcom_privdata *hw = ch->HW_privdata;
- int len = 0;
-
- if (strcmp(file->name, FILENAME_IO) == 0) {
- len = sprintf(page, "0x%x\n",
- (unsigned int)MIXCOM_BOARD_BASE(dev));
- } else if (strcmp(file->name, FILENAME_IRQ) == 0) {
- len = sprintf(page, "%d\n", (unsigned int)dev->irq);
- } else if (strcmp(file->name, FILENAME_CLOCK) == 0) {
- if (hw->clock) len = sprintf(page, "%d\n", hw->clock);
- else len = sprintf(page, "external\n");
- } else if (strcmp(file->name, FILENAME_CHANNEL) == 0) {
- len = sprintf(page, "%01d\n", hw->channel);
- } else if (strcmp(file->name, FILENAME_TWIN) == 0) {
- if (ch->twin) {
- len = sprintf(page, "%s\n",ch->twin->name);
- } else {
- len = sprintf(page, "none\n");
- }
- } else {
- printk(KERN_ERR "mixcom_read_proc: internal error, filename %s\n", file->name);
- return -EBADF;
- }
-
- if (off >= len) {
- *eof = 1;
- return 0;
- }
- *start = page + off;
- if (count >= len - off) *eof = 1;
- return min_t(int, count, len - off);
-}
-
-
-static struct net_device *mixcom_twin_check(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct proc_dir_entry *procfile = ch->procdir->parent->subdir;
- struct mixcom_privdata *hw = ch->HW_privdata;
-
- struct net_device *twin;
- struct comx_channel *ch_twin;
- struct mixcom_privdata *hw_twin;
-
-
- for ( ; procfile ; procfile = procfile->next) {
- if(!S_ISDIR(procfile->mode)) continue;
-
- twin = procfile->data;
- ch_twin = twin->priv;
- hw_twin = ch_twin->HW_privdata;
-
-
- if (twin != dev && dev->irq && dev->base_addr &&
- dev->irq == twin->irq &&
- ch->hardware == ch_twin->hardware &&
- dev->base_addr == twin->base_addr +
- (1-2*hw->channel)*MIXCOM_CHANNEL_OFFSET &&
- hw->channel == (1 - hw_twin->channel)) {
- if (!TWIN(twin) || TWIN(twin)==dev) {
- return twin;
- }
- }
- }
- return NULL;
-}
-
-
-static void setup_twin(struct net_device* dev)
-{
-
- if(TWIN(dev) && TWIN(TWIN(dev))) {
- TWIN(TWIN(dev))=NULL;
- }
- if ((TWIN(dev) = mixcom_twin_check(dev)) != NULL) {
- if (TWIN(TWIN(dev)) && TWIN(TWIN(dev)) != dev) {
- TWIN(dev)=NULL;
- } else {
- TWIN(TWIN(dev))=dev;
- }
- }
-}
-
-static int mixcom_write_proc(struct file *file, const char *buffer,
- u_long count, void *data)
-{
- struct proc_dir_entry *entry = (struct proc_dir_entry *)data;
- struct net_device *dev = (struct net_device *)entry->parent->data;
- struct comx_channel *ch = dev->priv;
- struct mixcom_privdata *hw = ch->HW_privdata;
- char *page;
- int value;
-
- if (!(page = (char *)__get_free_page(GFP_KERNEL))) {
- return -ENOMEM;
- }
-
- if (copy_from_user(page, buffer, count = min_t(unsigned long, count, PAGE_SIZE))) {
- free_page((unsigned long)page);
- return -EFAULT;
- }
- if (*(page + count - 1) == '\n') {
- *(page + count - 1) = 0;
- }
-
- if (strcmp(entry->name, FILENAME_IO) == 0) {
- value = simple_strtoul(page, NULL, 0);
- if (value != 0x180 && value != 0x280 && value != 0x380) {
- printk(KERN_ERR "MIXCOM: incorrect io address!\n");
- } else {
- dev->base_addr = MIXCOM_DEV_BASE(value,hw->channel);
- }
- } else if (strcmp(entry->name, FILENAME_IRQ) == 0) {
- value = simple_strtoul(page, NULL, 0);
- if (value < 0 || value > 15 || mixcom_set_irq[value]==0xFF) {
- printk(KERN_ERR "MIXCOM: incorrect irq value!\n");
- } else {
- dev->irq = value;
- }
- } else if (strcmp(entry->name, FILENAME_CLOCK) == 0) {
- if (strncmp("ext", page, 3) == 0) {
- hw->clock = 0;
- } else {
- int kbps;
-
- kbps = simple_strtoul(page, NULL, 0);
- if (!kbps) {
- hw->clock = 0;
- } else {
- hw->clock = kbps;
- }
- if (hw->clock < 32 || hw->clock > 2000) {
- hw->clock = 0;
- printk(KERN_ERR "MIXCOM: invalid clock rate!\n");
- }
- }
- if (ch->init_status & HW_OPEN && ch->HW_set_clock) {
- ch->HW_set_clock(dev);
- }
- } else if (strcmp(entry->name, FILENAME_CHANNEL) == 0) {
- value = simple_strtoul(page, NULL, 0);
- if (value > 2) {
- printk(KERN_ERR "Invalid channel number\n");
- } else {
- dev->base_addr+=(hw->channel - value) * MIXCOM_CHANNEL_OFFSET;
- hw->channel = value;
- }
- } else {
- printk(KERN_ERR "hw_read_proc: internal error, filename %s\n",
- entry->name);
- return -EBADF;
- }
-
- setup_twin(dev);
-
- free_page((unsigned long)page);
- return count;
-}
-
-static int MIXCOM_init(struct net_device *dev) {
- struct comx_channel *ch = dev->priv;
- struct mixcom_privdata *hw;
- struct proc_dir_entry *new_file;
-
- if ((ch->HW_privdata = kmalloc(sizeof(struct mixcom_privdata),
- GFP_KERNEL)) == NULL) {
- return -ENOMEM;
- }
-
- memset(hw = ch->HW_privdata, 0, sizeof(struct mixcom_privdata));
-
- if ((new_file = create_proc_entry(FILENAME_IO, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_HW_privdata;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &mixcom_read_proc;
- new_file->write_proc = &mixcom_write_proc;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_IRQ, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_filename_io;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &mixcom_read_proc;
- new_file->write_proc = &mixcom_write_proc;
- new_file->nlink = 1;
-
-#if 0
- if ((new_file = create_proc_entry(FILENAME_CLOCK, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- return -EIO;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &mixcom_read_proc;
- new_file->write_proc = &mixcom_write_proc;
- new_file->nlink = 1;
-#endif
-
- if ((new_file = create_proc_entry(FILENAME_CHANNEL, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_filename_irq;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &mixcom_read_proc;
- new_file->write_proc = &mixcom_write_proc;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_TWIN, S_IFREG | 0444,
- ch->procdir)) == NULL) {
- goto cleanup_filename_channel;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &mixcom_read_proc;
- new_file->write_proc = &mixcom_write_proc;
- new_file->nlink = 1;
-
- setup_twin(dev);
-
- /* Fill in ch_struct hw specific pointers */
- ch->HW_access_board = NULL;
- ch->HW_release_board = NULL;
- ch->HW_txe = MIXCOM_txe;
- ch->HW_open = MIXCOM_open;
- ch->HW_close = MIXCOM_close;
- ch->HW_send_packet = MIXCOM_send_packet;
- ch->HW_statistics = MIXCOM_statistics;
- ch->HW_set_clock = NULL;
-
- dev->base_addr = MIXCOM_DEV_BASE(MIXCOM_DEFAULT_IO,0);
- dev->irq = MIXCOM_DEFAULT_IRQ;
-
- MOD_INC_USE_COUNT;
- return 0;
-cleanup_filename_channel:
- remove_proc_entry(FILENAME_CHANNEL, ch->procdir);
-cleanup_filename_irq:
- remove_proc_entry(FILENAME_IRQ, ch->procdir);
-cleanup_filename_io:
- remove_proc_entry(FILENAME_IO, ch->procdir);
-cleanup_HW_privdata:
- kfree(ch->HW_privdata);
- return -EIO;
-}
-
-static int MIXCOM_exit(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct mixcom_privdata *hw = ch->HW_privdata;
-
- if(hw->channel==0 && TWIN(dev)) {
- return -EBUSY;
- }
-
- if(hw->channel==1 && TWIN(dev)) {
- TWIN(TWIN(dev))=NULL;
- }
-
- kfree(ch->HW_privdata);
- remove_proc_entry(FILENAME_IO, ch->procdir);
- remove_proc_entry(FILENAME_IRQ, ch->procdir);
-#if 0
- remove_proc_entry(FILENAME_CLOCK, ch->procdir);
-#endif
- remove_proc_entry(FILENAME_CHANNEL, ch->procdir);
- remove_proc_entry(FILENAME_TWIN, ch->procdir);
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static struct comx_hardware mixcomhw = {
- "mixcom",
- VERSION,
- MIXCOM_init,
- MIXCOM_exit,
- MIXCOM_dump,
- NULL
-};
-
-static int __init comx_hw_mixcom_init(void)
-{
- return comx_register_hardware(&mixcomhw);
-}
-
-static void __exit comx_hw_mixcom_exit(void)
-{
- comx_unregister_hardware("mixcom");
-}
-
-module_init(comx_hw_mixcom_init);
-module_exit(comx_hw_mixcom_exit);
===== drivers/net/wan/comx-hw-munich.c 1.17 vs edited =====
--- 1.17/drivers/net/wan/comx-hw-munich.c Wed Mar 3 18:32:01 2004
+++ edited/drivers/net/wan/comx-hw-munich.c Fri May 7 13:05:52 2004
@@ -1,2854 +1 @@
-/*
- * Hardware-level driver for the SliceCOM board for Linux kernels 2.4.X
- *
- * Current maintainer / latest changes: Pasztor Szilard <don@itc.hu>
- *
- * Original author: Bartok Istvan <bartoki@itc.hu>
- * Based on skeleton by Tivadar Szemethy <tiv@itc.hu>
- *
- * 0.51:
- * - port for 2.4.x
- * - clean up some code, make it more portable
- * - busted direct hardware access through mapped memory
- * - fix a possible race
- * - prevent procfs buffer overflow
- *
- * 0.50:
- * - support for the pcicom board, lots of rearrangements
- * - handle modem status lines
- *
- * 0.50a:
- * - fix for falc version 1.0
- *
- * 0.50b: T&t
- * - fix for bad localbus
- */
-#define VERSION "0.51"
-#define VERSIONSTR "SliceCOM v" VERSION ", 2002/01/07\n"
-
-#include <linux/config.h>
-#include <linux/ctype.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include <asm/delay.h>
-#include <asm/types.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#define COMX_NEW
-
-#ifndef COMX_NEW
-#include "../include/comx.h"
-#include "../include/munich32x.h"
-#include "../include/falc-lh.h"
-#else
-#include "comx.h"
-#include "munich32x.h"
-#include "falc-lh.h"
-#endif
-
-MODULE_AUTHOR("Bartok Istvan <bartoki@itc.hu>, Gergely Madarasz <gorgo@itc.hu>, Szilard Pasztor <don@itc.hu>");
-MODULE_DESCRIPTION("Hardware-level driver for the SliceCOM and PciCOM (WelCOM) adapters");
-MODULE_LICENSE("GPL");
-/*
- * TODO: az ilyenek a comxhw.h -ban szoktak lenni, idovel menjenek majd oda:
- */
-
-#define FILENAME_BOARDNUM "boardnum" /* /proc/comx/comx0.1/boardnum */
-#define FILENAME_TIMESLOTS "timeslots" /* /proc/comx/comx0.1/timeslots */
-#define FILENAME_FRAMING "framing" /* /proc/comx/comx0.1/framing */
-#define FILENAME_LINECODE "linecode" /* /proc/comx/comx0.1/linecode */
-#define FILENAME_CLOCK_SOURCE "clock_source" /* /proc/comx/comx0.1/clock_source */
-#define FILENAME_LOOPBACK "loopback" /* /proc/comx/comx0.1/loopback */
-#define FILENAME_REG "reg" /* /proc/comx/comx0.1/reg */
-#define FILENAME_LBIREG "lbireg" /* /proc/comx/comx0.1/lbireg */
-
-#define SLICECOM_BOARDNUM_DEFAULT 0
-
-#define SLICECOM_FRAMING_CRC4 1
-#define SLICECOM_FRAMING_NO_CRC4 2
-#define SLICECOM_FRAMING_DEFAULT SLICECOM_FRAMING_CRC4
-
-#define SLICECOM_LINECODE_HDB3 1
-#define SLICECOM_LINECODE_AMI 2
-#define SLICECOM_LINECODE_DEFAULT SLICECOM_LINECODE_HDB3
-
-#define SLICECOM_CLOCK_SOURCE_LINE 1
-#define SLICECOM_CLOCK_SOURCE_INTERNAL 2
-#define SLICECOM_CLOCK_SOURCE_DEFAULT SLICECOM_CLOCK_SOURCE_LINE
-
-#define SLICECOM_LOOPBACK_NONE 1
-#define SLICECOM_LOOPBACK_LOCAL 2
-#define SLICECOM_LOOPBACK_REMOTE 3
-#define SLICECOM_LOOPBACK_DEFAULT SLICECOM_LOOPBACK_NONE
-
-#define MUNICH_VIRT(addr) (void *)(&bar1[addr])
-
-struct slicecom_stringtable
-{
- char *name;
- int value;
-};
-
-/* A convention: keep "default" the last not NULL when reading from /proc,
- "error" is an indication that something went wrong, we have an undefined value */
-
-struct slicecom_stringtable slicecom_framings[] =
-{
- {"crc4", SLICECOM_FRAMING_CRC4},
- {"no-crc4", SLICECOM_FRAMING_NO_CRC4},
- {"default", SLICECOM_FRAMING_DEFAULT},
- {"error", 0}
-};
-
-struct slicecom_stringtable slicecom_linecodes[] =
-{
- {"hdb3", SLICECOM_LINECODE_HDB3},
- {"ami", SLICECOM_LINECODE_AMI},
- {"default", SLICECOM_LINECODE_DEFAULT},
- {"error", 0}
-};
-
-struct slicecom_stringtable slicecom_clock_sources[] =
-{
- {"line", SLICECOM_CLOCK_SOURCE_LINE},
- {"internal", SLICECOM_CLOCK_SOURCE_INTERNAL},
- {"default", SLICECOM_CLOCK_SOURCE_DEFAULT},
- {"error", 0}
-};
-
-struct slicecom_stringtable slicecom_loopbacks[] =
-{
- {"none", SLICECOM_LOOPBACK_NONE},
- {"local", SLICECOM_LOOPBACK_LOCAL},
- {"remote", SLICECOM_LOOPBACK_REMOTE},
- {"default", SLICECOM_LOOPBACK_DEFAULT},
- {"error", 0}
-};
-
-/*
- * Some tunable values...
- *
- * Note: when tuning values which change the length of text in
- * /proc/comx/comx[n]/status, keep in mind that it must be shorter then
- * PAGESIZE !
- */
-
-#define MAX_BOARDS 4 /* ezzel 4 kartya lehet a gepben: 0..3 */
-#define RX_DESC_MAX 8 /* Rx ring size, must be >= 4 */
-#define TX_DESC_MAX 4 /* Tx ring size, must be >= 2 */
- /* a sokkal hosszabb Tx ring mar ronthatja a nem-FIFO packet */
- /* schedulerek (fair queueing, stb.) hatekonysagat. */
-#define MAX_WORK 10 /* TOD: update the info max. ennyi-1 esemenyt dolgoz fel egy interrupt hivasnal */
-
-/*
- * These are tunable too, but don't touch them without fully understanding what is happening
- */
-
-#define UDELAY 20 /* We wait UDELAY usecs with disabled interrupts before and */
- /* after each command to avoid writing into each other's */
- /* ccb->action_spec. A _send_packet nem var, mert azt az */
- /* _interrupt()-bol is meghivhatja a LINE_tx() */
-
-/*
- * Just to avoid warnings about implicit declarations:
- */
-
-static int MUNICH_close(struct net_device *dev);
-static struct comx_hardware slicecomhw;
-static struct comx_hardware pcicomhw;
-
-static unsigned long flags;
-static spinlock_t mister_lock = SPIN_LOCK_UNLOCKED;
-
-typedef volatile struct /* Time Slot Assignment */
-{
- u32 rxfillmask:8, // ----------------------------+------+
- // | |
- rxchannel:5, // ----------------------+---+ | |
- rti:1, // ---------------------+| | | |
- res2:2, // -------------------++|| | | |
- // |||| | | |
- txfillmask:8, // ----------+------+ |||| | | |
- // | | |||| | | |
- txchannel:5, // ----+---+ | | |||| | | |
- tti:1, // ---+| | | | |||| | | |
- res1:2; // -++|| | | | |||| | | |
- // 3 2 1
- // 10987654 32109876 54321098 76543210
-} timeslot_spec_t;
-
-typedef volatile struct /* Receive Descriptor */
-{
- u32 zero1:16, no:13, hi:1, hold:1, zero2:1;
-
- u32 next;
- u32 data;
-
- u32 zero3:8, status:8, bno:13, zero4:1, c:1, fe:1;
-} rx_desc_t;
-
-typedef volatile struct /* Transmit Descriptor */
-{
- u32 fnum:11, csm:1, no13:1, zero1:2, v110:1, no:13, hi:1, hold:1, fe:1;
-
- u32 next;
- u32 data;
-
-} tx_desc_t;
-
-typedef volatile struct /* Channel Specification */
-{
- u32 iftf:1, mode:2, fa:1, trv:2, crc:1, inv:1, cs:1, tflag:7, ra:1, ro:1,
- th:1, ta:1, to:1, ti:1, ri:1, nitbs:1, fit:1, fir:1, re:1, te:1, ch:1,
- ifc:1, sfe:1, fe2:1;
-
- u32 frda;
- u32 ftda;
-
- u32 itbs:6, zero1:26;
-
-} channel_spec_t;
-
-typedef volatile struct /* Configuration Control Block */
-{
- u32 action_spec;
- u32 reserved1;
- u32 reserved2;
- timeslot_spec_t timeslot_spec[32];
- channel_spec_t channel_spec[32];
- u32 current_rx_desc[32];
- u32 current_tx_desc[32];
- u32 csa; /* Control Start Address. CSA = *CCBA; CCB = *CSA */
- /* MUNICH does it like: CCB = *( *CCBA ) */
-} munich_ccb_t;
-
-typedef volatile struct /* Entry in the interrupt queue */
-{
- u32 all;
-} munich_intq_t;
-
-#define MUNICH_INTQLEN 63 /* Rx/Tx Interrupt Queue Length
- (not the real len, but the TIQL/RIQL value) */
-#define MUNICH_INTQMAX ( 16*(MUNICH_INTQLEN+1) ) /* Rx/Tx/Periph Interrupt Queue size in munich_intq_t's */
-#define MUNICH_INTQSIZE ( 4*MUNICH_INTQMAX ) /* Rx/Tx/Periph Interrupt Queue size in bytes */
-
-#define MUNICH_PIQLEN 4 /* Peripheral Interrupt Queue Length. Unlike the RIQL/TIQL, */
-#define MUNICH_PIQMAX ( 4*MUNICH_PIQLEN ) /* PIQL register needs it like this */
-#define MUNICH_PIQSIZE ( 4*MUNICH_PIQMAX )
-
-typedef volatile u32 vol_u32; /* TOD: ezek megszunnek ha atirom readw()/writew()-re - kész */
-typedef volatile u8 vol_u8;
-
-typedef volatile struct /* counters of E1-errors and errored seconds, see rfc2495 */
-{
- /* use here only unsigned ints, we depend on it when calculating the sum for the last N intervals */
-
- unsigned line_code_violations, /* AMI: bipolar violations, HDB3: hdb3 violations */
- path_code_violations, /* FAS errors and CRC4 errors */
- e_bit_errors, /* E-Bit Errors (the remote side received from us with CRC4-error) */
- slip_secs, /* number of seconds with (receive) Controlled Slip(s) */
- fr_loss_secs, /* number of seconds an Out Of Frame defect was detected */
- line_err_secs, /* number of seconds with one or more Line Code Violations */
- degraded_mins, /* Degraded Minute - the estimated error rate is >1E-6, but <1E-3 */
- errored_secs, /* Errored Second - at least one of these happened:
- - Path Code Violation
- - Out Of Frame defect
- - Slip
- - receiving AIS
- - not incremented during an Unavailable Second */
- bursty_err_secs, /* Bursty Errored Second: (rfc2495 says it does not apply to E1)
- - Path Code Violations >1, but <320
- - not a Severely Errored Second
- - no AIS
- - not incremented during an Unavailabla Second */
- severely_err_secs, /* Severely Errored Second:
- - CRC4: >=832 Path COde Violations || >0 Out Of Frame defects
- - noCRC4: >=2048 Line Code Violations
- - not incremented during an Unavailable Second */
- unavail_secs; /* number of Unavailable Seconds. Unavailable state is said after:
- - 10 contiguous Severely Errored Seconds
- - or RAI || AIS || LOF || LOS
- - (any) loopback has been set */
-
- /*
- * we do not strictly comply to the rfc: we do not retroactively reduce errored_secs,
- * bursty_err_secs, severely_err_secs when 'unavailable state' is reached
- */
-
-} e1_stats_t;
-
-typedef volatile struct /* ezek board-adatok, nem lehetnek a slicecom_privdata -ban */
-{
- int use_count; /* num. of interfaces using the board */
- int irq; /* a kartya irq-ja. belemasoljuk a dev->irq -kba is, de csak hogy */
- /* szebb legyen az ifconfig outputja */
- /* ha != 0, az azt jelenti hogy az az irq most nekunk sikeresen */
- /* le van foglalva */
- struct pci_dev *pci; /* a kartya PCI strukturaja. NULL, ha nincs kartya */
- u32 *bar1; /* pci->base_address[0] ioremap()-ed by munich_probe(), */
- /* on x86 can be used both as a bus or virtual address. */
- /* These are the Munich's registers */
- u8 *lbi; /* pci->base_address[1] ioremap()-ed by munich_probe(), */
- /* this is a 256-byte range, the start of the LBI on the board */
- munich_ccb_t *ccb; /* virtual address of CCB */
- munich_intq_t *tiq; /* Tx Interrupt Queue */
- munich_intq_t *riq; /* Rx Interrupt Queue */
- munich_intq_t *piq; /* Peripheral Interrupt Queue (FALC interrupts arrive here) */
- int tiq_ptr, /* A 'current' helyek a tiq/riq/piq -ban. */
- riq_ptr, /* amikor feldolgoztam az interruptokat, a legelso ures */
- piq_ptr; /* interrupt_information szora mutatnak. */
- struct net_device *twins[32]; /* MUNICH channel -> network interface assignment */
-
- unsigned long lastcheck; /* When were the Rx rings last checked. Time in jiffies */
-
- struct timer_list modemline_timer;
- char isx21;
- char lineup;
- char framing; /* a beallitasok tarolasa */
- char linecode;
- char clock_source;
- char loopback;
-
- char devname[30]; /* what to show in /proc/interrupts */
- unsigned histogram[MAX_WORK]; /* number of processed events in the interrupt loop */
- unsigned stat_pri_races; /* number of special events, we try to handle them */
- unsigned stat_pti_races;
- unsigned stat_pri_races_missed; /* when it can not be handled, because of MAX_WORK */
- unsigned stat_pti_races_missed;
-
-#define SLICECOM_BOARD_INTERVALS_SIZE 97
- e1_stats_t intervals[SLICECOM_BOARD_INTERVALS_SIZE]; /* E1 line statistics */
- unsigned current_interval; /* pointer to the current interval */
- unsigned elapsed_seconds; /* elapsed seconds from the start of the current interval */
- unsigned ses_seconds; /* counter of contiguous Severely Errored Seconds */
- unsigned is_unavailable; /* set to 1 after 10 contiguous Severely Errored Seconds */
- unsigned no_ses_seconds; /* contiguous Severely Error -free seconds in unavail state */
-
- unsigned deg_elapsed_seconds; /* for counting the 'Degraded Mins' */
- unsigned deg_cumulated_errors;
-
- struct module *owner; /* pointer to our module to avoid module load races */
-} munich_board_t;
-
-struct slicecom_privdata
-{
- int busy; /* transmitter busy - number of packets in the Tx ring */
- int channel; /* Munich logical channel ('channel-group' in Cisco) */
- unsigned boardnum;
- u32 timeslots; /* i-th bit means i-th timeslot is our */
-
- int tx_ring_hist[TX_DESC_MAX]; /* histogram: number of packets in Tx ring when _send_packet is called */
-
- tx_desc_t tx_desc[TX_DESC_MAX]; /* the ring of Tx descriptors */
- u8 tx_data[TX_DESC_MAX][TXBUFFER_SIZE]; /* buffers for data to transmit */
- int tx_desc_ptr; /* hanyadik descriptornal tartunk a beirassal */
- /* ahol ez all, oda irtunk utoljara */
-
- rx_desc_t rx_desc[RX_DESC_MAX]; /* the ring of Rx descriptors */
- u8 rx_data[RX_DESC_MAX][RXBUFFER_SIZE]; /* buffers for received data */
- int rx_desc_ptr; /* hanyadik descriptornal tartunk az olvasassal */
-
- int rafutott;
-};
-
-static u32 reg, reg_ertek; /* why static: don't write stack trash into regs if strtoul() fails */
-static u32 lbireg;
-static u8 lbireg_ertek; /* why static: don't write stack trash into regs if strtoul() fails */
-
-static munich_board_t slicecom_boards[MAX_BOARDS];
-static munich_board_t pcicom_boards[MAX_BOARDS];
-
-/*
- * Reprogram Idle Channel Registers in the FALC - send special code in not used channels
- * Should be called from the open and close, when the timeslot assignment changes
- */
-
-void rework_idle_channels(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct slicecom_privdata *hw = ch->HW_privdata;
- munich_board_t *board = slicecom_boards + hw->boardnum;
- munich_ccb_t *ccb = board->ccb;
-
- u8 *lbi = board->lbi;
- int i, j, tmp;
-
-
- spin_lock_irqsave(&mister_lock, flags);
-
- for (i = 0; i < 4; i++)
- {
- tmp = 0xFF;
- for (j = 0; j < 8; j++)
- if (ccb->timeslot_spec[8 * i + j].tti == 0) tmp ^= (0x80 >> j);
- writeb(tmp, lbi + 0x30 + i);
- }
-
- spin_unlock_irqrestore(&mister_lock, flags);
-}
-
-/*
- * Set PCM framing - /proc/comx/comx0/framing
- */
-
-void slicecom_set_framing(int boardnum, int value)
-{
- u8 *lbi = slicecom_boards[boardnum].lbi;
-
- spin_lock_irqsave(&mister_lock, flags);
-
- slicecom_boards[boardnum].framing = value;
- switch (value)
- {
- case SLICECOM_FRAMING_CRC4:
- writeb(readb(lbi + FMR1) | 8, lbi + FMR1);
- writeb((readb(lbi + FMR2) & 0x3f) | 0x80, lbi + FMR2);
- break;
- case SLICECOM_FRAMING_NO_CRC4:
- writeb(readb(lbi + FMR1) & 0xf7, lbi + FMR1);
- writeb(readb(lbi + FMR2) & 0x3f, lbi + FMR2);
- break;
- default:
- printk("slicecom: board %d: unhandled " FILENAME_FRAMING
- " value %d\n", boardnum, value);
- }
-
- spin_unlock_irqrestore(&mister_lock, flags);
-}
-
-/*
- * Set PCM linecode - /proc/comx/comx0/linecode
- */
-
-void slicecom_set_linecode(int boardnum, int value)
-{
- u8 *lbi = slicecom_boards[boardnum].lbi;
-
- spin_lock_irqsave(&mister_lock, flags);
-
- slicecom_boards[boardnum].linecode = value;
- switch (value)
- {
- case SLICECOM_LINECODE_HDB3:
- writeb(readb(lbi + FMR0) | 0xf0, lbi + FMR0);
- break;
- case SLICECOM_LINECODE_AMI:
- writeb((readb(lbi + FMR0) & 0x0f) | 0xa0, lbi + FMR0);
- break;
- default:
- printk("slicecom: board %d: unhandled " FILENAME_LINECODE
- " value %d\n", boardnum, value);
- }
- spin_unlock_irqrestore(&mister_lock, flags);
-}
-
-/*
- * Set PCM clock source - /proc/comx/comx0/clock_source
- */
-
-void slicecom_set_clock_source(int boardnum, int value)
-{
- u8 *lbi = slicecom_boards[boardnum].lbi;
-
- spin_lock_irqsave(&mister_lock, flags);
-
- slicecom_boards[boardnum].clock_source = value;
- switch (value)
- {
- case SLICECOM_CLOCK_SOURCE_LINE:
- writeb(readb(lbi + LIM0) & ~1, lbi + LIM0);
- break;
- case SLICECOM_CLOCK_SOURCE_INTERNAL:
- writeb(readb(lbi + LIM0) | 1, lbi + LIM0);
- break;
- default:
- printk("slicecom: board %d: unhandled " FILENAME_CLOCK_SOURCE
- " value %d\n", boardnum, value);
- }
- spin_unlock_irqrestore(&mister_lock, flags);
-}
-
-/*
- * Set loopbacks - /proc/comx/comx0/loopback
- */
-
-void slicecom_set_loopback(int boardnum, int value)
-{
- u8 *lbi = slicecom_boards[boardnum].lbi;
-
- spin_lock_irqsave(&mister_lock, flags);
-
- slicecom_boards[boardnum].loopback = value;
- switch (value)
- {
- case SLICECOM_LOOPBACK_NONE:
- writeb(readb(lbi + LIM0) & ~2, lbi + LIM0); /* Local Loop OFF */
- writeb(readb(lbi + LIM1) & ~2, lbi + LIM1); /* Remote Loop OFF */
- break;
- case SLICECOM_LOOPBACK_LOCAL:
- writeb(readb(lbi + LIM1) & ~2, lbi + LIM1); /* Remote Loop OFF */
- writeb(readb(lbi + LIM0) | 2, lbi + LIM0); /* Local Loop ON */
- break;
- case SLICECOM_LOOPBACK_REMOTE:
- writeb(readb(lbi + LIM0) & ~2, lbi + LIM0); /* Local Loop OFF */
- writeb(readb(lbi + LIM1) | 2, lbi + LIM1); /* Remote Loop ON */
- break;
- default:
- printk("slicecom: board %d: unhandled " FILENAME_LOOPBACK
- " value %d\n", boardnum, value);
- }
- spin_unlock_irqrestore(&mister_lock, flags);
-}
-
-/*
- * Update E1 line status LEDs on the adapter
- */
-
-void slicecom_update_leds(munich_board_t * board)
-{
- u32 *bar1 = board->bar1;
- u8 *lbi = board->lbi;
- u8 frs0;
- u32 leds;
- int i;
-
- spin_lock_irqsave(&mister_lock, flags);
-
- leds = 0;
- frs0 = readb(lbi + FRS0); /* FRS0 bits described on page 137 */
-
- if (!(frs0 & 0xa0))
- {
- leds |= 0x2000; /* Green LED: Input signal seems to be OK, no LOS, no LFA */
- if (frs0 & 0x10)
- leds |= 0x8000; /* Red LED: Receiving Remote Alarm */
- }
- writel(leds, MUNICH_VIRT(GPDATA));
-
- if (leds == 0x2000 && !board->lineup)
- { /* line up */
- board->lineup = 1;
- for (i = 0; i < 32; i++)
- {
- if (board->twins[i] && (board->twins[i]->flags & IFF_RUNNING))
- {
- struct comx_channel *ch = board->twins[i]->priv;
-
- if (!test_and_set_bit(0, &ch->lineup_pending))
- {
- ch->lineup_timer.function = comx_lineup_func;
- ch->lineup_timer.data = (unsigned long)board->twins[i];
- ch->lineup_timer.expires = jiffies + HZ * ch->lineup_delay;
- add_timer(&ch->lineup_timer);
- }
- }
- }
- }
- else if (leds != 0x2000 && board->lineup)
- { /* line down */
- board->lineup = 0;
- for (i = 0; i < 32; i++)
- if (board->twins[i] && (board->twins[i]->flags & IFF_RUNNING))
- {
- struct comx_channel *ch = board->twins[i]->priv;
-
- if (test_and_clear_bit(0, &ch->lineup_pending))
- del_timer(&ch->lineup_timer);
- else if (ch->line_status & LINE_UP)
- {
- ch->line_status &= ~LINE_UP;
- if (ch->LINE_status)
- ch->LINE_status(board->twins[i], ch->line_status);
- }
- }
- }
- spin_unlock_irqrestore(&mister_lock, flags);
-}
-
-/*
- * This function gets called every second when the FALC issues the interrupt.
- * Hardware counters contain error counts for last 1-second time interval.
- * We add them to the global counters here.
- * Read rfc2495 to understand this.
- */
-
-void slicecom_update_line_counters(munich_board_t * board)
-{
- e1_stats_t *curr_int = &board->intervals[board->current_interval];
-
- u8 *lbi = board->lbi;
-
- unsigned framing_errors, code_violations, path_code_violations, crc4_errors,
- e_bit_errors;
- unsigned slip_detected, /* this one has logical value, not the number of slips! */
- out_of_frame_defect, /* logical value */
- ais_defect, /* logical value */
- errored_sec, bursty_err_sec, severely_err_sec = 0, failure_sec;
- u8 isr2, isr3, isr5, frs0;
-
- spin_lock_irqsave(&mister_lock, flags);
-
- isr2 = readb(lbi + ISR2); /* ISR0-5 described on page 156 */
- isr3 = readb(lbi + ISR3);
- isr5 = readb(lbi + ISR5);
- frs0 = readb(lbi + FRS0); /* FRS0 described on page 137 */
-
- /* Error Events: */
-
- code_violations = readb(lbi + CVCL) + (readb(lbi + CVCH) << 8);
- framing_errors = readb(lbi + FECL) + (readb(lbi + FECH) << 8);
- crc4_errors = readb(lbi + CEC1L) + (readb(lbi + CEC1H) << 8);
- e_bit_errors = readb(lbi + EBCL) + (readb(lbi + EBCH) << 8);
- slip_detected = isr3 & (ISR3_RSN | ISR3_RSP);
-
- path_code_violations = framing_errors + crc4_errors;
-
- curr_int->line_code_violations += code_violations;
- curr_int->path_code_violations += path_code_violations;
- curr_int->e_bit_errors += e_bit_errors;
-
- /* Performance Defects: */
-
- /* there was an LFA in the last second, but maybe disappeared: */
- out_of_frame_defect = (isr2 & ISR2_LFA) || (frs0 & FRS0_LFA);
-
- /* there was an AIS in the last second, but maybe disappeared: */
- ais_defect = (isr2 & ISR2_AIS) || (frs0 & FRS0_AIS);
-
- /* Performance Parameters: */
-
- if (out_of_frame_defect)
- curr_int->fr_loss_secs++;
- if (code_violations)
- curr_int->line_err_secs++;
-
- errored_sec = ((board->framing == SLICECOM_FRAMING_NO_CRC4) &&
- (code_violations)) || path_code_violations ||
- out_of_frame_defect || slip_detected || ais_defect;
-
- bursty_err_sec = !out_of_frame_defect && !ais_defect &&
- (path_code_violations > 1) && (path_code_violations < 320);
-
- switch (board->framing)
- {
- case SLICECOM_FRAMING_CRC4:
- severely_err_sec = out_of_frame_defect ||
- (path_code_violations >= 832);
- break;
- case SLICECOM_FRAMING_NO_CRC4:
- severely_err_sec = (code_violations >= 2048);
- break;
- }
-
- /*
- * failure_sec: true if there was a condition leading to a failure
- * (and leading to unavailable state) in this second:
- */
-
- failure_sec = (isr2 & ISR2_RA) || (frs0 & FRS0_RRA) /* Remote/Far End/Distant Alarm Failure */
- || ais_defect || out_of_frame_defect /* AIS or LOF Failure */
- || (isr2 & ISR2_LOS) || (frs0 & FRS0_LOS) /* Loss Of Signal Failure */
- || (board->loopback != SLICECOM_LOOPBACK_NONE); /* Loopback has been set */
-
- if (board->is_unavailable)
- {
- if (severely_err_sec)
- board->no_ses_seconds = 0;
- else
- board->no_ses_seconds++;
-
- if ((board->no_ses_seconds >= 10) && !failure_sec)
- {
- board->is_unavailable = 0;
- board->ses_seconds = 0;
- board->no_ses_seconds = 0;
- }
- }
- else
- {
- if (severely_err_sec)
- board->ses_seconds++;
- else
- board->ses_seconds = 0;
-
- if ((board->ses_seconds >= 10) || failure_sec)
- {
- board->is_unavailable = 1;
- board->ses_seconds = 0;
- board->no_ses_seconds = 0;
- }
- }
-
- if (board->is_unavailable)
- curr_int->unavail_secs++;
- else
- {
- if (slip_detected)
- curr_int->slip_secs++;
- curr_int->errored_secs += errored_sec;
- curr_int->bursty_err_secs += bursty_err_sec;
- curr_int->severely_err_secs += severely_err_sec;
- }
-
- /* the RFC does not say clearly which errors to count here, we try to count bit errors */
-
- if (!board->is_unavailable && !severely_err_sec)
- {
- board->deg_cumulated_errors += code_violations;
- board->deg_elapsed_seconds++;
- if (board->deg_elapsed_seconds >= 60)
- {
- if (board->deg_cumulated_errors >= 123)
- curr_int->degraded_mins++;
- board->deg_cumulated_errors = 0;
- board->deg_elapsed_seconds = 0;
- }
-
- }
-
- board->elapsed_seconds++;
- if (board->elapsed_seconds >= 900)
- {
- board->current_interval =
- (board->current_interval + 1) % SLICECOM_BOARD_INTERVALS_SIZE;
- memset((void *)&board->intervals[board->current_interval], 0,
- sizeof(e1_stats_t));
- board->elapsed_seconds = 0;
- }
-
- spin_unlock_irqrestore(&mister_lock, flags);
-}
-
-static void pcicom_modemline(unsigned long b)
-{
- munich_board_t *board = (munich_board_t *) b;
- struct net_device *dev = board->twins[0];
- struct comx_channel *ch = netdev_priv(dev);
- unsigned long regs;
-
- regs = readl((void *)(&board->bar1[GPDATA]));
- if ((ch->line_status & LINE_UP) && (regs & 0x0800))
- {
- ch->line_status &= ~LINE_UP;
- board->lineup = 0;
- if (ch->LINE_status)
- {
- ch->LINE_status(dev, ch->line_status);
- }
- }
-
- if (!(ch->line_status & LINE_UP) && !(regs & 0x0800))
- {
- ch->line_status |= LINE_UP;
- board->lineup = 1;
- if (ch->LINE_status)
- {
- ch->LINE_status(dev, ch->line_status);
- }
- }
-
- mod_timer((struct timer_list *)&board->modemline_timer, jiffies + HZ);
-}
-
-/*
- * Is it possible to transmit ?
- * Called (may be called) by the protocol layer
- */
-
-static int MUNICH_txe(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct slicecom_privdata *hw = ch->HW_privdata;
-
- return (hw->busy < TX_DESC_MAX - 1);
-}
-
-/*
- * Hw probe function. Detects all the boards in the system,
- * and fills up slicecom_boards[] and pcicom_boards[]
- * Returns 0 on success.
- * We do not disable interrupts!
- */
-static int munich_probe(void)
-{
- struct pci_dev *pci;
- int boardnum;
- int slicecom_boardnum;
- int pcicom_boardnum;
- u32 *bar1;
- u8 *lbi;
- munich_board_t *board;
-
- for (boardnum = 0; boardnum < MAX_BOARDS; boardnum++)
- {
- pcicom_boards[boardnum].pci = 0;
- pcicom_boards[boardnum].bar1 = 0;
- pcicom_boards[boardnum].lbi = 0;
- slicecom_boards[boardnum].pci = 0;
- slicecom_boards[boardnum].bar1 = 0;
- slicecom_boards[boardnum].lbi = 0;
- }
-
- pci = NULL;
- board = NULL;
- slicecom_boardnum = 0;
- pcicom_boardnum = 0;
-
- for (boardnum = 0;
- boardnum < MAX_BOARDS && (pci = pci_find_device(PCI_VENDOR_ID_SIEMENS,
- PCI_DEVICE_ID_SIEMENS_MUNICH32X, pci)); boardnum++)
- {
- if (pci_enable_device(pci))
- continue;
-
- printk("munich_probe: munich chip found, IRQ %d\n", pci->irq);
-
- bar1 = ioremap_nocache(pci->resource[0].start, 0x100);
- lbi = ioremap_nocache(pci->resource[1].start, 0x100);
-
- if (bar1 && lbi)
- {
- pci_write_config_dword(pci, MUNICH_PCI_PCIRES, 0xe0000);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- pci_write_config_dword(pci, MUNICH_PCI_PCIRES, 0);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- /* check the type of the card */
- writel(LREG0_MAGIC, MUNICH_VIRT(LREG0));
- writel(LREG1_MAGIC, MUNICH_VIRT(LREG1));
- writel(LREG2_MAGIC, MUNICH_VIRT(LREG2));
- writel(LREG3_MAGIC, MUNICH_VIRT(LREG3));
- writel(LREG4_MAGIC, MUNICH_VIRT(LREG4));
- writel(LREG5_MAGIC, MUNICH_VIRT(LREG5));
- writel(LCONF_MAGIC2,MUNICH_VIRT(LCONF)); /* enable the DMSM */
-
- if ((readb(lbi + VSTR) == 0x13) || (readb(lbi + VSTR) == 0x10))
- {
- board = slicecom_boards + slicecom_boardnum;
- sprintf((char *)board->devname, "slicecom%d",
- slicecom_boardnum);
- board->isx21 = 0;
- slicecom_boardnum++;
- }
- else if ((readb(lbi + VSTR) == 0x6) || (readb(lbi + GIS) == 0x6))
- {
- board = pcicom_boards + pcicom_boardnum;
- sprintf((char *)board->devname, "pcicom%d", pcicom_boardnum);
- board->isx21 = 1;
- pcicom_boardnum++;
- }
- if (board)
- {
- printk("munich_probe: %s board found\n", board->devname);
- writel(LCONF_MAGIC1, MUNICH_VIRT(LCONF)); /* reset the DMSM */
- board->pci = pci;
- board->bar1 = bar1;
- board->lbi = lbi;
- board->framing = SLICECOM_FRAMING_DEFAULT;
- board->linecode = SLICECOM_LINECODE_DEFAULT;
- board->clock_source = SLICECOM_CLOCK_SOURCE_DEFAULT;
- board->loopback = SLICECOM_LOOPBACK_DEFAULT;
- board->owner = THIS_MODULE;
- }
- else
- {
- printk("munich_probe: Board error, VSTR: %02X\n",
- readb(lbi + VSTR));
- iounmap((void *)bar1);
- iounmap((void *)lbi);
- }
- }
- else
- {
- printk("munich_probe: ioremap() failed, not enabling this board!\n");
- /* .pci = NULL, so the MUNICH_open will not try to open it */
- if (bar1) iounmap((void *)bar1);
- if (lbi) iounmap((void *)lbi);
- }
- }
-
- if (!pci && !boardnum)
- {
- printk("munich_probe: no PCI present!\n");
- return -ENODEV;
- }
-
- if (pcicom_boardnum + slicecom_boardnum == 0)
- {
- printk
- ("munich_probe: Couldn't find any munich board: vendor:device %x:%x not found\n",
- PCI_VENDOR_ID_SIEMENS, PCI_DEVICE_ID_SIEMENS_MUNICH32X);
- return -ENODEV;
- }
-
- /* Found some */
- if (pcicom_boardnum)
- printk("%d pcicom board(s) found.\n", pcicom_boardnum);
- if (slicecom_boardnum)
- printk("%d slicecom board(s) found.\n", slicecom_boardnum);
-
- return 0;
-}
-
-/*
- * Reset the hardware. Get called only from within this module if needed.
- */
-#if 0
-static int slicecom_reset(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
-
- printk("slicecom_reset: resetting the hardware\n");
-
- /* Begin to reset the hardware */
-
- if (ch->HW_set_clock)
- ch->HW_set_clock(dev);
-
- /* And finish it */
-
- return 0;
-}
-#endif
-
-/*
- * Transmit a packet.
- * Called by the protocol layer
- * Return values:
- * FRAME_ACCEPTED: frame is being transmited, transmitter is busy
- * FRAME_QUEUED: frame is being transmitted, there's more room in
- * the transmitter for additional packet(s)
- * FRAME_ERROR:
- * FRAME_DROPPED: there was some error
- */
-
-static int MUNICH_send_packet(struct net_device *dev, struct sk_buff *skb)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct slicecom_privdata *hw = ch->HW_privdata;
-
- /* Send it to the debug facility too if needed: */
-
- if (ch->debug_flags & DEBUG_HW_TX)
- comx_debug_bytes(dev, skb->data, skb->len, "MUNICH_send_packet");
-
- /* If the line is inactive, don't accept: */
-
- /* TODO: atgondolni hogy mi is legyen itt */
- /* if (!(ch->line_status & LINE_UP)) return FRAME_DROPPED; */
-
- /* More check, to be sure: */
-
- if (skb->len > TXBUFFER_SIZE)
- {
- ch->stats.tx_errors++;
- kfree_skb(skb);
- return FRAME_ERROR;
- }
-
- /* Maybe you have to disable irq's while programming the hw: */
-
- spin_lock_irqsave(&mister_lock, flags);
-
- /* And more check: */
-
- if (hw->busy >= TX_DESC_MAX - 1)
- {
- printk(KERN_ERR
- "%s: Transmitter called while busy... dropping frame, busy = %d\n",
- dev->name, hw->busy);
- spin_unlock_irqrestore(&mister_lock, flags);
- kfree_skb(skb);
- return FRAME_DROPPED;
- }
-
- if (hw->busy >= 0)
- hw->tx_ring_hist[hw->busy]++;
- /* DELL: */
- else
- printk("slicecom: %s: FATAL: busy = %d\n", dev->name, hw->busy);
-
-// /* DEL: */
-// printk("slicecom: %s: _send_packet called, busy = %d\n", dev->name, hw->busy );
-
- /* Packet can go, update stats: */
-
- ch->stats.tx_packets++;
- ch->stats.tx_bytes += skb->len;
-
- /* Pass the packet to the HW: */
- /* Step forward with the transmit descriptors: */
-
- hw->tx_desc_ptr = (hw->tx_desc_ptr + 1) % TX_DESC_MAX;
-
- memcpy(&(hw->tx_data[hw->tx_desc_ptr][0]), skb->data, skb->len);
- hw->tx_desc[hw->tx_desc_ptr].no = skb->len;
-
- /* We don't issue any command, just step with the HOLD bit */
-
- hw->tx_desc[hw->tx_desc_ptr].hold = 1;
- hw->tx_desc[(hw->tx_desc_ptr + TX_DESC_MAX - 1) % TX_DESC_MAX].hold = 0;
-
-#ifdef COMX_NEW
- dev_kfree_skb(skb);
-#endif
- /* csomag kerult a Tx ringbe: */
-
- hw->busy++;
-
- /* Report it: */
-
- if (ch->debug_flags & DEBUG_HW_TX)
- comx_debug(dev, "%s: MUNICH_send_packet was successful\n\n", dev->name);
-
- if (hw->busy >= TX_DESC_MAX - 1)
- {
- spin_unlock_irqrestore(&mister_lock, flags);
- return FRAME_ACCEPTED;
- }
-
- spin_unlock_irqrestore(&mister_lock, flags);
-
- /* All done */
-
- return FRAME_QUEUED;
-}
-
-/*
- * Interrupt handler routine.
- * Called by the Linux kernel.
- * BEWARE! The interrupts are enabled on the call!
- */
-static irqreturn_t MUNICH_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct sk_buff *skb;
- int length;
- int rx_status;
- int work; /* hany esemenyt kezeltem mar le */
- u32 *bar1;
- u8 *lbi;
- u32 stat, /* az esemenyek, amiket a ebben a loop korben le kell meg kezelni */
- race_stat = 0, /* race eseten ebben uzenek magamnak hogy mit kell meg lekezelni */
- ack; /* ezt fogom a vegen a STAT-ba irni, kiveszek belole 1-1 bitet ha */
-
- /* az adott dolgot nem kell ack-olni mert volt vele munkam, es */
- /* legjobb ha visszaterek ide megegyszer */
- munich_intq_t int_info;
-
- struct net_device *dev;
- struct comx_channel *ch;
- struct slicecom_privdata *hw;
- munich_board_t *board = (munich_board_t *) dev_id;
- int channel;
-
- // , boardnum = (int)dev_id;
-
- // board = munich_boards + boardnum;
- bar1 = board->bar1;
- lbi = board->lbi;
-
- // Do not uncomment this under heavy load! :->
- // printk("MUNICH_interrupt: masked STAT=0x%08x, tiq=0x%08x, riq=0x%08x, piq=0x%08x\n", stat, board->tiq[0].all, board->riq[0].all, board->piq[0].all );
-
- for (work = 0; (stat = (race_stat | (readl(MUNICH_VIRT(STAT)) & ~STAT_NOT_HANDLED_BY_INTERRUPT))) && (work < MAX_WORK - 1); work++)
- {
- ack = stat & (STAT_PRI | STAT_PTI | STAT_LBII);
-
- /* Handle the interrupt information in the Rx queue. We don't really trust */
- /* info from this queue, because it can be overflowed, so later check */
- /* every Rx ring for received packets. But there are some errors which can't */
- /* be counted from the Rx rings, so we parse it. */
-
- int_info = board->riq[board->riq_ptr];
- if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info van */
- {
- ack &= ~STAT_PRI; /* don't ack the interrupt, we had some work to do */
-
- channel = PCM_INT_CHANNEL(int_info.all);
- dev = board->twins[channel];
-
- if (dev == NULL)
- {
- printk
- ("MUNICH_interrupt: got an Rx interrupt info for NULL device "
- "%s.twins[%d], int_info = 0x%08x\n", board->devname,
- channel, int_info.all);
- goto go_for_next_interrupt;
- }
-
- ch = netdev_priv(dev);
- hw = (struct slicecom_privdata *)ch->HW_privdata;
-
- // printk("Rx STAT=0x%08x int_info=0x%08x rx_desc_ptr=%d rx_desc.status=0x%01x\n",
- // stat, int_info.all, hw->rx_desc_ptr, hw->rx_desc[ hw->rx_desc_ptr ].status );
-
- if (int_info.all & PCM_INT_HI)
- printk("SliceCOM: %s: Host Initiated interrupt\n", dev->name);
- if (int_info.all & PCM_INT_IFC)
- printk("SliceCOM: %s: Idle/Flag Change\n", dev->name);
- /* TOD: jo ez az Idle/Flag Change valamire? - azonnal latszik belole hogy mikor ad a masik oldal */
- /* TOD: ilyen IT most nem is jon, mert ki van maszkolva az interrupt, biztosan kell ez? */
-
- if (int_info.all & PCM_INT_FO)
- /* Internal buffer (RB) overrun */
- ch->stats.rx_over_errors++; /* TOD: Ez azt jelenti hogy a belso RB nem volt hozzaferheto, es ezert kihagyott valamit. De nem csak csomag lehetett, hanem esemeny, stb. is. lasd page 247. Ezzel a 'cat status'-hoz igazodok, de a netdevice.h szerint nem egyertelmu hogy ide ez kellene. Nem lehet hogy rx_missed ? */
- /* DE: nem gotozok sehova, elvileg jo igy */
- /* kesobb meg visszaterek az FO-ra, ha packet-FO volt. Keresd a "packet-FO"-t. */
- if (int_info.all & PCM_INT_FI) /* frame received, but we do not trust the int_info queue */
- if (int_info.all & PCM_INT_SF)
- { /* Short Frame: rovidebb mint a CRC */
- /* "rovidebb mint CRC+2byte" vizsgalat a "CRC+2"-nel */
- ch->stats.rx_length_errors++; /* TOD: noveljem? ne noveljem? */
- goto go_for_next_interrupt;
- }
-
- go_for_next_interrupt: /* One step in the interrupt queue */
- board->riq[board->riq_ptr].all = 0; /* megjelolom hogy itt meg nem jart a hw */
- board->riq_ptr = (board->riq_ptr + 1) % MUNICH_INTQMAX;
-
- }
-
- /* Check every Rx ring for incomed packets: */
-
- for (channel = 0; channel < 32; channel++)
- {
- dev = board->twins[channel];
-
- if (dev != NULL)
- {
- ch = netdev_priv(dev);
- hw = (struct slicecom_privdata *)ch->HW_privdata;
-
- rx_status = hw->rx_desc[hw->rx_desc_ptr].status;
-
- if (!(rx_status & 0x80)) /* mar jart itt a hardver */
- {
- ack &= ~STAT_PRI; /* Don't ack, we had some work */
-
- /* Ez most egy kicsit zuros, mert itt mar nem latom az int_infot */
- if (rx_status & RX_STATUS_ROF)
- ch->stats.rx_over_errors++; /* TOD: 'cat status'-hoz igazodok */
-
- if (rx_status & RX_STATUS_RA)
- /* Abort received or issued on channel */
- ch->stats.rx_frame_errors++; /* or HOLD bit in the descriptor */
- /* TOD: 'cat status'-hoz igazodok */
-
- if (rx_status & RX_STATUS_LFD)
- { /* Long Frame (longer then MFL in the MODE1) */
- ch->stats.rx_length_errors++;
- goto go_for_next_frame;
- }
-
- if (rx_status & RX_STATUS_NOB)
- { /* Not n*8 bits long frame - frame alignment */
- ch->stats.rx_frame_errors++; /* ez viszont nem igazodik a 'cat status'-hoz */
- goto go_for_next_frame;
- }
-
- if (rx_status & RX_STATUS_CRCO)
- { /* CRC error */
- ch->stats.rx_crc_errors++;
- goto go_for_next_frame;
- }
-
- if (rx_status & RX_STATUS_SF)
- { /* Short Frame: rovidebb mint CRC+2byte */
- ch->stats.rx_errors++; /* The HW does not set PCI_INT_ERR bit for this one, see page 246 */
- ch->stats.rx_length_errors++;
- goto go_for_next_frame;
- }
-
- if (rx_status != 0)
- {
- printk("SliceCOM: %s: unhandled rx_status: 0x%02x\n",
- dev->name, rx_status);
- goto go_for_next_frame;
- }
-
- /* frame received without errors: */
-
- length = hw->rx_desc[hw->rx_desc_ptr].bno;
- ch->stats.rx_packets++; /* Count only 'good' packets */
- ch->stats.rx_bytes += length;
-
- /* Allocate a larger skb and reserve the heading for efficiency: */
-
- if ((skb = dev_alloc_skb(length + 16)) == NULL)
- {
- ch->stats.rx_dropped++;
- goto go_for_next_frame;
- }
-
- /* Do bookkeeping: */
-
- skb_reserve(skb, 16);
- skb_put(skb, length);
- skb->dev = dev;
-
- /* Now copy the data into the buffer: */
-
- memcpy(skb->data, &(hw->rx_data[hw->rx_desc_ptr][0]), length);
-
- /* DEL: UGLY HACK!!!! */
- if (*((int *)skb->data) == 0x02000000 &&
- *(((int *)skb->data) + 1) == 0x3580008f)
- {
- printk("%s: swapping hack\n", dev->name);
- *((int *)skb->data) = 0x3580008f;
- *(((int *)skb->data) + 1) = 0x02000000;
- }
-
- if (ch->debug_flags & DEBUG_HW_RX)
- comx_debug_skb(dev, skb, "MUNICH_interrupt receiving");
-
- /* Pass it to the protocol entity: */
-
- ch->LINE_rx(dev, skb);
-
- go_for_next_frame:
- /* DEL: rafutott-e a HOLD bitre -detektalas */
- {
- if( ((rx_desc_t*)phys_to_virt(board->ccb->current_rx_desc[channel]))->hold
- && ((rx_desc_t*)phys_to_virt(board->ccb->current_rx_desc[channel]))->status != 0xff)
- hw->rafutott++; /* rafutott: hanyszor volt olyan hogy a current descriptoron HOLD bit volt, es a hw mar befejezte az irast (azaz a hw rafutott a HOLD bitre) */
- }
-
- // if( jiffies % 2 ) /* DELL: okozzunk egy kis Rx ring slipet :) */
- // {
- /* Step forward with the receive descriptors: */
- /* if you change this, change the copy of it below too! Search for: "RxSlip" */
- hw->rx_desc[(hw->rx_desc_ptr + RX_DESC_MAX - 1) % RX_DESC_MAX].hold = 1;
- hw->rx_desc[hw->rx_desc_ptr].status = 0xFF; /* megjelolom hogy itt meg nem jart a hw */
- hw->rx_desc[(hw->rx_desc_ptr + RX_DESC_MAX - 2) % RX_DESC_MAX].hold = 0;
- hw->rx_desc_ptr = (hw->rx_desc_ptr + 1) % RX_DESC_MAX;
- // }
- }
- }
- }
-
- stat &= ~STAT_PRI;
-
-// }
-
-// if( stat & STAT_PTI ) /* TOD: primko megvalositas: mindig csak egy esemenyt dolgozok fel, */
- /* es nem torlom a STAT-ot, ezert ujra visszajon ide a rendszer. Amikor */
- /* jon interrupt, de nincs mit feldolgozni, akkor torlom a STAT-ot. */
- /* 'needs a rewrite', de elso megoldasnak jo lesz */
-// {
- int_info = board->tiq[board->tiq_ptr];
- if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info van */
- {
- ack &= ~STAT_PTI; /* don't ack the interrupt, we had some work to do */
-
- channel = PCM_INT_CHANNEL(int_info.all);
- dev = board->twins[channel];
-
- if (dev == NULL)
- {
- printk("MUNICH_interrupt: got a Tx interrupt for NULL device "
- "%s.twins[%d], int_info = 0x%08x\n",
- board->isx21 ? "pcicom" : "slicecom", channel, int_info.all);
- goto go_for_next_tx_interrupt;
- }
-
- ch = netdev_priv(dev);
- hw = (struct slicecom_privdata *)ch->HW_privdata;
-
- // printk("Tx STAT=0x%08x int_info=0x%08x tiq_ptr=%d\n", stat, int_info.all, board->tiq_ptr );
-
- if (int_info.all & PCM_INT_FE2)
- { /* "Tx available" */
- /* do nothing */
- }
- else if (int_info.all & PCM_INT_FO)
- { /* Internal buffer (RB) overrun */
- ch->stats.rx_over_errors++;
- }
- else
- {
- printk("slicecom: %s: unhandled Tx int_info: 0x%08x\n",
- dev->name, int_info.all);
- }
-
- go_for_next_tx_interrupt:
- board->tiq[board->tiq_ptr].all = 0;
- board->tiq_ptr = (board->tiq_ptr + 1) % MUNICH_INTQMAX;
- }
-
- /* Check every Tx ring for incoming packets: */
-
- for (channel = 0; channel < 32; channel++)
- {
- dev = board->twins[channel];
-
- if (dev != NULL)
- {
- int newbusy;
-
- ch = netdev_priv(dev);
- hw = (struct slicecom_privdata *)ch->HW_privdata;
-
- /* We don't trust the "Tx available" info from the TIQ, but check */
- /* every ring if there is some free room */
-
- if (ch->init_status && netif_running(dev))
- {
- newbusy = ( TX_DESC_MAX + (& hw->tx_desc[ hw->tx_desc_ptr ]) -
- (tx_desc_t*)phys_to_virt(board->ccb->current_tx_desc[ hw->channel ]) ) % TX_DESC_MAX;
-
- if(newbusy < 0)
- {
- printk("slicecom: %s: FATAL: fresly computed busy = %d, HW: 0x%p, SW: 0x%p\n",
- dev->name, newbusy,
- phys_to_virt(board->ccb->current_tx_desc[hw->channel]),
- & hw->tx_desc[hw->tx_desc_ptr]);
- }
-
- /* Fogyott valami a Tx ringbol? */
-
- if (newbusy < hw->busy)
- {
- // ack &= ~STAT_PTI; /* Don't ack, we had some work */
- hw->busy = newbusy;
- if (ch->LINE_tx)
- ch->LINE_tx(dev); /* Report it to protocol driver */
- }
- else if (newbusy > hw->busy)
- printk("slicecom: %s: newbusy > hw->busy, this should not happen!\n", dev->name);
- }
- }
- }
- stat &= ~STAT_PTI;
-
- int_info = board->piq[board->piq_ptr];
- if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info van */
- {
- ack &= ~STAT_LBII; /* don't ack the interrupt, we had some work to do */
-
- /* We do not really use (yet) the interrupt info from this queue, */
-
- // printk("slicecom: %s: LBI Interrupt event: %08x\n", board->devname, int_info.all);
-
- if (!board->isx21)
- {
- slicecom_update_leds(board);
- slicecom_update_line_counters(board);
- }
-
- goto go_for_next_lbi_interrupt; /* To avoid warning about unused label */
-
- go_for_next_lbi_interrupt: /* One step in the interrupt queue */
- board->piq[board->piq_ptr].all = 0; /* megjelolom hogy itt meg nem jart a hw */
- board->piq_ptr = (board->piq_ptr + 1) % MUNICH_PIQMAX;
- }
- stat &= ~STAT_LBII;
-
- writel(ack, MUNICH_VIRT(STAT));
-
- if (stat & STAT_TSPA)
- {
- // printk("slicecom: %s: PCM TSP Asynchronous\n", board->devname);
- writel(STAT_TSPA, MUNICH_VIRT(STAT));
- stat &= ~STAT_TSPA;
- }
-
- if (stat & STAT_RSPA)
- {
- // printk("slicecom: %s: PCM RSP Asynchronous\n", board->devname);
- writel(STAT_RSPA, MUNICH_VIRT(STAT));
- stat &= ~STAT_RSPA;
- }
- if (stat)
- {
- printk("MUNICH_interrupt: unhandled interrupt, STAT=0x%08x\n",
- stat);
- writel(stat, MUNICH_VIRT(STAT)); /* ha valamit megsem kezeltunk le, azert ack-ot kuldunk neki */
- }
-
- }
- board->histogram[work]++;
-
- /* We can miss these if we reach the MAX_WORK */
- /* Count it to see how often it happens */
-
- if (race_stat & STAT_PRI)
- board->stat_pri_races_missed++;
- if (race_stat & STAT_PTI)
- board->stat_pti_races_missed++;
- return IRQ_HANDLED;
-}
-
-/*
- * Hardware open routine.
- * Called by comx (upper) layer when the user wants to bring up the interface
- * with ifconfig.
- * Initializes hardware, allocates resources etc.
- * Returns 0 on OK, or standard error value on error.
- */
-
-static int MUNICH_open(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct slicecom_privdata *hw = ch->HW_privdata;
- struct proc_dir_entry *procfile = ch->procdir->subdir;
- munich_board_t *board;
- munich_ccb_t *ccb;
-
- u32 *bar1;
- u8 *lbi;
- u32 stat;
- unsigned long flags, jiffs;
-
- int i, channel;
- u32 timeslots = hw->timeslots;
-
- board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
-
- bar1 = board->bar1;
- lbi = board->lbi;
-
- /* TODO: a timeslotok ellenorzese kell majd ide .. hat, biztos? mar a write_proc-ban is
- ellenorzom valamennyire.
- if (!dev->io || !dev->irq) return -ENODEV;
- */
-
- if (!board->pci)
- {
- printk("MUNICH_open: no %s board with boardnum = %d\n",
- ch->hardware->name, hw->boardnum);
- return -ENODEV;
- }
-
- spin_lock_irqsave(&mister_lock, flags);
- /* lock the section to avoid race with multiple opens and make sure
- that no interrupts get called while this lock is active */
-
- if (board->use_count == 0) /* bring up the board if it was unused */
- /* if fails, frees allocated resources and returns. */
- /* TOD: is it safe? nem kellene resetelni a kartyat? */
- {
- printk("MUNICH_open: %s: bringing up board\n", board->devname);
-
- /* Clean up the board's static struct if messed: */
-
- for (i = 0; i < 32; i++)
- board->twins[i] = NULL;
- for (i = 0; i < MAX_WORK; i++)
- board->histogram[i] = 0;
-
- board->lineup = 0;
-
- /* Allocate CCB: */
- board->ccb = kmalloc(sizeof(munich_ccb_t), GFP_KERNEL);
- if (board->ccb == NULL)
- {
- spin_unlock_irqrestore(&mister_lock, flags);
- return -ENOMEM;
- }
- memset((void *)board->ccb, 0, sizeof(munich_ccb_t));
- board->ccb->csa = virt_to_phys(board->ccb);
- ccb = board->ccb;
- for (i = 0; i < 32; i++)
- {
- ccb->timeslot_spec[i].tti = 1;
- ccb->timeslot_spec[i].rti = 1;
- }
-
- /* Interrupt queues: */
-
- board->tiq = kmalloc(MUNICH_INTQSIZE, GFP_KERNEL);
- if (board->tiq == NULL)
- {
- spin_unlock_irqrestore(&mister_lock, flags);
- return -ENOMEM;
- }
- memset((void *)board->tiq, 0, MUNICH_INTQSIZE);
-
- board->riq = kmalloc(MUNICH_INTQSIZE, GFP_KERNEL);
- if (board->riq == NULL)
- {
- spin_unlock_irqrestore(&mister_lock, flags);
- return -ENOMEM;
- }
- memset((void *)board->riq, 0, MUNICH_INTQSIZE);
-
- board->piq = kmalloc(MUNICH_PIQSIZE, GFP_KERNEL);
- if (board->piq == NULL)
- {
- spin_unlock_irqrestore(&mister_lock, flags);
- return -ENOMEM;
- }
- memset((void *)board->piq, 0, MUNICH_PIQSIZE);
-
- board->tiq_ptr = 0;
- board->riq_ptr = 0;
- board->piq_ptr = 0;
-
- /* Request irq: */
-
- board->irq = 0;
-
- /* (char*) cast to avoid warning about discarding volatile: */
- if (request_irq(board->pci->irq, MUNICH_interrupt, 0,
- (char *)board->devname, (void *)board))
- {
- printk("MUNICH_open: %s: unable to obtain irq %d\n", board->devname,
- board->pci->irq);
- /* TOD: free other resources (a sok malloc feljebb) */
- spin_unlock_irqrestore(&mister_lock, flags);
- return -EAGAIN;
- }
- board->irq = board->pci->irq; /* csak akkor legyen != 0, ha tenyleg le van foglalva nekunk */
-
- /* Programming device: */
-
- /* Reset the board like a power-on: */
- /* TOD:
- - It is not a real power-on: if a DMA transaction fails with master abort, the board
- stays in half-dead state.
- - It doesn't reset the FALC line driver */
-
- pci_write_config_dword(board->pci, MUNICH_PCI_PCIRES, 0xe0000);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- pci_write_config_dword(board->pci, MUNICH_PCI_PCIRES, 0);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
-
- writel(virt_to_phys(&ccb->csa), MUNICH_VIRT(CCBA));
- writel(virt_to_phys( board->tiq ), MUNICH_VIRT(TIQBA));
- writel(MUNICH_INTQLEN, MUNICH_VIRT(TIQL));
- writel(virt_to_phys( board->riq ), MUNICH_VIRT(RIQBA));
- writel(MUNICH_INTQLEN, MUNICH_VIRT(RIQL));
- writel(virt_to_phys( board->piq ), MUNICH_VIRT(PIQBA));
- writel(MUNICH_PIQLEN, MUNICH_VIRT(PIQL));
-
- /* Put the magic values into the registers: */
-
- writel(MODE1_MAGIC, MUNICH_VIRT(MODE1));
- writel(MODE2_MAGIC, MUNICH_VIRT(MODE2));
-
- writel(LREG0_MAGIC, MUNICH_VIRT(LREG0));
- writel(LREG1_MAGIC, MUNICH_VIRT(LREG1));
- writel(LREG2_MAGIC, MUNICH_VIRT(LREG2));
- writel(LREG3_MAGIC, MUNICH_VIRT(LREG3));
- writel(LREG4_MAGIC, MUNICH_VIRT(LREG4));
- writel(LREG5_MAGIC, MUNICH_VIRT(LREG5));
-
- writel(LCONF_MAGIC1, MUNICH_VIRT(LCONF)); /* reset the DMSM */
- writel(LCONF_MAGIC2, MUNICH_VIRT(LCONF)); /* enable the DMSM */
-
- writel(~0, MUNICH_VIRT(TXPOLL));
- writel(board->isx21 ? 0x1400 : 0xa000, MUNICH_VIRT(GPDIR));
-
- if (readl(MUNICH_VIRT(STAT))) writel(readl(MUNICH_VIRT(STAT)), MUNICH_VIRT(STAT));
-
- ccb->action_spec = CCB_ACTIONSPEC_RES | CCB_ACTIONSPEC_IA;
- writel(CMD_ARPCM, MUNICH_VIRT(CMD)); /* Start the PCM core reset */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
-
- stat = 0; /* Wait for the action to complete max. 1 second */
- jiffs = jiffies;
- while (!((stat = readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCMF)) && time_before(jiffies, jiffs + HZ))
- {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
-
- if (stat & STAT_PCMF)
- {
- printk(KERN_ERR
- "MUNICH_open: %s: Initial ARPCM failed. STAT=0x%08x\n",
- board->devname, stat);
- writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT));
- free_irq(board->irq, (void *)board); /* TOD: free other resources too *//* maybe shut down hw? */
- board->irq = 0;
- spin_unlock_irqrestore(&mister_lock, flags);
- return -EAGAIN;
- }
- else if (!(stat & STAT_PCMA))
- {
- printk(KERN_ERR
- "MUNICH_open: %s: Initial ARPCM timeout. STAT=0x%08x\n",
- board->devname, stat);
- free_irq(board->irq, (void *)board); /* TOD: free other resources too *//* maybe shut off the hw? */
- board->irq = 0;
- spin_unlock_irqrestore(&mister_lock, flags);
- return -EIO;
- }
-
- writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT)); /* Acknowledge */
-
- if (board->isx21) writel(0, MUNICH_VIRT(GPDATA));
-
- printk("MUNICH_open: %s: succesful HW-open took %ld jiffies\n",
- board->devname, jiffies - jiffs);
-
- /* Set up the FALC hanging on the Local Bus: */
-
- if (!board->isx21)
- {
- writeb(0x0e, lbi + FMR1);
- writeb(0, lbi + LIM0);
- writeb(0xb0, lbi + LIM1); /* TODO: input threshold */
- writeb(0xf7, lbi + XPM0);
- writeb(0x02, lbi + XPM1);
- writeb(0x00, lbi + XPM2);
- writeb(0xf0, lbi + FMR0);
- writeb(0x80, lbi + PCD);
- writeb(0x80, lbi + PCR);
- writeb(0x00, lbi + LIM2);
- writeb(0x07, lbi + XC0);
- writeb(0x3d, lbi + XC1);
- writeb(0x05, lbi + RC0);
- writeb(0x00, lbi + RC1);
- writeb(0x83, lbi + FMR2);
- writeb(0x9f, lbi + XSW);
- writeb(0x0f, lbi + XSP);
- writeb(0x00, lbi + TSWM);
- writeb(0xe0, lbi + MODE);
- writeb(0xff, lbi + IDLE); /* Idle Code to send in unused timeslots */
- writeb(0x83, lbi + IPC); /* interrupt query line mode: Push/pull output, active high */
- writeb(0xbf, lbi + IMR3); /* send an interrupt every second */
-
- slicecom_set_framing(hw->boardnum, board->framing);
- slicecom_set_linecode(hw->boardnum, board->linecode);
- slicecom_set_clock_source(hw->boardnum, board->clock_source);
- slicecom_set_loopback(hw->boardnum, board->loopback);
-
- memset((void *)board->intervals, 0, sizeof(board->intervals));
- board->current_interval = 0;
- board->elapsed_seconds = 0;
- board->ses_seconds = 0;
- board->is_unavailable = 0;
- board->no_ses_seconds = 0;
- board->deg_elapsed_seconds = 0;
- board->deg_cumulated_errors = 0;
- }
-
- /* Enable the interrupts last */
- /* These interrupts will be enabled. We do not need the others. */
-
- writel(readl(MUNICH_VIRT(IMASK)) & ~(STAT_PTI | STAT_PRI | STAT_LBII | STAT_TSPA | STAT_RSPA), MUNICH_VIRT(IMASK));
- }
-
- spin_unlock_irqrestore(&mister_lock, flags);
-
- dev->irq = board->irq; /* hogy szep legyen az ifconfig outputja */
- ccb = board->ccb; /* TODO: ez igy csunya egy kicsit hogy benn is meg kinn is beletoltom :( */
-
- spin_lock_irqsave(&mister_lock, flags);
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
-
- /* Check if the selected timeslots aren't used already */
-
- for (i = 0; i < 32; i++)
- if (((1 << i) & timeslots) && !ccb->timeslot_spec[i].tti)
- {
- printk("MUNICH_open: %s: timeslot %d already used by %s\n",
- dev->name, i, board->twins[ccb->timeslot_spec[i].txchannel]->name);
- spin_unlock_irqrestore(&mister_lock, flags);
- return -EBUSY; /* TODO: lehet hogy valami mas errno kellene? */
- }
-
- /* find a free channel: */
- /* TODO: ugly, rewrite it */
-
- for (channel = 0; channel <= 32; channel++)
- {
- if (channel == 32)
- { /* not found a free one */
- printk
- ("MUNICH_open: %s: FATAL: can not find a free channel - this should not happen!\n",
- dev->name);
- spin_unlock_irqrestore(&mister_lock, flags);
- return -ENODEV;
- }
- if (board->twins[channel] == NULL)
- break; /* found the first free one */
- }
-
- board->lastcheck = jiffies; /* avoid checking uninitialized hardware channel */
-
- /* Open the channel. If fails, calls MUNICH_close() to properly free resources and stop the HW */
-
- hw->channel = channel;
- board->twins[channel] = dev;
-
- board->use_count++; /* meg nem nyitottuk meg a csatornat, de a twins-ben
- mar elfoglaltunk egyet, es ha a _close-t akarjuk hivni, akkor ez kell. */
- for (i = 0; i < 32; i++)
- if ((1 << i) & timeslots)
- {
- ccb->timeslot_spec[i].tti = 0;
- ccb->timeslot_spec[i].txchannel = channel;
- ccb->timeslot_spec[i].txfillmask = ~0;
-
- ccb->timeslot_spec[i].rti = 0;
- ccb->timeslot_spec[i].rxchannel = channel;
- ccb->timeslot_spec[i].rxfillmask = ~0;
- }
-
- if (!board->isx21) rework_idle_channels(dev);
-
- memset((void *)&(hw->tx_desc), 0, TX_DESC_MAX * sizeof(tx_desc_t));
- memset((void *)&(hw->rx_desc), 0, RX_DESC_MAX * sizeof(rx_desc_t));
-
- for (i = 0; i < TX_DESC_MAX; i++)
- {
- hw->tx_desc[i].fe = 1;
- hw->tx_desc[i].fnum = 2;
- hw->tx_desc[i].data = virt_to_phys( & (hw->tx_data[i][0]) );
- hw->tx_desc[i].next = virt_to_phys( & (hw->tx_desc[ (i+1) % TX_DESC_MAX ]) );
-
- }
- hw->tx_desc_ptr = 0; /* we will send an initial packet so it is correct: "oda irtunk utoljara" */
- hw->busy = 0;
- hw->tx_desc[hw->tx_desc_ptr].hold = 1;
- hw->tx_desc[hw->tx_desc_ptr].no = 1; /* TOD: inkabb csak 0 hosszut kuldjunk ki az initkor? */
-
- for (i = 0; i < RX_DESC_MAX; i++)
- {
- hw->rx_desc[i].no = RXBUFFER_SIZE;
- hw->rx_desc[i].data = virt_to_phys(&(hw->rx_data[i][0]));
- hw->rx_desc[i].next = virt_to_phys(&(hw->rx_desc[(i+1) % RX_DESC_MAX]));
- hw->rx_desc[i].status = 0xFF;
- }
- hw->rx_desc_ptr = 0;
-
- hw->rx_desc[(hw->rx_desc_ptr + RX_DESC_MAX - 2) % RX_DESC_MAX].hold = 1;
-
- memset((void *)&ccb->channel_spec[channel], 0, sizeof(channel_spec_t));
-
- ccb->channel_spec[channel].ti = 0; /* Transmit off */
- ccb->channel_spec[channel].to = 1;
- ccb->channel_spec[channel].ta = 0;
-
- ccb->channel_spec[channel].th = 1; /* Transmit hold */
-
- ccb->channel_spec[channel].ri = 0; /* Receive off */
- ccb->channel_spec[channel].ro = 1;
- ccb->channel_spec[channel].ra = 0;
-
- ccb->channel_spec[channel].mode = 3; /* HDLC */
-
- ccb->action_spec = CCB_ACTIONSPEC_IN | (channel << 8);
- writel(CMD_ARPCM, MUNICH_VIRT(CMD));
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
-
- spin_unlock_irqrestore(&mister_lock, flags);
-
- stat = 0;
- jiffs = jiffies;
- while (!((stat = readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCMF)) && time_before(jiffies, jiffs + HZ))
- {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
-
- if (stat & STAT_PCMF)
- {
- printk(KERN_ERR "MUNICH_open: %s: %s channel %d off failed\n",
- dev->name, board->devname, channel);
- writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT));
- MUNICH_close(dev);
- return -EAGAIN;
- }
- else if (!(stat & STAT_PCMA))
- {
- printk(KERN_ERR "MUNICH_open: %s: %s channel %d off timeout\n",
- dev->name, board->devname, channel);
- MUNICH_close(dev);
- return -EIO;
- }
-
- writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT));
- // printk("MUNICH_open: %s: succesful channel off took %ld jiffies\n", board->devname, jiffies-jiffs);
-
- spin_lock_irqsave(&mister_lock, flags);
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
-
- ccb->channel_spec[channel].ifc = 1; /* 1 .. 'Idle/Flag change' interrupt letiltva */
- ccb->channel_spec[channel].fit = 1;
- ccb->channel_spec[channel].nitbs = 1;
- ccb->channel_spec[channel].itbs = 2;
-
- /* TODOO: lehet hogy jo lenne igy, de utana kellene nezni hogy nem okoz-e fragmentaciot */
- // ccb->channel_spec[channel].itbs = 2 * number_of_timeslots;
- // printk("open: %s: number_of_timeslots: %d\n", dev->name, number_of_timeslots);
-
- ccb->channel_spec[channel].mode = 3; /* HDLC */
- ccb->channel_spec[channel].ftda = virt_to_phys(&(hw->tx_desc));
- ccb->channel_spec[channel].frda = virt_to_phys(&(hw->rx_desc[0]));
-
- ccb->channel_spec[channel].ti = 1; /* Transmit init */
- ccb->channel_spec[channel].to = 0;
- ccb->channel_spec[channel].ta = 1;
-
- ccb->channel_spec[channel].th = 0;
-
- ccb->channel_spec[channel].ri = 1; /* Receive init */
- ccb->channel_spec[channel].ro = 0;
- ccb->channel_spec[channel].ra = 1;
-
- ccb->action_spec = CCB_ACTIONSPEC_ICO | (channel << 8);
- writel(CMD_ARPCM, MUNICH_VIRT(CMD)); /* Start the channel init */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
-
- spin_unlock_irqrestore(&mister_lock, flags);
-
- stat = 0; /* Wait for the action to complete max. 1 second */
- jiffs = jiffies;
- while (!((stat = readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCMF)) && time_before(jiffies, jiffs + HZ))
- {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
-
- if (stat & STAT_PCMF)
- {
- printk(KERN_ERR "MUNICH_open: %s: channel open ARPCM failed\n",
- board->devname);
- writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT));
- MUNICH_close(dev);
- return -EAGAIN;
- }
- else if (!(stat & STAT_PCMA))
- {
- printk(KERN_ERR "MUNICH_open: %s: channel open ARPCM timeout\n",
- board->devname);
- MUNICH_close(dev);
- return -EIO;
- }
-
- writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT));
- // printk("MUNICH_open: %s: succesful channel open took %ld jiffies\n", board->devname, jiffies-jiffs);
-
- spin_lock_irqsave(&mister_lock, flags);
-
- ccb->channel_spec[channel].nitbs = 0; /* once ITBS defined, these must be 0 */
- ccb->channel_spec[channel].itbs = 0;
-
- if (board->isx21)
- {
- init_timer(&board->modemline_timer);
- board->modemline_timer.data = (unsigned long)board;
- board->modemline_timer.function = pcicom_modemline;
- board->modemline_timer.expires = jiffies + HZ;
- add_timer((struct timer_list *)&board->modemline_timer);
- }
-
- /* It is done. Declare that we're open: */
- hw->busy = 0; /* It may be 1 if the frame at Tx init already ended, but it is not */
- /* a real problem: we compute hw->busy on every interrupt */
- hw->rafutott = 0;
- ch->init_status |= HW_OPEN;
-
- /* Initialize line state: */
- if (board->lineup)
- ch->line_status |= LINE_UP;
- else
- ch->line_status &= ~LINE_UP;
-
- /* Remove w attribute from /proc files associated to hw parameters:
- no write when the device is open */
-
- for (; procfile; procfile = procfile->next)
- if (strcmp(procfile->name, FILENAME_BOARDNUM) == 0 ||
- strcmp(procfile->name, FILENAME_TIMESLOTS) == 0)
- procfile->mode = S_IFREG | 0444;
-
- spin_unlock_irqrestore(&mister_lock, flags);
-
- return 0;
-}
-
-/*
- * Hardware close routine.
- * Called by comx (upper) layer when the user wants to bring down the interface
- * with ifconfig.
- * We also call it from MUNICH_open, if the open fails.
- * Brings down hardware, frees resources, stops receiver
- * Returns 0 on OK, or standard error value on error.
- */
-
-static int MUNICH_close(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct slicecom_privdata *hw = ch->HW_privdata;
- struct proc_dir_entry *procfile = ch->procdir->subdir;
- munich_board_t *board;
- munich_ccb_t *ccb;
-
- u32 *bar1;
- u32 timeslots = hw->timeslots;
- int stat, i, channel = hw->channel;
- unsigned long jiffs;
-
- board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
-
- ccb = board->ccb;
- bar1 = board->bar1;
-
- if (board->isx21)
- del_timer((struct timer_list *)&board->modemline_timer);
-
- spin_lock_irqsave(&mister_lock, flags);
-
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
-
- /* Disable receiver for the channel: */
-
- for (i = 0; i < 32; i++)
- if ((1 << i) & timeslots)
- {
- ccb->timeslot_spec[i].tti = 1;
- ccb->timeslot_spec[i].txfillmask = 0; /* just to be double-sure :) */
-
- ccb->timeslot_spec[i].rti = 1;
- ccb->timeslot_spec[i].rxfillmask = 0;
- }
-
- if (!board->isx21) rework_idle_channels(dev);
-
- ccb->channel_spec[channel].ti = 0; /* Receive off, Transmit off */
- ccb->channel_spec[channel].to = 1;
- ccb->channel_spec[channel].ta = 0;
- ccb->channel_spec[channel].th = 1;
-
- ccb->channel_spec[channel].ri = 0;
- ccb->channel_spec[channel].ro = 1;
- ccb->channel_spec[channel].ra = 0;
-
- board->twins[channel] = NULL;
-
- ccb->action_spec = CCB_ACTIONSPEC_IN | (channel << 8);
- writel(CMD_ARPCM, MUNICH_VIRT(CMD));
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
-
- spin_unlock_irqrestore(&mister_lock, flags);
-
- stat = 0;
- jiffs = jiffies;
- while (!((stat = readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCMF)) && time_before(jiffies, jiffs + HZ))
- {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
-
- if (stat & STAT_PCMF)
- {
- printk(KERN_ERR
- "MUNICH_close: %s: FATAL: channel off ARPCM failed, not closing!\n",
- dev->name);
- writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMF, MUNICH_VIRT(STAT));
- /* If we return success, the privdata (and the descriptor list) will be freed */
- return -EIO;
- }
- else if (!(stat & STAT_PCMA))
- printk(KERN_ERR "MUNICH_close: %s: channel off ARPCM timeout\n",
- board->devname);
-
- writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT));
- // printk("MUNICH_close: %s: channel off took %ld jiffies\n", board->devname, jiffies-jiffs);
-
- spin_lock_irqsave(&mister_lock, flags);
-
- if (board->use_count) board->use_count--;
-
- if (!board->use_count) /* we were the last user of the board */
- {
- printk("MUNICH_close: bringing down board %s\n", board->devname);
-
- /* program down the board: */
-
- writel(0x0000FF7F, MUNICH_VIRT(IMASK)); /* do not send any interrupts */
- writel(0, MUNICH_VIRT(CMD)); /* stop the timer if someone started it */
- writel(~0U, MUNICH_VIRT(STAT)); /* if an interrupt came between the cli()-sti(), quiet it */
- if (ch->hardware == &pcicomhw)
- writel(0x1400, MUNICH_VIRT(GPDATA));
-
- /* Put the board into 'reset' state: */
- pci_write_config_dword(board->pci, MUNICH_PCI_PCIRES, 0xe0000);
-
- /* Free irq and other resources: */
- if (board->irq)
- free_irq(board->irq, (void *)board); /* Ha nem inicializalta magat, akkor meg nincs irq */
- board->irq = 0;
-
- /* Free CCB and the interrupt queues */
- if (board->ccb) kfree((void *)board->ccb);
- if (board->tiq) kfree((void *)board->tiq);
- if (board->riq) kfree((void *)board->riq);
- if (board->piq) kfree((void *)board->piq);
- board->ccb = NULL;
- board->tiq = board->riq = board->piq = NULL;
- }
-
- /* Enable setting of hw parameters */
- for (; procfile; procfile = procfile->next)
- if (strcmp(procfile->name, FILENAME_BOARDNUM) == 0 ||
- strcmp(procfile->name, FILENAME_TIMESLOTS) == 0)
- procfile->mode = S_IFREG | 0644;
-
- /* We're not open anymore */
- ch->init_status &= ~HW_OPEN;
-
- spin_unlock_irqrestore(&mister_lock, flags);
-
- return 0;
-}
-
-/*
- * Give (textual) status information.
- * The text it returns will be a part of what appears when the user does a
- * cat /proc/comx/comx[n]/status
- * Don't write more than PAGESIZE.
- * Return value: number of bytes written (length of the string, incl. 0)
- */
-
-static int MUNICH_minden(struct net_device *dev, char *page)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct slicecom_privdata *hw = ch->HW_privdata;
- munich_board_t *board;
- struct net_device *devp;
-
- u8 *lbi;
- e1_stats_t *curr_int, *prev_int;
- e1_stats_t last4, last96; /* sum of last 4, resp. last 96 intervals */
- unsigned *sump, /* running pointer for the sum data */
- *p; /* running pointer for the interval data */
-
- int len = 0;
- u8 frs0, frs1;
- u8 fmr2;
- int i, j;
- u32 timeslots;
-
- board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
-
- lbi = board->lbi;
- curr_int = &board->intervals[board->current_interval];
- prev_int =
- &board->
- intervals[(board->current_interval + SLICECOM_BOARD_INTERVALS_SIZE -
- 1) % SLICECOM_BOARD_INTERVALS_SIZE];
-
- if (!board->isx21)
- {
- frs0 = readb(lbi + FRS0);
- fmr2 = readb(lbi + FMR2);
- len += scnprintf(page + len, PAGE_SIZE - len, "Controller status:\n");
- if (frs0 == 0)
- len += scnprintf(page + len, PAGE_SIZE - len, "\tNo alarms\n");
- else
- {
- if (frs0 & FRS0_LOS)
- len += scnprintf(page + len, PAGE_SIZE - len, "\tLoss Of Signal\n");
- else
- {
- if (frs0 & FRS0_AIS)
- len += scnprintf(page + len, PAGE_SIZE - len,
- "\tAlarm Indication Signal\n");
- else
- {
- if (frs0 & FRS0_AUXP)
- len += scnprintf(page + len, PAGE_SIZE - len,
- "\tAuxiliary Pattern Indication\n");
- if (frs0 & FRS0_LFA)
- len += scnprintf(page + len, PAGE_SIZE - len,
- "\tLoss of Frame Alignment\n");
- else
- {
- if (frs0 & FRS0_RRA)
- len += scnprintf(page + len, PAGE_SIZE - len,
- "\tReceive Remote Alarm\n");
-
- /* You can't set this framing with the /proc interface, but it */
- /* may be good to have here this alarm if you set it by hand: */
-
- if ((board->framing == SLICECOM_FRAMING_CRC4) &&
- (frs0 & FRS0_LMFA))
- len += scnprintf(page + len, PAGE_SIZE - len,
- "\tLoss of CRC4 Multiframe Alignment\n");
-
- if (((fmr2 & 0xc0) == 0xc0) && (frs0 & FRS0_NMF))
- len += scnprintf(page + len, PAGE_SIZE - len,
- "\tNo CRC4 Multiframe alignment Found after 400 msec\n");
- }
- }
- }
- }
-
- frs1 = readb(lbi + FRS1);
- if (FRS1_XLS & frs1)
- len += scnprintf(page + len, PAGE_SIZE - len,
- "\tTransmit Line Short\n");
-
- /* debug Rx ring: DEL: - vagy meghagyni, de akkor legyen kicsit altalanosabb */
- }
-
- len += scnprintf(page + len, PAGE_SIZE - len, "Rx ring:\n");
- len += scnprintf(page + len, PAGE_SIZE - len, "\trafutott: %d\n", hw->rafutott);
- len += scnprintf(page + len, PAGE_SIZE - len,
- "\tlastcheck: %ld, jiffies: %ld\n", board->lastcheck, jiffies);
- len += scnprintf(page + len, PAGE_SIZE - len, "\tbase: %08x\n",
- (u32) virt_to_phys(&hw->rx_desc[0]));
- len += scnprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %d\n",
- hw->rx_desc_ptr);
- len += scnprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %08x\n",
- (u32) virt_to_phys(&hw->rx_desc[hw->rx_desc_ptr]));
- len += scnprintf(page + len, PAGE_SIZE - len, "\thw_curr_ptr: %08x\n",
- board->ccb->current_rx_desc[hw->channel]);
-
- for (i = 0; i < RX_DESC_MAX; i++)
- len += scnprintf(page + len, PAGE_SIZE - len, "\t%08x %08x %08x %08x\n",
- *((u32 *) & hw->rx_desc[i] + 0),
- *((u32 *) & hw->rx_desc[i] + 1),
- *((u32 *) & hw->rx_desc[i] + 2),
- *((u32 *) & hw->rx_desc[i] + 3));
-
- if (!board->isx21)
- {
- len += scnprintf(page + len, PAGE_SIZE - len,
- "Interfaces using this board: (channel-group, interface, timeslots)\n");
- for (i = 0; i < 32; i++)
- {
- devp = board->twins[i];
- if (devp != NULL)
- {
- timeslots =
- ((struct slicecom_privdata *)((struct comx_channel *)devp->
- priv)->HW_privdata)->
- timeslots;
- len += scnprintf(page + len, PAGE_SIZE - len, "\t%2d %s: ", i,
- devp->name);
- for (j = 0; j < 32; j++)
- if ((1 << j) & timeslots)
- len += scnprintf(page + len, PAGE_SIZE - len, "%d ", j);
- len += scnprintf(page + len, PAGE_SIZE - len, "\n");
- }
- }
- }
-
- len += scnprintf(page + len, PAGE_SIZE - len, "Interrupt work histogram:\n");
- for (i = 0; i < MAX_WORK; i++)
- len += scnprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i,
- board->histogram[i], (i &&
- ((i + 1) % 4 == 0 ||
- i == MAX_WORK - 1)) ? '\n' : ' ');
-
- len += scnprintf(page + len, PAGE_SIZE - len, "Tx ring histogram:\n");
- for (i = 0; i < TX_DESC_MAX; i++)
- len += scnprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i,
- hw->tx_ring_hist[i], (i &&
- ((i + 1) % 4 == 0 ||
- i ==
- TX_DESC_MAX - 1)) ? '\n' : ' ');
-
- if (!board->isx21)
- {
-
- memset((void *)&last4, 0, sizeof(last4));
- memset((void *)&last96, 0, sizeof(last96));
-
- /* Calculate the sum of last 4 intervals: */
-
- for (i = 1; i <= 4; i++)
- {
- p = (unsigned *)&board->intervals[(board->current_interval +
- SLICECOM_BOARD_INTERVALS_SIZE -
- i) % SLICECOM_BOARD_INTERVALS_SIZE];
- sump = (unsigned *)&last4;
- for (j = 0; j < (sizeof(e1_stats_t) / sizeof(unsigned)); j++)
- sump[j] += p[j];
- }
-
- /* Calculate the sum of last 96 intervals: */
-
- for (i = 1; i <= 96; i++)
- {
- p = (unsigned *)&board->intervals[(board->current_interval +
- SLICECOM_BOARD_INTERVALS_SIZE -
- i) % SLICECOM_BOARD_INTERVALS_SIZE];
- sump = (unsigned *)&last96;
- for (j = 0; j < (sizeof(e1_stats_t) / sizeof(unsigned)); j++)
- sump[j] += p[j];
- }
-
- len += scnprintf(page + len, PAGE_SIZE - len,
- "Data in current interval (%d seconds elapsed):\n",
- board->elapsed_seconds);
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
- curr_int->line_code_violations,
- curr_int->path_code_violations, curr_int->e_bit_errors);
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
- curr_int->slip_secs, curr_int->fr_loss_secs,
- curr_int->line_err_secs, curr_int->degraded_mins);
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
- curr_int->errored_secs, curr_int->bursty_err_secs,
- curr_int->severely_err_secs, curr_int->unavail_secs);
-
- len += scnprintf(page + len, PAGE_SIZE - len,
- "Data in Interval 1 (15 minutes):\n");
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
- prev_int->line_code_violations,
- prev_int->path_code_violations, prev_int->e_bit_errors);
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
- prev_int->slip_secs, prev_int->fr_loss_secs,
- prev_int->line_err_secs, prev_int->degraded_mins);
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
- prev_int->errored_secs, prev_int->bursty_err_secs,
- prev_int->severely_err_secs, prev_int->unavail_secs);
-
- len += scnprintf(page + len, PAGE_SIZE - len,
- "Data in last 4 intervals (1 hour):\n");
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
- last4.line_code_violations, last4.path_code_violations,
- last4.e_bit_errors);
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
- last4.slip_secs, last4.fr_loss_secs, last4.line_err_secs,
- last4.degraded_mins);
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
- last4.errored_secs, last4.bursty_err_secs,
- last4.severely_err_secs, last4.unavail_secs);
-
- len += scnprintf(page + len, PAGE_SIZE - len,
- "Data in last 96 intervals (24 hours):\n");
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n",
- last96.line_code_violations, last96.path_code_violations,
- last96.e_bit_errors);
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n",
- last96.slip_secs, last96.fr_loss_secs,
- last96.line_err_secs, last96.degraded_mins);
- len += scnprintf(page + len, PAGE_SIZE - len,
- " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n",
- last96.errored_secs, last96.bursty_err_secs,
- last96.severely_err_secs, last96.unavail_secs);
-
- }
-
-// len +=scnprintf( page + len, PAGE_SIZE - len, "Special events:\n" );
-// len +=scnprintf( page + len, PAGE_SIZE - len, "\tstat_pri/missed: %u / %u\n", board->stat_pri_races, board->stat_pri_races_missed );
-// len +=scnprintf( page + len, PAGE_SIZE - len, "\tstat_pti/missed: %u / %u\n", board->stat_pti_races, board->stat_pti_races_missed );
- return len;
-}
-
-/*
- * Memory dump function. Not used currently.
- */
-static int BOARD_dump(struct net_device *dev)
-{
- printk
- ("BOARD_dump() requested. It is unimplemented, it should not be called\n");
- return (-1);
-}
-
-/*
- * /proc file read function for the files registered by this module.
- * This function is called by the procfs implementation when a user
- * wants to read from a file registered by this module.
- * page is the workspace, start should point to the real start of data,
- * off is the file offset, data points to the file's proc_dir_entry
- * structure.
- * Returns the number of bytes copied to the request buffer.
- */
-
-static int munich_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct proc_dir_entry *file = (struct proc_dir_entry *)data;
- struct net_device *dev = file->parent->data;
- struct comx_channel *ch = netdev_priv(dev);
- struct slicecom_privdata *hw = ch->HW_privdata;
- munich_board_t *board;
-
- int len = 0, i;
- u32 timeslots = hw->timeslots;
-
- board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
-
- if (!strcmp(file->name, FILENAME_BOARDNUM))
- len = sprintf(page, "%d\n", hw->boardnum);
- else if (!strcmp(file->name, FILENAME_TIMESLOTS))
- {
- for (i = 0; i < 32; i++)
- if ((1 << i) & timeslots)
- len += scnprintf(page + len, PAGE_SIZE - len, "%d ", i);
- len += scnprintf(page + len, PAGE_SIZE - len, "\n");
- }
- else if (!strcmp(file->name, FILENAME_FRAMING))
- {
- i = 0;
- while (slicecom_framings[i].value &&
- slicecom_framings[i].value != board->framing)
- i++;
- len += scnprintf(page + len, PAGE_SIZE - len, "%s\n",
- slicecom_framings[i].name);
- }
- else if (!strcmp(file->name, FILENAME_LINECODE))
- {
- i = 0;
- while (slicecom_linecodes[i].value &&
- slicecom_linecodes[i].value != board->linecode)
- i++;
- len += scnprintf(page + len, PAGE_SIZE - len, "%s\n",
- slicecom_linecodes[i].name);
- }
- else if (!strcmp(file->name, FILENAME_CLOCK_SOURCE))
- {
- i = 0;
- while (slicecom_clock_sources[i].value &&
- slicecom_clock_sources[i].value != board->clock_source)
- i++;
- len +=
- scnprintf(page + len, PAGE_SIZE - len, "%s\n",
- slicecom_clock_sources[i].name);
- }
- else if (!strcmp(file->name, FILENAME_LOOPBACK))
- {
- i = 0;
- while (slicecom_loopbacks[i].value &&
- slicecom_loopbacks[i].value != board->loopback)
- i++;
- len += scnprintf(page + len, PAGE_SIZE - len, "%s\n",
- slicecom_loopbacks[i].name);
- }
- /* We set permissions to write-only for REG and LBIREG, but root can read them anyway: */
- else if (!strcmp(file->name, FILENAME_REG))
- {
- len += scnprintf(page + len, PAGE_SIZE - len,
- "%s: " FILENAME_REG ": write-only file\n", dev->name);
- }
- else if (!strcmp(file->name, FILENAME_LBIREG))
- {
- len += scnprintf(page + len, PAGE_SIZE - len,
- "%s: " FILENAME_LBIREG ": write-only file\n", dev->name);
- }
- else
- {
- printk("slicecom_read_proc: internal error, filename %s\n", file->name);
- return -EBADF;
- }
- /* file handling administration: count eof status, offset, start address
- and count: */
-
- if (off >= len)
- {
- *eof = 1;
- return 0;
- }
-
- *start = page + off;
- if (count >= len - off)
- *eof = 1;
- return min((off_t) count, (off_t) len - off);
-}
-
-/*
- * Write function for /proc files registered by us.
- * See the comment on read function above.
- * Beware! buffer is in userspace!!!
- * Returns the number of bytes written
- */
-
-static int munich_write_proc(struct file *file, const char *buffer,
- u_long count, void *data)
-{
- struct proc_dir_entry *entry = (struct proc_dir_entry *)data;
- struct net_device *dev = (struct net_device *)entry->parent->data;
- struct comx_channel *ch = netdev_priv(dev);
- struct slicecom_privdata *hw = ch->HW_privdata;
- munich_board_t *board;
-
- unsigned long ts, tmp_boardnum;
-
- u32 tmp_timeslots = 0;
- char *page, *p;
- int i;
-
- board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
-
- /* Paranoia checking: */
-
- if (PDE(file->f_dentry->d_inode) != entry)
- {
- printk(KERN_ERR "munich_write_proc: file <-> data internal error\n");
- return -EIO;
- }
-
- /* Request tmp buffer */
- if (!(page = (char *)__get_free_page(GFP_KERNEL)))
- return -ENOMEM;
-
- /* Copy user data and cut trailing \n */
- if (copy_from_user(page, buffer, count = min(count, PAGE_SIZE))) {
- free_page((unsigned long)page);
- return -EFAULT;
- }
- if (*(page + count - 1) == '\n')
- *(page + count - 1) = 0;
- *(page + PAGE_SIZE - 1) = 0;
-
- if (!strcmp(entry->name, FILENAME_BOARDNUM))
- {
- tmp_boardnum = simple_strtoul(page, NULL, 0);
- if (0 <= tmp_boardnum && tmp_boardnum < MAX_BOARDS)
- hw->boardnum = tmp_boardnum;
- else
- {
- printk("%s: " FILENAME_BOARDNUM " range is 0...%d\n", dev->name,
- MAX_BOARDS - 1);
- free_page((unsigned long)page);
- return -EINVAL;
- }
- }
- else if (!strcmp(entry->name, FILENAME_TIMESLOTS))
- {
- p = page;
- while (*p)
- {
- if (isspace(*p))
- p++;
- else
- {
- ts = simple_strtoul(p, &p, 10); /* base = 10: Don't read 09 as an octal number */
- /* ts = 0 ha nem tudta beolvasni a stringet, erre egy kicsit epitek itt: */
- if (0 <= ts && ts < 32)
- {
- tmp_timeslots |= (1 << ts);
- }
- else
- {
- printk("%s: " FILENAME_TIMESLOTS " range is 1...31\n",
- dev->name);
- free_page((unsigned long)page);
- return -EINVAL;
- }
- }
- }
- hw->timeslots = tmp_timeslots;
- }
- else if (!strcmp(entry->name, FILENAME_FRAMING))
- {
- i = 0;
- while (slicecom_framings[i].value &&
- strncmp(slicecom_framings[i].name, page,
- strlen(slicecom_framings[i].name)))
- i++;
- if (!slicecom_framings[i].value)
- {
- printk("slicecom: %s: Invalid " FILENAME_FRAMING " '%s'\n",
- dev->name, page);
- free_page((unsigned long)page);
- return -EINVAL;
- }
- else
- { /*
- * If somebody says:
- * echo >boardnum 0
- * echo >framing no-crc4
- * echo >boardnum 1
- * - when the framing was set, hw->boardnum was 0, so it would set the framing for board 0
- * Workaround: allow to set it only if interface is administrative UP
- */
- if (netif_running(dev))
- slicecom_set_framing(hw->boardnum, slicecom_framings[i].value);
- else
- {
- printk("%s: " FILENAME_FRAMING
- " can not be set while the interface is DOWN\n",
- dev->name);
- free_page((unsigned long)page);
- return -EINVAL;
- }
- }
- }
- else if (!strcmp(entry->name, FILENAME_LINECODE))
- {
- i = 0;
- while (slicecom_linecodes[i].value &&
- strncmp(slicecom_linecodes[i].name, page,
- strlen(slicecom_linecodes[i].name)))
- i++;
- if (!slicecom_linecodes[i].value)
- {
- printk("slicecom: %s: Invalid " FILENAME_LINECODE " '%s'\n",
- dev->name, page);
- free_page((unsigned long)page);
- return -EINVAL;
- }
- else
- { /*
- * Allow to set it only if interface is administrative UP,
- * for the same reason as FILENAME_FRAMING
- */
- if (netif_running(dev))
- slicecom_set_linecode(hw->boardnum,
- slicecom_linecodes[i].value);
- else
- {
- printk("%s: " FILENAME_LINECODE
- " can not be set while the interface is DOWN\n",
- dev->name);
- free_page((unsigned long)page);
- return -EINVAL;
- }
- }
- }
- else if (!strcmp(entry->name, FILENAME_CLOCK_SOURCE))
- {
- i = 0;
- while (slicecom_clock_sources[i].value &&
- strncmp(slicecom_clock_sources[i].name, page,
- strlen(slicecom_clock_sources[i].name)))
- i++;
- if (!slicecom_clock_sources[i].value)
- {
- printk("%s: Invalid " FILENAME_CLOCK_SOURCE " '%s'\n", dev->name,
- page);
- free_page((unsigned long)page);
- return -EINVAL;
- }
- else
- { /*
- * Allow to set it only if interface is administrative UP,
- * for the same reason as FILENAME_FRAMING
- */
- if (netif_running(dev))
- slicecom_set_clock_source(hw->boardnum,
- slicecom_clock_sources[i].value);
- else
- {
- printk("%s: " FILENAME_CLOCK_SOURCE
- " can not be set while the interface is DOWN\n",
- dev->name);
- free_page((unsigned long)page);
- return -EINVAL;
- }
- }
- }
- else if (!strcmp(entry->name, FILENAME_LOOPBACK))
- {
- i = 0;
- while (slicecom_loopbacks[i].value &&
- strncmp(slicecom_loopbacks[i].name, page,
- strlen(slicecom_loopbacks[i].name)))
- i++;
- if (!slicecom_loopbacks[i].value)
- {
- printk("%s: Invalid " FILENAME_LOOPBACK " '%s'\n", dev->name, page);
- free_page((unsigned long)page);
- return -EINVAL;
- }
- else
- { /*
- * Allow to set it only if interface is administrative UP,
- * for the same reason as FILENAME_FRAMING
- */
- if (netif_running(dev))
- slicecom_set_loopback(hw->boardnum,
- slicecom_loopbacks[i].value);
- else
- {
- printk("%s: " FILENAME_LOOPBACK
- " can not be set while the interface is DOWN\n",
- dev->name);
- free_page((unsigned long)page);
- return -EINVAL;
- }
- }
- }
- else if (!strcmp(entry->name, FILENAME_REG))
- { /* DEL: 'reg' csak tmp */
- char *p;
- u32 *bar1 = board->bar1;
-
- reg = simple_strtoul(page, &p, 0);
- reg_ertek = simple_strtoul(p + 1, NULL, 0);
-
- if (reg < 0x100)
- {
- printk("reg(0x%02x) := 0x%08x jiff: %lu\n", reg, reg_ertek, jiffies);
- writel(reg_ertek, MUNICH_VIRT(reg >> 2));
- }
- else
- {
- printk("reg(0x%02x) is 0x%08x jiff: %lu\n", reg - 0x100,
- readl(MUNICH_VIRT((reg - 0x100) >> 2)), jiffies);
- }
- }
- else if (!strcmp(entry->name, FILENAME_LBIREG))
- { /* DEL: 'lbireg' csak tmp */
- char *p;
- u8 *lbi = board->lbi;
-
- lbireg = simple_strtoul(page, &p, 0);
- lbireg_ertek = simple_strtoul(p + 1, NULL, 0);
-
- if (lbireg < 0x100)
- {
- printk("lbireg(0x%02x) := 0x%02x jiff: %lu\n", lbireg,
- lbireg_ertek, jiffies);
- writeb(lbireg_ertek, lbi + lbireg);
- }
- else
- printk("lbireg(0x%02x) is 0x%02x jiff: %lu\n", lbireg - 0x100,
- readb(lbi + lbireg - 0x100), jiffies);
- }
- else
- {
- printk(KERN_ERR "munich_write_proc: internal error, filename %s\n",
- entry->name);
- free_page((unsigned long)page);
- return -EBADF;
- }
-
- /* Don't forget to free the workspace */
- free_page((unsigned long)page);
- return count;
-}
-
-/*
- * Boardtype init function.
- * Called by the comx (upper) layer, when you set boardtype.
- * Allocates resources associated to using munich board for this device,
- * initializes ch_struct pointers etc.
- * Returns 0 on success and standard error codes on error.
- */
-
-static int init_escape(struct comx_channel *ch)
-{
- kfree(ch->HW_privdata);
- return -EIO;
-}
-
-static int BOARD_init(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
- struct slicecom_privdata *hw;
- struct proc_dir_entry *new_file;
-
- /* Alloc data for private structure */
- if ((ch->HW_privdata =
- kmalloc(sizeof(struct slicecom_privdata), GFP_KERNEL)) == NULL)
- return -ENOMEM;
-
- memset(hw = ch->HW_privdata, 0, sizeof(struct slicecom_privdata));
-
- /* Register /proc files */
- if ((new_file = create_proc_entry(FILENAME_BOARDNUM, S_IFREG | 0644,
- ch->procdir)) == NULL)
- return init_escape(ch);
- new_file->data = (void *)new_file;
- new_file->read_proc = &munich_read_proc;
- new_file->write_proc = &munich_write_proc;
-// new_file->proc_iops = &comx_normal_inode_ops;
- new_file->nlink = 1;
-
- if (ch->hardware == &slicecomhw)
- {
- if ((new_file = create_proc_entry(FILENAME_TIMESLOTS, S_IFREG | 0644,
- ch->procdir)) == NULL)
- return init_escape(ch);
- new_file->data = (void *)new_file;
- new_file->read_proc = &munich_read_proc;
- new_file->write_proc = &munich_write_proc;
-// new_file->proc_iops = &comx_normal_inode_ops;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_FRAMING, S_IFREG | 0644,
- ch->procdir)) == NULL)
- return init_escape(ch);
- new_file->data = (void *)new_file;
- new_file->read_proc = &munich_read_proc;
- new_file->write_proc = &munich_write_proc;
-// new_file->proc_iops = &comx_normal_inode_ops;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_LINECODE, S_IFREG | 0644,
- ch->procdir)) == NULL)
- return init_escape(ch);
- new_file->data = (void *)new_file;
- new_file->read_proc = &munich_read_proc;
- new_file->write_proc = &munich_write_proc;
-// new_file->proc_iops = &comx_normal_inode_ops;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_CLOCK_SOURCE, S_IFREG | 0644,
- ch->procdir)) == NULL)
- return init_escape(ch);
- new_file->data = (void *)new_file;
- new_file->read_proc = &munich_read_proc;
- new_file->write_proc = &munich_write_proc;
-// new_file->proc_iops = &comx_normal_inode_ops;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_LOOPBACK, S_IFREG | 0644,
- ch->procdir)) == NULL)
- return init_escape(ch);
- new_file->data = (void *)new_file;
- new_file->read_proc = &munich_read_proc;
- new_file->write_proc = &munich_write_proc;
-// new_file->proc_iops = &comx_normal_inode_ops;
- new_file->nlink = 1;
- }
-
- /* DEL: ez itt csak fejlesztesi celokra!! */
- if ((new_file = create_proc_entry(FILENAME_REG, S_IFREG | 0200, ch->procdir)) == NULL)
- return init_escape(ch);
- new_file->data = (void *)new_file;
- new_file->read_proc = &munich_read_proc;
- new_file->write_proc = &munich_write_proc;
-// new_file->proc_iops = &comx_normal_inode_ops;
- new_file->nlink = 1;
-
- /* DEL: ez itt csak fejlesztesi celokra!! */
- if ((new_file = create_proc_entry(FILENAME_LBIREG, S_IFREG | 0200,
- ch->procdir)) == NULL)
- return init_escape(ch);
- new_file->data = (void *)new_file;
- new_file->read_proc = &munich_read_proc;
- new_file->write_proc = &munich_write_proc;
-// new_file->proc_iops = &comx_normal_inode_ops;
- new_file->nlink = 1;
-
- /* Fill in ch_struct hw specific pointers: */
-
- ch->HW_txe = MUNICH_txe;
- ch->HW_open = MUNICH_open;
- ch->HW_close = MUNICH_close;
- ch->HW_send_packet = MUNICH_send_packet;
-#ifndef COMX_NEW
- ch->HW_minden = MUNICH_minden;
-#else
- ch->HW_statistics = MUNICH_minden;
-#endif
-
- hw->boardnum = SLICECOM_BOARDNUM_DEFAULT;
- hw->timeslots = ch->hardware == &pcicomhw ? 0xffffffff : 2;
-
- /* O.K. Count one more user on this module */
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-/*
- * Boardtype exit function.
- * Called by the comx (upper) layer, when you clear boardtype from munich.
- * Frees resources associated to using munich board for this device,
- * resets ch_struct pointers etc.
- */
-static int BOARD_exit(struct net_device *dev)
-{
- struct comx_channel *ch = netdev_priv(dev);
-
- /* Free private data area */
-// board = hw->boardnum + (ch->hardware == &pcicomhw ? pcicom_boards : slicecom_boards);
-
- kfree(ch->HW_privdata);
- /* Remove /proc files */
- remove_proc_entry(FILENAME_BOARDNUM, ch->procdir);
- if (ch->hardware == &slicecomhw)
- {
- remove_proc_entry(FILENAME_TIMESLOTS, ch->procdir);
- remove_proc_entry(FILENAME_FRAMING, ch->procdir);
- remove_proc_entry(FILENAME_LINECODE, ch->procdir);
- remove_proc_entry(FILENAME_CLOCK_SOURCE, ch->procdir);
- remove_proc_entry(FILENAME_LOOPBACK, ch->procdir);
- }
- remove_proc_entry(FILENAME_REG, ch->procdir);
- remove_proc_entry(FILENAME_LBIREG, ch->procdir);
-
- /* Minus one user for the module accounting */
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static struct comx_hardware slicecomhw =
-{
- "slicecom",
-#ifdef COMX_NEW
- VERSION,
-#endif
- BOARD_init,
- BOARD_exit,
- BOARD_dump,
- NULL
-};
-
-static struct comx_hardware pcicomhw =
-{
- "pcicom",
-#ifdef COMX_NEW
- VERSION,
-#endif
- BOARD_init,
- BOARD_exit,
- BOARD_dump,
- NULL
-};
-
-/* Module management */
-
-static int __init init_mister(void)
-{
- printk(VERSIONSTR);
- comx_register_hardware(&slicecomhw);
- comx_register_hardware(&pcicomhw);
- return munich_probe();
-}
-
-static void __exit cleanup_mister(void)
-{
- int i;
-
- comx_unregister_hardware("slicecom");
- comx_unregister_hardware("pcicom");
-
- for (i = 0; i < MAX_BOARDS; i++)
- {
- if (slicecom_boards[i].bar1)
- iounmap((void *)slicecom_boards[i].bar1);
- if (slicecom_boards[i].lbi)
- iounmap((void *)slicecom_boards[i].lbi);
- if (pcicom_boards[i].bar1)
- iounmap((void *)pcicom_boards[i].bar1);
- if (pcicom_boards[i].lbi)
- iounmap((void *)pcicom_boards[i].lbi);
- }
-}
-
-module_init(init_mister);
-module_exit(cleanup_mister);
===== drivers/net/wan/comx-proto-fr.c 1.13 vs edited =====
--- 1.13/drivers/net/wan/comx-proto-fr.c Thu Sep 11 19:40:53 2003
+++ edited/drivers/net/wan/comx-proto-fr.c Fri May 7 13:05:52 2004
@@ -1,1014 +1 @@
-/*
- * Frame-relay protocol module for the COMX driver
- * for Linux 2.2.X
- *
- * Original author: Tivadar Szemethy <tiv@itc.hu>
- * Maintainer: Gergely Madarasz <gorgo@itc.hu>
- *
- * Copyright (C) 1998-1999 ITConsult-Pro Co. <info@itc.hu>
- *
- * Contributors:
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br> (0.73)
- *
- * 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.
- *
- * Version 0.70 (99/06/14):
- * - cleaned up the source code a bit
- * - ported back to kernel, now works as builtin code
- *
- * Version 0.71 (99/06/25):
- * - use skb priorities and queues for sending keepalive
- * - use device queues for slave->master data transmit
- * - set IFF_RUNNING only line protocol up
- * - fixes on slave device flags
- *
- * Version 0.72 (99/07/09):
- * - handle slave tbusy with master tbusy (should be fixed)
- * - fix the keepalive timer addition/deletion
- *
- * Version 0.73 (00/08/15)
- * - resource release on failure at fr_master_init and
- * fr_slave_init
- */
-#define VERSION "0.73"
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/jiffies.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/if_arp.h>
-#include <linux/inetdevice.h>
-#include <linux/pkt_sched.h>
-#include <linux/init.h>
-
-#include <asm/uaccess.h>
-
-#include "comx.h"
-#include "comxhw.h"
-
-MODULE_AUTHOR("Author: Tivadar Szemethy <tiv@itc.hu>");
-MODULE_DESCRIPTION("Frame Relay protocol implementation for the COMX drivers"
- "for Linux kernel 2.4.X");
-MODULE_LICENSE("GPL");
-
-#define FRAD_UI 0x03
-#define NLPID_IP 0xcc
-#define NLPID_Q933_LMI 0x08
-#define NLPID_CISCO_LMI 0x09
-#define Q933_ENQ 0x75
-#define Q933_LINESTAT 0x51
-#define Q933_COUNTERS 0x53
-
-#define MAXALIVECNT 3 /* No. of failures */
-
-struct fr_data {
- u16 dlci;
- struct net_device *master;
- char keepa_pend;
- char keepa_freq;
- char keepalivecnt, keeploopcnt;
- struct timer_list keepa_timer;
- u8 local_cnt, remote_cnt;
-};
-
-static struct comx_protocol fr_master_protocol;
-static struct comx_protocol fr_slave_protocol;
-static struct comx_hardware fr_dlci;
-
-static void fr_keepalive_send(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = ch->LINE_privdata;
- struct sk_buff *skb;
- u8 *fr_packet;
-
- skb=alloc_skb(dev->hard_header_len + 13, GFP_ATOMIC);
-
- if(skb==NULL)
- return;
-
- skb_reserve(skb, dev->hard_header_len);
-
- fr_packet=(u8*)skb_put(skb, 13);
-
- fr_packet[0] = (fr->dlci & (1024 - 15)) >> 2;
- fr_packet[1] = (fr->dlci & 15) << 4 | 1; // EA bit 1
- fr_packet[2] = FRAD_UI;
- fr_packet[3] = NLPID_Q933_LMI;
- fr_packet[4] = 0;
- fr_packet[5] = Q933_ENQ;
- fr_packet[6] = Q933_LINESTAT;
- fr_packet[7] = 0x01;
- fr_packet[8] = 0x01;
- fr_packet[9] = Q933_COUNTERS;
- fr_packet[10] = 0x02;
- fr_packet[11] = ++fr->local_cnt;
- fr_packet[12] = fr->remote_cnt;
-
- skb->dev = dev;
- skb->priority = TC_PRIO_CONTROL;
- dev_queue_xmit(skb);
-}
-
-static void fr_keepalive_timerfun(unsigned long d)
-{
- struct net_device *dev = (struct net_device *)d;
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = ch->LINE_privdata;
- struct proc_dir_entry *dir = ch->procdir->parent->subdir;
- struct comx_channel *sch;
- struct fr_data *sfr;
- struct net_device *sdev;
-
- if (ch->init_status & LINE_OPEN) {
- if (fr->keepalivecnt == MAXALIVECNT) {
- comx_status(dev, ch->line_status & ~PROTO_UP);
- dev->flags &= ~IFF_RUNNING;
- for (; dir ; dir = dir->next) {
- if(!S_ISDIR(dir->mode)) {
- continue;
- }
-
- if ((sdev = dir->data) && (sch = sdev->priv) &&
- (sdev->type == ARPHRD_DLCI) &&
- (sfr = sch->LINE_privdata)
- && (sfr->master == dev) &&
- (sdev->flags & IFF_UP)) {
- sdev->flags &= ~IFF_RUNNING;
- comx_status(sdev,
- sch->line_status & ~PROTO_UP);
- }
- }
- }
- if (fr->keepalivecnt <= MAXALIVECNT) {
- ++fr->keepalivecnt;
- }
- fr_keepalive_send(dev);
- }
- mod_timer(&fr->keepa_timer, jiffies + HZ * fr->keepa_freq);
-}
-
-static void fr_rx_lmi(struct net_device *dev, struct sk_buff *skb,
- u16 dlci, u8 nlpid)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = ch->LINE_privdata;
- struct proc_dir_entry *dir = ch->procdir->parent->subdir;
- struct comx_channel *sch;
- struct fr_data *sfr;
- struct net_device *sdev;
-
- if (dlci != fr->dlci || nlpid != NLPID_Q933_LMI || !fr->keepa_freq) {
- return;
- }
-
- fr->remote_cnt = skb->data[7];
- if (skb->data[8] == fr->local_cnt) { // keepalive UP!
- fr->keepalivecnt = 0;
- if ((ch->line_status & LINE_UP) &&
- !(ch->line_status & PROTO_UP)) {
- comx_status(dev, ch->line_status |= PROTO_UP);
- dev->flags |= IFF_RUNNING;
- for (; dir ; dir = dir->next) {
- if(!S_ISDIR(dir->mode)) {
- continue;
- }
-
- if ((sdev = dir->data) && (sch = sdev->priv) &&
- (sdev->type == ARPHRD_DLCI) &&
- (sfr = sch->LINE_privdata)
- && (sfr->master == dev) &&
- (sdev->flags & IFF_UP)) {
- sdev->flags |= IFF_RUNNING;
- comx_status(sdev,
- sch->line_status | PROTO_UP);
- }
- }
- }
- }
-}
-
-static void fr_set_keepalive(struct net_device *dev, int keepa)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = ch->LINE_privdata;
-
- if (!keepa && fr->keepa_freq) { // switch off
- fr->keepa_freq = 0;
- if (ch->line_status & LINE_UP) {
- comx_status(dev, ch->line_status | PROTO_UP);
- dev->flags |= IFF_RUNNING;
- del_timer(&fr->keepa_timer);
- }
- return;
- }
-
- if (keepa) { // bekapcs
- if(fr->keepa_freq && (ch->line_status & LINE_UP)) {
- del_timer(&fr->keepa_timer);
- }
- fr->keepa_freq = keepa;
- fr->local_cnt = fr->remote_cnt = 0;
- init_timer(&fr->keepa_timer);
- fr->keepa_timer.expires = jiffies + HZ;
- fr->keepa_timer.function = fr_keepalive_timerfun;
- fr->keepa_timer.data = (unsigned long)dev;
- ch->line_status &= ~(PROTO_UP | PROTO_LOOP);
- dev->flags &= ~IFF_RUNNING;
- comx_status(dev, ch->line_status);
- if(ch->line_status & LINE_UP) {
- add_timer(&fr->keepa_timer);
- }
- }
-}
-
-static void fr_rx(struct net_device *dev, struct sk_buff *skb)
-{
- struct comx_channel *ch = dev->priv;
- struct proc_dir_entry *dir = ch->procdir->parent->subdir;
- struct net_device *sdev = dev;
- struct comx_channel *sch;
- struct fr_data *sfr;
- u16 dlci;
- u8 nlpid;
-
- if(skb->len <= 4 || skb->data[2] != FRAD_UI) {
- kfree_skb(skb);
- return;
- }
-
- /* Itt majd ki kell talalni, melyik slave kapja a csomagot */
- dlci = ((skb->data[0] & 0xfc) << 2) | ((skb->data[1] & 0xf0) >> 4);
- if ((nlpid = skb->data[3]) == 0) { // Optional padding
- nlpid = skb->data[4];
- skb_pull(skb, 1);
- }
- skb_pull(skb, 4); /* DLCI and header throw away */
-
- if (ch->debug_flags & DEBUG_COMX_DLCI) {
- comx_debug(dev, "Frame received, DLCI: %d, NLPID: 0x%02x\n",
- dlci, nlpid);
- comx_debug_skb(dev, skb, "Contents");
- }
-
- /* Megkeressuk, kihez tartozik */
- for (; dir ; dir = dir->next) {
- if(!S_ISDIR(dir->mode)) {
- continue;
- }
- if ((sdev = dir->data) && (sch = sdev->priv) &&
- (sdev->type == ARPHRD_DLCI) && (sfr = sch->LINE_privdata) &&
- (sfr->master == dev) && (sfr->dlci == dlci)) {
- skb->dev = sdev;
- if (ch->debug_flags & DEBUG_COMX_DLCI) {
- comx_debug(dev, "Passing it to %s\n",sdev->name);
- }
- if (dev != sdev) {
- sch->stats.rx_packets++;
- sch->stats.rx_bytes += skb->len;
- }
- break;
- }
- }
- switch(nlpid) {
- case NLPID_IP:
- skb->protocol = htons(ETH_P_IP);
- skb->mac.raw = skb->data;
- comx_rx(sdev, skb);
- break;
- case NLPID_Q933_LMI:
- fr_rx_lmi(dev, skb, dlci, nlpid);
- default:
- kfree_skb(skb);
- break;
- }
-}
-
-static int fr_tx(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct proc_dir_entry *dir = ch->procdir->parent->subdir;
- struct net_device *sdev;
- struct comx_channel *sch;
- struct fr_data *sfr;
- int cnt = 1;
-
- /* Ha minden igaz, 2 helyen fog allni a tbusy: a masternel,
- es annal a slave-nel aki eppen kuldott.
- Egy helyen akkor all, ha a master kuldott.
- Ez megint jo lesz majd, ha utemezni akarunk */
-
- /* This should be fixed, the slave tbusy should be set when
- the masters queue is full and reset when not */
-
- for (; dir ; dir = dir->next) {
- if(!S_ISDIR(dir->mode)) {
- continue;
- }
- if ((sdev = dir->data) && (sch = sdev->priv) &&
- (sdev->type == ARPHRD_DLCI) && (sfr = sch->LINE_privdata) &&
- (sfr->master == dev) && (netif_queue_stopped(sdev))) {
- netif_wake_queue(sdev);
- cnt++;
- }
- }
-
- netif_wake_queue(dev);
- return 0;
-}
-
-static void fr_status(struct net_device *dev, unsigned short status)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = ch->LINE_privdata;
- struct proc_dir_entry *dir = ch->procdir->parent->subdir;
- struct net_device *sdev;
- struct comx_channel *sch;
- struct fr_data *sfr;
-
- if (status & LINE_UP) {
- if (!fr->keepa_freq) {
- status |= PROTO_UP;
- }
- } else {
- status &= ~(PROTO_UP | PROTO_LOOP);
- }
-
- if (dev == fr->master && fr->keepa_freq) {
- if (status & LINE_UP) {
- fr->keepa_timer.expires = jiffies + HZ;
- add_timer(&fr->keepa_timer);
- fr->keepalivecnt = MAXALIVECNT + 1;
- fr->keeploopcnt = 0;
- } else {
- del_timer(&fr->keepa_timer);
- }
- }
-
- /* Itt a status valtozast vegig kell vinni az osszes slave-n */
- for (; dir ; dir = dir->next) {
- if(!S_ISDIR(dir->mode)) {
- continue;
- }
-
- if ((sdev = dir->data) && (sch = sdev->priv) &&
- (sdev->type == ARPHRD_FRAD || sdev->type == ARPHRD_DLCI) &&
- (sfr = sch->LINE_privdata) && (sfr->master == dev)) {
- if(status & LINE_UP) {
- netif_wake_queue(sdev);
- }
- comx_status(sdev, status);
- if(status & (PROTO_UP | PROTO_LOOP)) {
- dev->flags |= IFF_RUNNING;
- } else {
- dev->flags &= ~IFF_RUNNING;
- }
- }
- }
-}
-
-static int fr_open(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = ch->LINE_privdata;
- struct proc_dir_entry *comxdir = ch->procdir;
- struct comx_channel *mch;
-
- if (!(ch->init_status & HW_OPEN)) {
- return -ENODEV;
- }
-
- if ((ch->hardware == &fr_dlci && ch->protocol != &fr_slave_protocol) ||
- (ch->protocol == &fr_slave_protocol && ch->hardware != &fr_dlci)) {
- printk(KERN_ERR "Trying to open an improperly set FR interface, giving up\n");
- return -EINVAL;
- }
-
- if (!fr->master) {
- return -ENODEV;
- }
- mch = fr->master->priv;
- if (fr->master != dev && (!(mch->init_status & LINE_OPEN)
- || (mch->protocol != &fr_master_protocol))) {
- printk(KERN_ERR "Master %s is inactive, or incorrectly set up, "
- "unable to open %s\n", fr->master->name, dev->name);
- return -ENODEV;
- }
-
- ch->init_status |= LINE_OPEN;
- ch->line_status &= ~(PROTO_UP | PROTO_LOOP);
- dev->flags &= ~IFF_RUNNING;
-
- if (fr->master == dev) {
- if (fr->keepa_freq) {
- fr->keepa_timer.function = fr_keepalive_timerfun;
- fr->keepa_timer.data = (unsigned long)dev;
- add_timer(&fr->keepa_timer);
- } else {
- if (ch->line_status & LINE_UP) {
- ch->line_status |= PROTO_UP;
- dev->flags |= IFF_RUNNING;
- }
- }
- } else {
- ch->line_status = mch->line_status;
- if(fr->master->flags & IFF_RUNNING) {
- dev->flags |= IFF_RUNNING;
- }
- }
-
- for (; comxdir ; comxdir = comxdir->next) {
- if (strcmp(comxdir->name, FILENAME_DLCI) == 0 ||
- strcmp(comxdir->name, FILENAME_MASTER) == 0 ||
- strcmp(comxdir->name, FILENAME_KEEPALIVE) == 0) {
- comxdir->mode = S_IFREG | 0444;
- }
- }
-// comx_status(dev, ch->line_status);
- return 0;
-}
-
-static int fr_close(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = ch->LINE_privdata;
- struct proc_dir_entry *comxdir = ch->procdir;
-
- if (fr->master == dev) { // Ha master
- struct proc_dir_entry *dir = ch->procdir->parent->subdir;
- struct net_device *sdev = dev;
- struct comx_channel *sch;
- struct fr_data *sfr;
-
- if (!(ch->init_status & HW_OPEN)) {
- return -ENODEV;
- }
-
- if (fr->keepa_freq) {
- del_timer(&fr->keepa_timer);
- }
-
- for (; dir ; dir = dir->next) {
- if(!S_ISDIR(dir->mode)) {
- continue;
- }
- if ((sdev = dir->data) && (sch = sdev->priv) &&
- (sdev->type == ARPHRD_DLCI) &&
- (sfr = sch->LINE_privdata) &&
- (sfr->master == dev) &&
- (sch->init_status & LINE_OPEN)) {
- dev_close(sdev);
- }
- }
- }
-
- ch->init_status &= ~LINE_OPEN;
- ch->line_status &= ~(PROTO_UP | PROTO_LOOP);
- dev->flags &= ~IFF_RUNNING;
-
- for (; comxdir ; comxdir = comxdir->next) {
- if (strcmp(comxdir->name, FILENAME_DLCI) == 0 ||
- strcmp(comxdir->name, FILENAME_MASTER) == 0 ||
- strcmp(comxdir->name, FILENAME_KEEPALIVE) == 0) {
- comxdir->mode = S_IFREG | 0444;
- }
- }
-
- return 0;
-}
-
-static int fr_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct comx_channel *sch, *mch;
- struct fr_data *fr = ch->LINE_privdata;
- struct fr_data *sfr;
- struct net_device *sdev;
- struct proc_dir_entry *dir = ch->procdir->parent->subdir;
-
- if (!fr->master) {
- printk(KERN_ERR "BUG: fr_xmit without a master!!! dev: %s\n", dev->name);
- return 0;
- }
-
- mch = fr->master->priv;
-
- /* Ennek majd a slave utemezeskor lesz igazan jelentosege */
- if (ch->debug_flags & DEBUG_COMX_DLCI) {
- comx_debug_skb(dev, skb, "Sending frame");
- }
-
- if (dev != fr->master) {
- struct sk_buff *newskb=skb_clone(skb, GFP_ATOMIC);
- if (!newskb)
- return -ENOMEM;
- newskb->dev=fr->master;
- dev_queue_xmit(newskb);
- ch->stats.tx_bytes += skb->len;
- ch->stats.tx_packets++;
- dev_kfree_skb(skb);
- } else {
- netif_stop_queue(dev);
- for (; dir ; dir = dir->next) {
- if(!S_ISDIR(dir->mode)) {
- continue;
- }
- if ((sdev = dir->data) && (sch = sdev->priv) &&
- (sdev->type == ARPHRD_DLCI) && (sfr = sch->LINE_privdata) &&
- (sfr->master == dev) && (netif_queue_stopped(sdev))) {
- netif_stop_queue(sdev);
- }
- }
-
- switch(mch->HW_send_packet(dev, skb)) {
- case FRAME_QUEUED:
- netif_wake_queue(dev);
- break;
- case FRAME_ACCEPTED:
- case FRAME_DROPPED:
- break;
- case FRAME_ERROR:
- printk(KERN_ERR "%s: Transmit frame error (len %d)\n",
- dev->name, skb->len);
- break;
- }
- }
- return 0;
-}
-
-static int fr_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, void *daddr, void *saddr, unsigned len)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = ch->LINE_privdata;
-
- skb_push(skb, dev->hard_header_len);
- /* Put in DLCI */
- skb->data[0] = (fr->dlci & (1024 - 15)) >> 2;
- skb->data[1] = (fr->dlci & 15) << 4 | 1; // EA bit 1
- skb->data[2] = FRAD_UI;
- skb->data[3] = NLPID_IP;
-
- return dev->hard_header_len;
-}
-
-static int fr_statistics(struct net_device *dev, char *page)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = ch->LINE_privdata;
- int len = 0;
-
- if (fr->master == dev) {
- struct proc_dir_entry *dir = ch->procdir->parent->subdir;
- struct net_device *sdev;
- struct comx_channel *sch;
- struct fr_data *sfr;
- int slaves = 0;
-
- len += sprintf(page + len,
- "This is a Frame Relay master device\nSlaves: ");
- for (; dir ; dir = dir->next) {
- if(!S_ISDIR(dir->mode)) {
- continue;
- }
- if ((sdev = dir->data) && (sch = sdev->priv) &&
- (sdev->type == ARPHRD_DLCI) &&
- (sfr = sch->LINE_privdata) &&
- (sfr->master == dev) && (sdev != dev)) {
- slaves++;
- len += sprintf(page + len, "%s ", sdev->name);
- }
- }
- len += sprintf(page + len, "%s\n", slaves ? "" : "(none)");
- if (fr->keepa_freq) {
- len += sprintf(page + len, "Line keepalive (value %d) "
- "status %s [%d]\n", fr->keepa_freq,
- ch->line_status & PROTO_LOOP ? "LOOP" :
- ch->line_status & PROTO_UP ? "UP" : "DOWN",
- fr->keepalivecnt);
- } else {
- len += sprintf(page + len, "Line keepalive protocol "
- "is not set\n");
- }
- } else { // if slave
- len += sprintf(page + len,
- "This is a Frame Relay slave device, master: %s\n",
- fr->master ? fr->master->name : "(not set)");
- }
- return len;
-}
-
-static int fr_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct proc_dir_entry *file = (struct proc_dir_entry *)data;
- struct net_device *dev = file->parent->data;
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = NULL;
- int len = 0;
-
- if (ch) {
- fr = ch->LINE_privdata;
- }
-
- if (strcmp(file->name, FILENAME_DLCI) == 0) {
- len = sprintf(page, "%04d\n", fr->dlci);
- } else if (strcmp(file->name, FILENAME_MASTER) == 0) {
- len = sprintf(page, "%-9s\n", fr->master ? fr->master->name :
- "(none)");
- } else if (strcmp(file->name, FILENAME_KEEPALIVE) == 0) {
- len = fr->keepa_freq ? sprintf(page, "% 3d\n", fr->keepa_freq)
- : sprintf(page, "off\n");
- } else {
- printk(KERN_ERR "comxfr: internal error, filename %s\n", file->name);
- return -EBADF;
- }
-
- if (off >= len) {
- *eof = 1;
- return 0;
- }
-
- *start = page + off;
- if (count >= len - off) *eof = 1;
- return min_t(int, count, len - off);
-}
-
-static int fr_write_proc(struct file *file, const char *buffer,
- u_long count, void *data)
-{
- struct proc_dir_entry *entry = (struct proc_dir_entry *)data;
- struct net_device *dev = entry->parent->data;
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = NULL;
- char *page;
-
- if (ch) {
- fr = ch->LINE_privdata;
- }
-
- if (!(page = (char *)__get_free_page(GFP_KERNEL))) {
- return -ENOMEM;
- }
-
- if (copy_from_user(page, buffer, count)) {
- free_page((unsigned long)page);
- return -EFAULT;
- }
- if (*(page + count - 1) == '\n') {
- *(page + count - 1) = 0;
- }
-
- if (strcmp(entry->name, FILENAME_DLCI) == 0) {
- u16 dlci_new = simple_strtoul(page, NULL, 10);
-
- if (dlci_new > 1023) {
- printk(KERN_ERR "Invalid DLCI value\n");
- }
- else fr->dlci = dlci_new;
- } else if (strcmp(entry->name, FILENAME_MASTER) == 0) {
- struct net_device *new_master = dev_get_by_name(page);
-
- if (new_master && new_master->type == ARPHRD_FRAD) {
- struct comx_channel *sch = new_master->priv;
- struct fr_data *sfr = sch->LINE_privdata;
-
- if (sfr && sfr->master == new_master) {
- if(fr->master)
- dev_put(fr->master);
- fr->master = new_master;
- /* Megorokli a master statuszat */
- ch->line_status = sch->line_status;
- }
- }
- } else if (strcmp(entry->name, FILENAME_KEEPALIVE) == 0) {
- int keepa_new = -1;
-
- if (strcmp(page, KEEPALIVE_OFF) == 0) {
- keepa_new = 0;
- } else {
- keepa_new = simple_strtoul(page, NULL, 10);
- }
-
- if (keepa_new < 0 || keepa_new > 100) {
- printk(KERN_ERR "invalid keepalive\n");
- } else {
- if (fr->keepa_freq && keepa_new != fr->keepa_freq) {
- fr_set_keepalive(dev, 0);
- }
- if (keepa_new) {
- fr_set_keepalive(dev, keepa_new);
- }
- }
- } else {
- printk(KERN_ERR "comxfr_write_proc: internal error, filename %s\n",
- entry->name);
- count = -EBADF;
- }
-
- free_page((unsigned long)page);
- return count;
-}
-
-static int fr_exit(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = ch->LINE_privdata;
- struct net_device *sdev = dev;
- struct comx_channel *sch;
- struct fr_data *sfr;
- struct proc_dir_entry *dir = ch->procdir->parent->subdir;
-
- /* Ha lezarunk egy master-t, le kell kattintani a slave-eket is */
- if (fr->master && fr->master == dev) {
- for (; dir ; dir = dir->next) {
- if(!S_ISDIR(dir->mode)) {
- continue;
- }
- if ((sdev = dir->data) && (sch = sdev->priv) &&
- (sdev->type == ARPHRD_DLCI) &&
- (sfr = sch->LINE_privdata) && (sfr->master == dev)) {
- dev_close(sdev);
- sfr->master = NULL;
- }
- }
- }
- dev->flags = 0;
- dev->type = 0;
- dev->mtu = 0;
- dev->hard_header_len = 0;
-
- ch->LINE_rx = NULL;
- ch->LINE_tx = NULL;
- ch->LINE_status = NULL;
- ch->LINE_open = NULL;
- ch->LINE_close = NULL;
- ch->LINE_xmit = NULL;
- ch->LINE_header = NULL;
- ch->LINE_rebuild_header = NULL;
- ch->LINE_statistics = NULL;
-
- ch->LINE_status = 0;
-
- if (fr->master != dev) { // if not master, remove dlci
- if(fr->master)
- dev_put(fr->master);
- remove_proc_entry(FILENAME_DLCI, ch->procdir);
- remove_proc_entry(FILENAME_MASTER, ch->procdir);
- } else {
- if (fr->keepa_freq) {
- fr_set_keepalive(dev, 0);
- }
- remove_proc_entry(FILENAME_KEEPALIVE, ch->procdir);
- remove_proc_entry(FILENAME_DLCI, ch->procdir);
- }
-
- kfree(fr);
- ch->LINE_privdata = NULL;
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static int fr_master_init(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr;
- struct proc_dir_entry *new_file;
-
- if ((fr = ch->LINE_privdata = kmalloc(sizeof(struct fr_data),
- GFP_KERNEL)) == NULL) {
- return -ENOMEM;
- }
- memset(fr, 0, sizeof(struct fr_data));
- fr->master = dev; // this means master
- fr->dlci = 0; // let's say default
-
- dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
- dev->type = ARPHRD_FRAD;
- dev->mtu = 1500;
- dev->hard_header_len = 4;
- dev->addr_len = 0;
-
- ch->LINE_rx = fr_rx;
- ch->LINE_tx = fr_tx;
- ch->LINE_status = fr_status;
- ch->LINE_open = fr_open;
- ch->LINE_close = fr_close;
- ch->LINE_xmit = fr_xmit;
- ch->LINE_header = fr_header;
- ch->LINE_rebuild_header = NULL;
- ch->LINE_statistics = fr_statistics;
-
- if ((new_file = create_proc_entry(FILENAME_DLCI, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_LINE_privdata;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &fr_read_proc;
- new_file->write_proc = &fr_write_proc;
- new_file->size = 5;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_KEEPALIVE, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_filename_dlci;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &fr_read_proc;
- new_file->write_proc = &fr_write_proc;
- new_file->size = 4;
- new_file->nlink = 1;
-
- fr_set_keepalive(dev, 0);
-
- MOD_INC_USE_COUNT;
- return 0;
-cleanup_filename_dlci:
- remove_proc_entry(FILENAME_DLCI, ch->procdir);
-cleanup_LINE_privdata:
- kfree(fr);
- return -EIO;
-}
-
-static int fr_slave_init(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr;
- struct proc_dir_entry *new_file;
-
- if ((fr = ch->LINE_privdata = kmalloc(sizeof(struct fr_data),
- GFP_KERNEL)) == NULL) {
- return -ENOMEM;
- }
- memset(fr, 0, sizeof(struct fr_data));
-
- dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
- dev->type = ARPHRD_DLCI;
- dev->mtu = 1500;
- dev->hard_header_len = 4;
- dev->addr_len = 0;
-
- ch->LINE_rx = fr_rx;
- ch->LINE_tx = fr_tx;
- ch->LINE_status = fr_status;
- ch->LINE_open = fr_open;
- ch->LINE_close = fr_close;
- ch->LINE_xmit = fr_xmit;
- ch->LINE_header = fr_header;
- ch->LINE_rebuild_header = NULL;
- ch->LINE_statistics = fr_statistics;
-
- if ((new_file = create_proc_entry(FILENAME_DLCI, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_LINE_privdata;
- }
-
- new_file->data = (void *)new_file;
- new_file->read_proc = &fr_read_proc;
- new_file->write_proc = &fr_write_proc;
- new_file->size = 5;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_MASTER, S_IFREG | 0644,
- ch->procdir)) == NULL) {
- goto cleanup_filename_dlci;
- }
- new_file->data = (void *)new_file;
- new_file->read_proc = &fr_read_proc;
- new_file->write_proc = &fr_write_proc;
- new_file->size = 10;
- new_file->nlink = 1;
- MOD_INC_USE_COUNT;
- return 0;
-cleanup_filename_dlci:
- remove_proc_entry(FILENAME_DLCI, ch->procdir);
-cleanup_LINE_privdata:
- kfree(fr);
- return -EIO;
-}
-
-static int dlci_open(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
-
- ch->init_status |= HW_OPEN;
-
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int dlci_close(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
-
- ch->init_status &= ~HW_OPEN;
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static int dlci_txe(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct fr_data *fr = ch->LINE_privdata;
-
- if (!fr->master) {
- return 0;
- }
-
- ch = fr->master->priv;
- fr = ch->LINE_privdata;
- return ch->HW_txe(fr->master);
-}
-
-static int dlci_statistics(struct net_device *dev, char *page)
-{
- return 0;
-}
-
-static int dlci_init(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
-
- ch->HW_open = dlci_open;
- ch->HW_close = dlci_close;
- ch->HW_txe = dlci_txe;
- ch->HW_statistics = dlci_statistics;
-
- /* Nincs egyeb hw info, mert ugyis a fr->master-bol fog minden kiderulni */
-
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int dlci_exit(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
-
- ch->HW_open = NULL;
- ch->HW_close = NULL;
- ch->HW_txe = NULL;
- ch->HW_statistics = NULL;
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static int dlci_dump(struct net_device *dev)
-{
- printk(KERN_INFO "dlci_dump %s, HOGY MI ???\n", dev->name);
- return -1;
-}
-
-static struct comx_protocol fr_master_protocol = {
- .name = "frad",
- .version = VERSION,
- .encap_type = ARPHRD_FRAD,
- .line_init = fr_master_init,
- .line_exit = fr_exit,
-};
-
-static struct comx_protocol fr_slave_protocol = {
- .name = "ietf-ip",
- .version = VERSION,
- .encap_type = ARPHRD_DLCI,
- .line_init = fr_slave_init,
- .line_exit = fr_exit,
-};
-
-static struct comx_hardware fr_dlci = {
- .name = "dlci",
- .version = VERSION,
- .hw_init = dlci_init,
- .hw_exit = dlci_exit,
- .hw_dump = dlci_dump,
-};
-
-static int __init comx_proto_fr_init(void)
-{
- int ret;
-
- if ((ret = comx_register_hardware(&fr_dlci))) {
- return ret;
- }
- if ((ret = comx_register_protocol(&fr_master_protocol))) {
- return ret;
- }
- return comx_register_protocol(&fr_slave_protocol);
-}
-
-static void __exit comx_proto_fr_exit(void)
-{
- comx_unregister_hardware(fr_dlci.name);
- comx_unregister_protocol(fr_master_protocol.name);
- comx_unregister_protocol(fr_slave_protocol.name);
-}
-
-module_init(comx_proto_fr_init);
-module_exit(comx_proto_fr_exit);
===== drivers/net/wan/comx-proto-lapb.c 1.12 vs edited =====
--- 1.12/drivers/net/wan/comx-proto-lapb.c Sun Jan 11 00:39:04 2004
+++ edited/drivers/net/wan/comx-proto-lapb.c Fri May 7 13:05:52 2004
@@ -1,551 +1 @@
-/*
- * LAPB protocol module for the COMX driver
- * for Linux kernel 2.2.X
- *
- * Original author: Tivadar Szemethy <tiv@itc.hu>
- * Maintainer: Gergely Madarasz <gorgo@itc.hu>
- *
- * Copyright (C) 1997-1999 (C) ITConsult-Pro Co. <info@itc.hu>
- *
- * 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.
- *
- * Version 0.80 (99/06/14):
- * - cleaned up the source code a bit
- * - ported back to kernel, now works as non-module
- *
- * Changed (00/10/29, Henner Eisen):
- * - comx_rx() / comxlapb_data_indication() return status.
- *
- */
-#define VERSION "0.80"
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/if_arp.h>
-#include <linux/inetdevice.h>
-#include <asm/uaccess.h>
-#include <linux/lapb.h>
-#include <linux/init.h>
-
-#include "comx.h"
-#include "comxhw.h"
-
-static struct proc_dir_entry *create_comxlapb_proc_entry(char *name, int mode,
- int size, struct proc_dir_entry *dir);
-
-static void comxlapb_rx(struct net_device *dev, struct sk_buff *skb)
-{
- if (!dev || !dev->priv) {
- dev_kfree_skb(skb);
- } else {
- lapb_data_received(dev, skb);
- }
-}
-
-static int comxlapb_tx(struct net_device *dev)
-{
- netif_wake_queue(dev);
- return 0;
-}
-
-static int comxlapb_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, void *daddr, void *saddr, unsigned len)
-{
- return dev->hard_header_len;
-}
-
-static void comxlapb_status(struct net_device *dev, unsigned short status)
-{
- struct comx_channel *ch;
-
- if (!dev || !(ch = dev->priv)) {
- return;
- }
- if (status & LINE_UP) {
- netif_wake_queue(dev);
- }
- comx_status(dev, status);
-}
-
-static int comxlapb_open(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- int err = 0;
-
- if (!(ch->init_status & HW_OPEN)) {
- return -ENODEV;
- }
-
- err = lapb_connect_request(dev);
-
- if (ch->debug_flags & DEBUG_COMX_LAPB) {
- comx_debug(dev, "%s: lapb opened, error code: %d\n",
- dev->name, err);
- }
-
- if (!err) {
- ch->init_status |= LINE_OPEN;
- MOD_INC_USE_COUNT;
- }
- return err;
-}
-
-static int comxlapb_close(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
-
- if (!(ch->init_status & HW_OPEN)) {
- return -ENODEV;
- }
-
- if (ch->debug_flags & DEBUG_COMX_LAPB) {
- comx_debug(dev, "%s: lapb closed\n", dev->name);
- }
-
- lapb_disconnect_request(dev);
-
- ch->init_status &= ~LINE_OPEN;
- ch->line_status &= ~PROTO_UP;
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static int comxlapb_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct sk_buff *skb2;
-
- if (!dev || !(ch = dev->priv) || !(dev->flags & (IFF_UP | IFF_RUNNING))) {
- return -ENODEV;
- }
-
- if (dev->type == ARPHRD_X25) { // first byte tells what to do
- switch(skb->data[0]) {
- case 0x00:
- break; // transmit
- case 0x01:
- lapb_connect_request(dev);
- kfree_skb(skb);
- return 0;
- case 0x02:
- lapb_disconnect_request(dev);
- default:
- kfree_skb(skb);
- return 0;
- }
- skb_pull(skb,1);
- }
-
- netif_stop_queue(dev);
-
- if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
- lapb_data_request(dev, skb2);
- }
-
- return FRAME_ACCEPTED;
-}
-
-static int comxlapb_statistics(struct net_device *dev, char *page)
-{
- struct lapb_parms_struct parms;
- int len = 0;
-
- len += sprintf(page + len, "Line status: ");
- if (lapb_getparms(dev, &parms) != LAPB_OK) {
- len += sprintf(page + len, "not initialized\n");
- return len;
- }
- len += sprintf(page + len, "%s (%s), T1: %d/%d, T2: %d/%d, N2: %d/%d, "
- "window: %d\n", parms.mode & LAPB_DCE ? "DCE" : "DTE",
- parms.mode & LAPB_EXTENDED ? "EXTENDED" : "STANDARD",
- parms.t1timer, parms.t1, parms.t2timer, parms.t2,
- parms.n2count, parms.n2, parms.window);
-
- return len;
-}
-
-static int comxlapb_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct proc_dir_entry *file = (struct proc_dir_entry *)data;
- struct net_device *dev = file->parent->data;
- struct lapb_parms_struct parms;
- int len = 0;
-
- if (lapb_getparms(dev, &parms)) {
- return -ENODEV;
- }
-
- if (strcmp(file->name, FILENAME_T1) == 0) {
- len += sprintf(page + len, "%02u / %02u\n",
- parms.t1timer, parms.t1);
- } else if (strcmp(file->name, FILENAME_T2) == 0) {
- len += sprintf(page + len, "%02u / %02u\n",
- parms.t2timer, parms.t2);
- } else if (strcmp(file->name, FILENAME_N2) == 0) {
- len += sprintf(page + len, "%02u / %02u\n",
- parms.n2count, parms.n2);
- } else if (strcmp(file->name, FILENAME_WINDOW) == 0) {
- len += sprintf(page + len, "%u\n", parms.window);
- } else if (strcmp(file->name, FILENAME_MODE) == 0) {
- len += sprintf(page + len, "%s, %s\n",
- parms.mode & LAPB_DCE ? "DCE" : "DTE",
- parms.mode & LAPB_EXTENDED ? "EXTENDED" : "STANDARD");
- } else {
- printk(KERN_ERR "comxlapb: internal error, filename %s\n", file->name);
- return -EBADF;
- }
-
- if (off >= len) {
- *eof = 1;
- return 0;
- }
-
- *start = page + off;
- if (count >= len - off) {
- *eof = 1;
- }
- return min_t(int, count, len - off);
-}
-
-static int comxlapb_write_proc(struct file *file, const char *buffer,
- u_long count, void *data)
-{
- struct proc_dir_entry *entry = (struct proc_dir_entry *)data;
- struct net_device *dev = entry->parent->data;
- struct lapb_parms_struct parms;
- unsigned long parm;
- char *page;
-
- if (lapb_getparms(dev, &parms)) {
- return -ENODEV;
- }
-
- if (!(page = (char *)__get_free_page(GFP_KERNEL))) {
- return -ENOMEM;
- }
-
- if (copy_from_user(page, buffer, count)) {
- free_page((unsigned long)page);
- return -EFAULT;
- }
- if (*(page + count - 1) == '\n') {
- *(page + count - 1) = 0;
- }
-
- if (strcmp(entry->name, FILENAME_T1) == 0) {
- parm=simple_strtoul(page,NULL,10);
- if (parm > 0 && parm < 100) {
- parms.t1=parm;
- lapb_setparms(dev, &parms);
- }
- } else if (strcmp(entry->name, FILENAME_T2) == 0) {
- parm=simple_strtoul(page, NULL, 10);
- if (parm > 0 && parm < 100) {
- parms.t2=parm;
- lapb_setparms(dev, &parms);
- }
- } else if (strcmp(entry->name, FILENAME_N2) == 0) {
- parm=simple_strtoul(page, NULL, 10);
- if (parm > 0 && parm < 100) {
- parms.n2=parm;
- lapb_setparms(dev, &parms);
- }
- } else if (strcmp(entry->name, FILENAME_WINDOW) == 0) {
- parms.window = simple_strtoul(page, NULL, 10);
- lapb_setparms(dev, &parms);
- } else if (strcmp(entry->name, FILENAME_MODE) == 0) {
- if (comx_strcasecmp(page, "dte") == 0) {
- parms.mode &= ~(LAPB_DCE | LAPB_DTE);
- parms.mode |= LAPB_DTE;
- } else if (comx_strcasecmp(page, "dce") == 0) {
- parms.mode &= ~(LAPB_DTE | LAPB_DCE);
- parms.mode |= LAPB_DCE;
- } else if (comx_strcasecmp(page, "std") == 0 ||
- comx_strcasecmp(page, "standard") == 0) {
- parms.mode &= ~LAPB_EXTENDED;
- parms.mode |= LAPB_STANDARD;
- } else if (comx_strcasecmp(page, "ext") == 0 ||
- comx_strcasecmp(page, "extended") == 0) {
- parms.mode &= ~LAPB_STANDARD;
- parms.mode |= LAPB_EXTENDED;
- }
- lapb_setparms(dev, &parms);
- } else {
- printk(KERN_ERR "comxlapb_write_proc: internal error, filename %s\n",
- entry->name);
- return -EBADF;
- }
-
- free_page((unsigned long)page);
- return count;
-}
-
-static void comxlapb_connected(struct net_device *dev, int reason)
-{
- struct comx_channel *ch = dev->priv;
- struct proc_dir_entry *comxdir = ch->procdir->subdir;
-
- if (ch->debug_flags & DEBUG_COMX_LAPB) {
- comx_debug(ch->dev, "%s: lapb connected, reason: %d\n",
- ch->dev->name, reason);
- }
-
- if (ch->dev->type == ARPHRD_X25) {
- unsigned char *p;
- struct sk_buff *skb;
-
- if ((skb = dev_alloc_skb(1)) == NULL) {
- printk(KERN_ERR "comxlapb: out of memory!\n");
- return;
- }
- p = skb_put(skb,1);
- *p = 0x01; // link established
- skb->dev = ch->dev;
- skb->protocol = htons(ETH_P_X25);
- skb->mac.raw = skb->data;
- skb->pkt_type = PACKET_HOST;
-
- netif_rx(skb);
- ch->dev->last_rx = jiffies;
- }
-
- for (; comxdir; comxdir = comxdir->next) {
- if (strcmp(comxdir->name, FILENAME_MODE) == 0) {
- comxdir->mode = S_IFREG | 0444;
- }
- }
-
-
- ch->line_status |= PROTO_UP;
- comx_status(ch->dev, ch->line_status);
-}
-
-static void comxlapb_disconnected(struct net_device *dev, int reason)
-{
- struct comx_channel *ch = dev->priv;
- struct proc_dir_entry *comxdir = ch->procdir->subdir;
-
- if (ch->debug_flags & DEBUG_COMX_LAPB) {
- comx_debug(ch->dev, "%s: lapb disconnected, reason: %d\n",
- ch->dev->name, reason);
- }
-
- if (ch->dev->type == ARPHRD_X25) {
- unsigned char *p;
- struct sk_buff *skb;
-
- if ((skb = dev_alloc_skb(1)) == NULL) {
- printk(KERN_ERR "comxlapb: out of memory!\n");
- return;
- }
- p = skb_put(skb,1);
- *p = 0x02; // link disconnected
- skb->dev = ch->dev;
- skb->protocol = htons(ETH_P_X25);
- skb->mac.raw = skb->data;
- skb->pkt_type = PACKET_HOST;
-
- netif_rx(skb);
- ch->dev->last_rx = jiffies;
- }
-
- for (; comxdir; comxdir = comxdir->next) {
- if (strcmp(comxdir->name, FILENAME_MODE) == 0) {
- comxdir->mode = S_IFREG | 0644;
- }
- }
-
- ch->line_status &= ~PROTO_UP;
- comx_status(ch->dev, ch->line_status);
-}
-
-static int comxlapb_data_indication(struct net_device *dev, struct sk_buff *skb)
-{
- struct comx_channel *ch = dev->priv;
-
- if (ch->dev->type == ARPHRD_X25) {
- skb_push(skb, 1);
-
- if (skb_cow(skb, 1))
- return NET_RX_DROP;
-
- skb->data[0] = 0; // indicate data for X25
- skb->protocol = htons(ETH_P_X25);
- } else {
- skb->protocol = htons(ETH_P_IP);
- }
-
- skb->dev = ch->dev;
- skb->mac.raw = skb->data;
- return comx_rx(ch->dev, skb);
-}
-
-static void comxlapb_data_transmit(struct net_device *dev, struct sk_buff *skb)
-{
- struct comx_channel *ch = dev->priv;
-
- if (ch->HW_send_packet) {
- ch->HW_send_packet(ch->dev, skb);
- }
-}
-
-static int comxlapb_exit(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
-
- dev->flags = 0;
- dev->type = 0;
- dev->mtu = 0;
- dev->hard_header_len = 0;
-
- ch->LINE_rx = NULL;
- ch->LINE_tx = NULL;
- ch->LINE_status = NULL;
- ch->LINE_open = NULL;
- ch->LINE_close = NULL;
- ch->LINE_xmit = NULL;
- ch->LINE_header = NULL;
- ch->LINE_statistics = NULL;
-
- if (ch->debug_flags & DEBUG_COMX_LAPB) {
- comx_debug(dev, "%s: unregistering lapb\n", dev->name);
- }
- lapb_unregister(dev);
-
- remove_proc_entry(FILENAME_T1, ch->procdir);
- remove_proc_entry(FILENAME_T2, ch->procdir);
- remove_proc_entry(FILENAME_N2, ch->procdir);
- remove_proc_entry(FILENAME_MODE, ch->procdir);
- remove_proc_entry(FILENAME_WINDOW, ch->procdir);
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static int comxlapb_init(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct lapb_register_struct lapbreg;
-
- dev->mtu = 1500;
- dev->hard_header_len = 4;
- dev->addr_len = 0;
-
- ch->LINE_rx = comxlapb_rx;
- ch->LINE_tx = comxlapb_tx;
- ch->LINE_status = comxlapb_status;
- ch->LINE_open = comxlapb_open;
- ch->LINE_close = comxlapb_close;
- ch->LINE_xmit = comxlapb_xmit;
- ch->LINE_header = comxlapb_header;
- ch->LINE_statistics = comxlapb_statistics;
-
- lapbreg.connect_confirmation = comxlapb_connected;
- lapbreg.connect_indication = comxlapb_connected;
- lapbreg.disconnect_confirmation = comxlapb_disconnected;
- lapbreg.disconnect_indication = comxlapb_disconnected;
- lapbreg.data_indication = comxlapb_data_indication;
- lapbreg.data_transmit = comxlapb_data_transmit;
- if (lapb_register(dev, &lapbreg)) {
- return -ENOMEM;
- }
- if (ch->debug_flags & DEBUG_COMX_LAPB) {
- comx_debug(dev, "%s: lapb registered\n", dev->name);
- }
-
- if (!create_comxlapb_proc_entry(FILENAME_T1, 0644, 8, ch->procdir)) {
- return -ENOMEM;
- }
- if (!create_comxlapb_proc_entry(FILENAME_T2, 0644, 8, ch->procdir)) {
- return -ENOMEM;
- }
- if (!create_comxlapb_proc_entry(FILENAME_N2, 0644, 8, ch->procdir)) {
- return -ENOMEM;
- }
- if (!create_comxlapb_proc_entry(FILENAME_MODE, 0644, 14, ch->procdir)) {
- return -ENOMEM;
- }
- if (!create_comxlapb_proc_entry(FILENAME_WINDOW, 0644, 0, ch->procdir)) {
- return -ENOMEM;
- }
-
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int comxlapb_init_lapb(struct net_device *dev)
-{
- dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
- dev->type = ARPHRD_LAPB;
-
- return(comxlapb_init(dev));
-}
-
-static int comxlapb_init_x25(struct net_device *dev)
-{
- dev->flags = IFF_NOARP;
- dev->type = ARPHRD_X25;
-
- return(comxlapb_init(dev));
-}
-
-static struct proc_dir_entry *create_comxlapb_proc_entry(char *name, int mode,
- int size, struct proc_dir_entry *dir)
-{
- struct proc_dir_entry *new_file;
-
- if ((new_file = create_proc_entry(name, S_IFREG | mode, dir)) != NULL) {
- new_file->data = (void *)new_file;
- new_file->read_proc = &comxlapb_read_proc;
- new_file->write_proc = &comxlapb_write_proc;
- new_file->size = size;
- new_file->nlink = 1;
- }
- return(new_file);
-}
-
-static struct comx_protocol comxlapb_protocol = {
- "lapb",
- VERSION,
- ARPHRD_LAPB,
- comxlapb_init_lapb,
- comxlapb_exit,
- NULL
-};
-
-static struct comx_protocol comx25_protocol = {
- "x25",
- VERSION,
- ARPHRD_X25,
- comxlapb_init_x25,
- comxlapb_exit,
- NULL
-};
-
-static int __init comx_proto_lapb_init(void)
-{
- int ret;
-
- if ((ret = comx_register_protocol(&comxlapb_protocol)) != 0) {
- return ret;
- }
- return comx_register_protocol(&comx25_protocol);
-}
-
-static void __exit comx_proto_lapb_exit(void)
-{
- comx_unregister_protocol(comxlapb_protocol.name);
- comx_unregister_protocol(comx25_protocol.name);
-}
-
-module_init(comx_proto_lapb_init);
-module_exit(comx_proto_lapb_exit);
-
-MODULE_LICENSE("GPL");
===== drivers/net/wan/comx-proto-ppp.c 1.6 vs edited =====
--- 1.6/drivers/net/wan/comx-proto-ppp.c Thu Sep 11 19:40:53 2003
+++ edited/drivers/net/wan/comx-proto-ppp.c Fri May 7 13:05:52 2004
@@ -1,269 +1 @@
-/*
- * Synchronous PPP / Cisco-HDLC driver for the COMX boards
- *
- * Author: Gergely Madarasz <gorgo@itc.hu>
- *
- * based on skeleton code by Tivadar Szemethy <tiv@itc.hu>
- *
- * Copyright (C) 1999 ITConsult-Pro Co. <info@itc.hu>
- *
- * 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.
- *
- *
- * Version 0.10 (99/06/10):
- * - written the first code :)
- *
- * Version 0.20 (99/06/16):
- * - added hdlc protocol
- * - protocol up is IFF_RUNNING
- *
- * Version 0.21 (99/07/15):
- * - some small fixes with the line status
- *
- * Version 0.22 (99/08/05):
- * - don't test IFF_RUNNING but the pp_link_state of the sppp
- *
- * Version 0.23 (99/12/02):
- * - tbusy fixes
- *
- */
-#define VERSION "0.23"
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/jiffies.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/if_arp.h>
-#include <linux/inetdevice.h>
-#include <asm/uaccess.h>
-#include <linux/init.h>
-
-#include <net/syncppp.h>
-#include "comx.h"
-
-MODULE_AUTHOR("Author: Gergely Madarasz <gorgo@itc.hu>");
-MODULE_DESCRIPTION("Cisco-HDLC / Synchronous PPP driver for the COMX sync serial boards");
-MODULE_LICENSE("GPL");
-
-static struct comx_protocol syncppp_protocol;
-static struct comx_protocol hdlc_protocol;
-
-struct syncppp_data {
- struct timer_list status_timer;
-};
-
-static void syncppp_status_timerfun(unsigned long d) {
- struct net_device *dev=(struct net_device *)d;
- struct comx_channel *ch=dev->priv;
- struct syncppp_data *spch=ch->LINE_privdata;
- struct sppp *sp = (struct sppp *)sppp_of(dev);
-
- if(!(ch->line_status & PROTO_UP) &&
- (sp->pp_link_state==SPPP_LINK_UP)) {
- comx_status(dev, ch->line_status | PROTO_UP);
- }
- if((ch->line_status & PROTO_UP) &&
- (sp->pp_link_state==SPPP_LINK_DOWN)) {
- comx_status(dev, ch->line_status & ~PROTO_UP);
- }
- mod_timer(&spch->status_timer,jiffies + HZ*3);
-}
-
-static int syncppp_tx(struct net_device *dev)
-{
- struct comx_channel *ch=dev->priv;
-
- if(ch->line_status & LINE_UP) {
- netif_wake_queue(dev);
- }
- return 0;
-}
-
-static void syncppp_status(struct net_device *dev, unsigned short status)
-{
- status &= ~(PROTO_UP | PROTO_LOOP);
- if(status & LINE_UP) {
- netif_wake_queue(dev);
- sppp_open(dev);
- } else {
- /* Line went down */
- netif_stop_queue(dev);
- sppp_close(dev);
- }
- comx_status(dev, status);
-}
-
-static int syncppp_open(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct syncppp_data *spch = ch->LINE_privdata;
-
- if (!(ch->init_status & HW_OPEN)) return -ENODEV;
-
- ch->init_status |= LINE_OPEN;
- ch->line_status &= ~(PROTO_UP | PROTO_LOOP);
-
- if(ch->line_status & LINE_UP) {
- sppp_open(dev);
- }
-
- init_timer(&spch->status_timer);
- spch->status_timer.function=syncppp_status_timerfun;
- spch->status_timer.data=(unsigned long)dev;
- spch->status_timer.expires=jiffies + HZ*3;
- add_timer(&spch->status_timer);
-
- return 0;
-}
-
-static int syncppp_close(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct syncppp_data *spch = ch->LINE_privdata;
-
- if (!(ch->init_status & HW_OPEN)) return -ENODEV;
- del_timer(&spch->status_timer);
-
- sppp_close(dev);
-
- ch->init_status &= ~LINE_OPEN;
- ch->line_status &= ~(PROTO_UP | PROTO_LOOP);
-
- return 0;
-}
-
-static int syncppp_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
-
- netif_stop_queue(dev);
- switch(ch->HW_send_packet(dev, skb)) {
- case FRAME_QUEUED:
- netif_wake_queue(dev);
- break;
- case FRAME_ACCEPTED:
- case FRAME_DROPPED:
- break;
- case FRAME_ERROR:
- printk(KERN_ERR "%s: Transmit frame error (len %d)\n",
- dev->name, skb->len);
- break;
- }
- return 0;
-}
-
-
-static int syncppp_statistics(struct net_device *dev, char *page)
-{
- int len = 0;
-
- len += sprintf(page + len, " ");
- return len;
-}
-
-
-static int syncppp_exit(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
-
- sppp_detach(dev);
-
- dev->flags = 0;
- dev->type = 0;
- dev->mtu = 0;
-
- ch->LINE_rx = NULL;
- ch->LINE_tx = NULL;
- ch->LINE_status = NULL;
- ch->LINE_open = NULL;
- ch->LINE_close = NULL;
- ch->LINE_xmit = NULL;
- ch->LINE_header = NULL;
- ch->LINE_rebuild_header = NULL;
- ch->LINE_statistics = NULL;
-
- kfree(ch->LINE_privdata);
- ch->LINE_privdata = NULL;
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static int syncppp_init(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct ppp_device *pppdev = (struct ppp_device *)ch->if_ptr;
-
- ch->LINE_privdata = kmalloc(sizeof(struct syncppp_data), GFP_KERNEL);
- if (!ch->LINE_privdata)
- return -ENOMEM;
-
- pppdev->dev = dev;
- sppp_attach(pppdev);
-
- if(ch->protocol == &hdlc_protocol) {
- pppdev->sppp.pp_flags |= PP_CISCO;
- dev->type = ARPHRD_HDLC;
- } else {
- pppdev->sppp.pp_flags &= ~PP_CISCO;
- dev->type = ARPHRD_PPP;
- }
-
- ch->LINE_rx = sppp_input;
- ch->LINE_tx = syncppp_tx;
- ch->LINE_status = syncppp_status;
- ch->LINE_open = syncppp_open;
- ch->LINE_close = syncppp_close;
- ch->LINE_xmit = syncppp_xmit;
- ch->LINE_header = NULL;
- ch->LINE_statistics = syncppp_statistics;
-
-
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static struct comx_protocol syncppp_protocol = {
- "ppp",
- VERSION,
- ARPHRD_PPP,
- syncppp_init,
- syncppp_exit,
- NULL
-};
-
-static struct comx_protocol hdlc_protocol = {
- "hdlc",
- VERSION,
- ARPHRD_PPP,
- syncppp_init,
- syncppp_exit,
- NULL
-};
-
-static int __init comx_proto_ppp_init(void)
-{
- int ret;
-
- ret = comx_register_protocol(&hdlc_protocol);
- if (!ret) {
- ret = comx_register_protocol(&syncppp_protocol);
- if (ret)
- comx_unregister_protocol(hdlc_protocol.name);
- }
- return ret;
-}
-
-static void __exit comx_proto_ppp_exit(void)
-{
- comx_unregister_protocol(syncppp_protocol.name);
- comx_unregister_protocol(hdlc_protocol.name);
-}
-
-module_init(comx_proto_ppp_init);
-module_exit(comx_proto_ppp_exit);
===== drivers/net/wan/comx.c 1.23 vs edited =====
--- 1.23/drivers/net/wan/comx.c Thu Mar 18 22:27:11 2004
+++ edited/drivers/net/wan/comx.c Fri May 7 13:05:52 2004
@@ -1,1128 +1 @@
-/*
- * Device driver framework for the COMX line of synchronous serial boards
- *
- * for Linux kernel 2.2.X / 2.4.X
- *
- * Original authors: Arpad Bakay <bakay.arpad@synergon.hu>,
- * Peter Bajan <bajan.peter@synergon.hu>,
- * Previous maintainer: Tivadar Szemethy <tiv@itc.hu>
- * Current maintainer: Gergely Madarasz <gorgo@itc.hu>
- *
- * Copyright (C) 1995-1999 ITConsult-Pro Co.
- *
- * Contributors:
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br> (0.85)
- *
- * 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.
- *
- * Version 0.80 (99/06/11):
- * - clean up source code (playing a bit of indent)
- * - port back to kernel, add support for non-module versions
- * - add support for board resets when channel protocol is down
- * - reset the device structure after protocol exit
- * the syncppp driver needs it
- * - add support for /proc/comx/protocols and
- * /proc/comx/boardtypes
- *
- * Version 0.81 (99/06/21):
- * - comment out the board reset support code, the locomx
- * driver seems not buggy now
- * - printk() levels fixed
- *
- * Version 0.82 (99/07/08):
- * - Handle stats correctly if the lowlevel driver is
- * is not a comx one (locomx - z85230)
- *
- * Version 0.83 (99/07/15):
- * - reset line_status when interface is down
- *
- * Version 0.84 (99/12/01):
- * - comx_status should not check for IFF_UP (to report
- * line status from dev->open())
- *
- * Version 0.85 (00/08/15):
- * - resource release on failure in comx_mkdir
- * - fix return value on failure at comx_write_proc
- *
- * Changed (00/10/29, Henner Eisen):
- * - comx_rx() / comxlapb_data_indication() return status.
- */
-#define VERSION "0.85"
-
-#include <linux/config.h>
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/jiffies.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <asm/uaccess.h>
-#include <linux/ctype.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
-#ifndef CONFIG_PROC_FS
-#error For now, COMX really needs the /proc filesystem
-#endif
-
-#include <net/syncppp.h>
-#include "comx.h"
-
-MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>");
-MODULE_DESCRIPTION("Common code for the COMX synchronous serial adapters");
-MODULE_LICENSE("GPL");
-
-static struct comx_hardware *comx_channels = NULL;
-static struct comx_protocol *comx_lines = NULL;
-
-static int comx_mkdir(struct inode *, struct dentry *, int);
-static int comx_rmdir(struct inode *, struct dentry *);
-static struct dentry *comx_lookup(struct inode *, struct dentry *, struct nameidata *);
-
-static struct inode_operations comx_root_inode_ops = {
- .lookup = comx_lookup,
- .mkdir = comx_mkdir,
- .rmdir = comx_rmdir,
-};
-
-static int comx_delete_dentry(struct dentry *dentry);
-static struct proc_dir_entry *create_comx_proc_entry(char *name, int mode,
- int size, struct proc_dir_entry *dir);
-
-static struct dentry_operations comx_dentry_operations = {
- .d_delete = comx_delete_dentry,
-};
-
-
-static struct proc_dir_entry * comx_root_dir;
-
-struct comx_debugflags_struct comx_debugflags[] = {
- { "comx_rx", DEBUG_COMX_RX },
- { "comx_tx", DEBUG_COMX_TX },
- { "hw_tx", DEBUG_HW_TX },
- { "hw_rx", DEBUG_HW_RX },
- { "hdlc_keepalive", DEBUG_HDLC_KEEPALIVE },
- { "comxppp", DEBUG_COMX_PPP },
- { "comxlapb", DEBUG_COMX_LAPB },
- { "dlci", DEBUG_COMX_DLCI },
- { NULL, 0 }
-};
-
-
-int comx_debug(struct net_device *dev, char *fmt, ...)
-{
- struct comx_channel *ch = dev->priv;
- char *page,*str;
- va_list args;
- int len;
-
- if (!ch->debug_area) return 0;
-
- if (!(page = (char *)__get_free_page(GFP_ATOMIC))) return -ENOMEM;
-
- va_start(args, fmt);
- len = vsprintf(str = page, fmt, args);
- va_end(args);
-
- if (len >= PAGE_SIZE) {
- printk(KERN_ERR "comx_debug: PANIC! len = %d !!!\n", len);
- free_page((unsigned long)page);
- return -EINVAL;
- }
-
- while (len) {
- int to_copy;
- int free = (ch->debug_start - ch->debug_end + ch->debug_size)
- % ch->debug_size;
-
- to_copy = min_t(int, free ? free : ch->debug_size,
- min_t(int, ch->debug_size - ch->debug_end, len));
- memcpy(ch->debug_area + ch->debug_end, str, to_copy);
- str += to_copy;
- len -= to_copy;
- ch->debug_end = (ch->debug_end + to_copy) % ch->debug_size;
- if (ch->debug_start == ch->debug_end) // Full ? push start away
- ch->debug_start = (ch->debug_start + len + 1) %
- ch->debug_size;
- ch->debug_file->size = (ch->debug_end - ch->debug_start +
- ch->debug_size) % ch->debug_size;
- }
-
- free_page((unsigned long)page);
- return 0;
-}
-
-int comx_debug_skb(struct net_device *dev, struct sk_buff *skb, char *msg)
-{
- struct comx_channel *ch = dev->priv;
-
- if (!ch->debug_area) return 0;
- if (!skb) comx_debug(dev, "%s: %s NULL skb\n\n", dev->name, msg);
- if (!skb->len) comx_debug(dev, "%s: %s empty skb\n\n", dev->name, msg);
-
- return comx_debug_bytes(dev, skb->data, skb->len, msg);
-}
-
-int comx_debug_bytes(struct net_device *dev, unsigned char *bytes, int len,
- char *msg)
-{
- int pos = 0;
- struct comx_channel *ch = dev->priv;
-
- if (!ch->debug_area) return 0;
-
- comx_debug(dev, "%s: %s len %d\n", dev->name, msg, len);
-
- while (pos != len) {
- char line[80];
- int i = 0;
-
- memset(line, 0, 80);
- sprintf(line,"%04d ", pos);
- do {
- sprintf(line + 5 + (pos % 16) * 3, "%02x", bytes[pos]);
- sprintf(line + 60 + (pos % 16), "%c",
- isprint(bytes[pos]) ? bytes[pos] : '.');
- pos++;
- } while (pos != len && pos % 16);
-
- while ( i++ != 78 ) if (line[i] == 0) line[i] = ' ';
- line[77] = '\n';
- line[78] = 0;
-
- comx_debug(dev, "%s", line);
- }
- comx_debug(dev, "\n");
- return 0;
-}
-
-static void comx_loadavg_timerfun(unsigned long d)
-{
- struct net_device *dev = (struct net_device *)d;
- struct comx_channel *ch = dev->priv;
-
- ch->avg_bytes[ch->loadavg_counter] = ch->current_stats->rx_bytes;
- ch->avg_bytes[ch->loadavg_counter + ch->loadavg_size] =
- ch->current_stats->tx_bytes;
-
- ch->loadavg_counter = (ch->loadavg_counter + 1) % ch->loadavg_size;
-
- mod_timer(&ch->loadavg_timer,jiffies + HZ * ch->loadavg[0]);
-}
-
-#if 0
-static void comx_reset_timerfun(unsigned long d)
-{
- struct net_device *dev = (struct net_device *)d;
- struct comx_channel *ch = dev->priv;
-
- if(!(ch->line_status & (PROTO_LOOP | PROTO_UP))) {
- if(test_and_set_bit(0,&ch->reset_pending) && ch->HW_reset) {
- ch->HW_reset(dev);
- }
- }
-
- mod_timer(&ch->reset_timer, jiffies + HZ * ch->reset_timeout);
-}
-#endif
-
-static int comx_open(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct proc_dir_entry *comxdir = ch->procdir->subdir;
- int ret=0;
-
- if (!ch->protocol || !ch->hardware) return -ENODEV;
-
- if ((ret = ch->HW_open(dev))) return ret;
- if ((ret = ch->LINE_open(dev))) {
- ch->HW_close(dev);
- return ret;
- };
-
- for (; comxdir ; comxdir = comxdir->next) {
- if (strcmp(comxdir->name, FILENAME_HARDWARE) == 0 ||
- strcmp(comxdir->name, FILENAME_PROTOCOL) == 0)
- comxdir->mode = S_IFREG | 0444;
- }
-
-#if 0
- ch->reset_pending = 1;
- ch->reset_timeout = 30;
- ch->reset_timer.function = comx_reset_timerfun;
- ch->reset_timer.data = (unsigned long)dev;
- ch->reset_timer.expires = jiffies + HZ * ch->reset_timeout;
- add_timer(&ch->reset_timer);
-#endif
-
- return 0;
-}
-
-static int comx_close(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- struct proc_dir_entry *comxdir = ch->procdir->subdir;
- int ret = -ENODEV;
-
- if (test_and_clear_bit(0, &ch->lineup_pending)) {
- del_timer(&ch->lineup_timer);
- }
-
-#if 0
- del_timer(&ch->reset_timer);
-#endif
-
- if (ch->init_status & LINE_OPEN && ch->protocol && ch->LINE_close) {
- ret = ch->LINE_close(dev);
- }
-
- if (ret) return ret;
-
- if (ch->init_status & HW_OPEN && ch->hardware && ch->HW_close) {
- ret = ch->HW_close(dev);
- }
-
- ch->line_status=0;
-
- for (; comxdir ; comxdir = comxdir->next) {
- if (strcmp(comxdir->name, FILENAME_HARDWARE) == 0 ||
- strcmp(comxdir->name, FILENAME_PROTOCOL) == 0)
- comxdir->mode = S_IFREG | 0644;
- }
-
- return ret;
-}
-
-void comx_status(struct net_device *dev, int status)
-{
- struct comx_channel *ch = dev->priv;
-
-#if 0
- if(status & (PROTO_UP | PROTO_LOOP)) {
- clear_bit(0,&ch->reset_pending);
- }
-#endif
-
- printk(KERN_NOTICE "Interface %s: modem status %s, line protocol %s\n",
- dev->name, status & LINE_UP ? "UP" : "DOWN",
- status & PROTO_LOOP ? "LOOP" : status & PROTO_UP ?
- "UP" : "DOWN");
-
- ch->line_status = status;
-}
-
-static int comx_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
- int rc;
-
- if (skb->len > dev->mtu + dev->hard_header_len) {
- printk(KERN_ERR "comx_xmit: %s: skb->len %d > dev->mtu %d\n", dev->name,
- (int)skb->len, dev->mtu);
- }
-
- if (ch->debug_flags & DEBUG_COMX_TX) {
- comx_debug_skb(dev, skb, "comx_xmit skb");
- }
-
- rc=ch->LINE_xmit(skb, dev);
-// if (!rc) dev_kfree_skb(skb);
-
- return rc;
-}
-
-static int comx_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, void *daddr, void *saddr, unsigned len)
-{
- struct comx_channel *ch = dev->priv;
-
- if (ch->LINE_header) {
- return (ch->LINE_header(skb, dev, type, daddr, saddr, len));
- } else {
- return 0;
- }
-}
-
-static int comx_rebuild_header(struct sk_buff *skb)
-{
- struct net_device *dev = skb->dev;
- struct comx_channel *ch = dev->priv;
-
- if (ch->LINE_rebuild_header) {
- return(ch->LINE_rebuild_header(skb));
- } else {
- return 0;
- }
-}
-
-int comx_rx(struct net_device *dev, struct sk_buff *skb)
-{
- struct comx_channel *ch = dev->priv;
-
- if (ch->debug_flags & DEBUG_COMX_RX) {
- comx_debug_skb(dev, skb, "comx_rx skb");
- }
- if (skb) {
- netif_rx(skb);
- dev->last_rx = jiffies;
- }
- return 0;
-}
-
-static struct net_device_stats *comx_stats(struct net_device *dev)
-{
- struct comx_channel *ch = dev->priv;
-
- return ch->current_stats;
-}
-
-void comx_lineup_func(unsigned long d)
-{
- struct net_device *dev = (struct net_device *)d;
- struct comx_channel *ch = dev->priv;
-
- del_timer(&ch->lineup_timer);
- clear_bit(0, &ch->lineup_pending);
-
- if (ch->LINE_status) {
- ch->LINE_status(dev, ch->line_status |= LINE_UP);
- }
-}
-
-#define LOADAVG(avg, off) (int) \
- ((ch->avg_bytes[(ch->loadavg_counter - 1 + ch->loadavg_size * 2) \
- % ch->loadavg_size + off] - ch->avg_bytes[(ch->loadavg_counter - 1 \
- - ch->loadavg[avg] / ch->loadavg[0] + ch->loadavg_size * 2) \
- % ch->loadavg_size + off]) / ch->loadavg[avg] * 8)
-
-static int comx_statistics(struct net_device *dev, char *page)
-{
- struct comx_channel *ch = dev->priv;
- int len = 0;
- int tmp;
- int i = 0;
- char tmpstr[20];
- int tmpstrlen = 0;
-
- len += sprintf(page + len, "Interface administrative status is %s, "
- "modem status is %s, protocol is %s\n",
- dev->flags & IFF_UP ? "UP" : "DOWN",
- ch->line_status & LINE_UP ? "UP" : "DOWN",
- ch->line_status & PROTO_LOOP ? "LOOP" :
- ch->line_status & PROTO_UP ? "UP" : "DOWN");
- len += sprintf(page + len, "Modem status changes: %lu, Transmitter status "
- "is %s, tbusy: %d\n", ch->current_stats->tx_carrier_errors, ch->HW_txe ?
- ch->HW_txe(dev) ? "IDLE" : "BUSY" : "NOT READY", netif_running(dev));
- len += sprintf(page + len, "Interface load (input): %d / %d / %d bits/s (",
- LOADAVG(0,0), LOADAVG(1, 0), LOADAVG(2, 0));
- tmpstr[0] = 0;
- for (i=0; i != 3; i++) {
- char tf;
-
- tf = ch->loadavg[i] % 60 == 0 &&
- ch->loadavg[i] / 60 > 0 ? 'm' : 's';
- tmpstrlen += sprintf(tmpstr + tmpstrlen, "%d%c%s",
- ch->loadavg[i] / (tf == 'm' ? 60 : 1), tf,
- i == 2 ? ")\n" : "/");
- }
- len += sprintf(page + len,
- "%s (output): %d / %d / %d bits/s (%s", tmpstr,
- LOADAVG(0,ch->loadavg_size), LOADAVG(1, ch->loadavg_size),
- LOADAVG(2, ch->loadavg_size), tmpstr);
-
- len += sprintf(page + len, "Debug flags: ");
- tmp = len; i = 0;
- while (comx_debugflags[i].name) {
- if (ch->debug_flags & comx_debugflags[i].value)
- len += sprintf(page + len, "%s ",
- comx_debugflags[i].name);
- i++;
- }
- len += sprintf(page + len, "%s\n", tmp == len ? "none" : "");
-
- len += sprintf(page + len, "RX errors: len: %lu, overrun: %lu, crc: %lu, "
- "aborts: %lu\n buffer overrun: %lu, pbuffer overrun: %lu\n"
- "TX errors: underrun: %lu\n",
- ch->current_stats->rx_length_errors, ch->current_stats->rx_over_errors,
- ch->current_stats->rx_crc_errors, ch->current_stats->rx_frame_errors,
- ch->current_stats->rx_missed_errors, ch->current_stats->rx_fifo_errors,
- ch->current_stats->tx_fifo_errors);
-
- if (ch->LINE_statistics && (ch->init_status & LINE_OPEN)) {
- len += ch->LINE_statistics(dev, page + len);
- } else {
- len += sprintf(page+len, "Line status: driver not initialized\n");
- }
- if (ch->HW_statistics && (ch->init_status & HW_OPEN)) {
- len += ch->HW_statistics(dev, page + len);
- } else {
- len += sprintf(page+len, "Board status: driver not initialized\n");
- }
-
- return len;
-}
-
-static int comx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- struct comx_channel *ch = dev->priv;
-
- if (ch->LINE_ioctl) {
- return(ch->LINE_ioctl(dev, ifr, cmd));
- }
- return -EINVAL;
-}
-
-static void comx_reset_dev(struct net_device *dev)
-{
- dev->open = comx_open;
- dev->stop = comx_close;
- dev->hard_start_xmit = comx_xmit;
- dev->hard_header = comx_header;
- dev->rebuild_header = comx_rebuild_header;
- dev->get_stats = comx_stats;
- dev->do_ioctl = comx_ioctl;
- dev->change_mtu = NULL;
- dev->tx_queue_len = 20;
- dev->flags = IFF_NOARP;
-}
-
-static int comx_init_dev(struct net_device *dev)
-{
- struct comx_channel *ch;
-
- if ((ch = kmalloc(sizeof(struct comx_channel), GFP_KERNEL)) == NULL) {
- return -ENOMEM;
- }
- memset(ch, 0, sizeof(struct comx_channel));
-
- ch->loadavg[0] = 5;
- ch->loadavg[1] = 300;
- ch->loadavg[2] = 900;
- ch->loadavg_size = ch->loadavg[2] / ch->loadavg[0] + 1;
- if ((ch->avg_bytes = kmalloc(ch->loadavg_size *
- sizeof(unsigned long) * 2, GFP_KERNEL)) == NULL) {
- kfree(ch);
- return -ENOMEM;
- }
-
- memset(ch->avg_bytes, 0, ch->loadavg_size * sizeof(unsigned long) * 2);
- ch->loadavg_counter = 0;
- ch->loadavg_timer.function = comx_loadavg_timerfun;
- ch->loadavg_timer.data = (unsigned long)dev;
- ch->loadavg_timer.expires = jiffies + HZ * ch->loadavg[0];
- add_timer(&ch->loadavg_timer);
-
- dev->priv = (void *)ch;
- ch->dev = dev;
- ch->line_status &= ~LINE_UP;
-
- ch->current_stats = &ch->stats;
-
- comx_reset_dev(dev);
- return 0;
-}
-
-static int comx_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct proc_dir_entry *file = (struct proc_dir_entry *)data;
- struct net_device *dev = file->parent->data;
- struct comx_channel *ch = dev->priv;
- int len = 0;
-
- if (strcmp(file->name, FILENAME_STATUS) == 0) {
- len = comx_statistics(dev, page);
- } else if (strcmp(file->name, FILENAME_HARDWARE) == 0) {
- len = sprintf(page, "%s\n", ch->hardware ?
- ch->hardware->name : HWNAME_NONE);
- } else if (strcmp(file->name, FILENAME_PROTOCOL) == 0) {
- len = sprintf(page, "%s\n", ch->protocol ?
- ch->protocol->name : PROTONAME_NONE);
- } else if (strcmp(file->name, FILENAME_LINEUPDELAY) == 0) {
- len = sprintf(page, "%01d\n", ch->lineup_delay);
- }
-
- if (off >= len) {
- *eof = 1;
- return 0;
- }
-
- *start = page + off;
- if (count >= len - off) {
- *eof = 1;
- }
- return min_t(int, count, len - off);
-}
-
-
-static int comx_root_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
-{
- struct proc_dir_entry *file = (struct proc_dir_entry *)data;
- struct comx_hardware *hw;
- struct comx_protocol *line;
-
- int len = 0;
-
- if (strcmp(file->name, FILENAME_HARDWARELIST) == 0) {
- for(hw=comx_channels;hw;hw=hw->next)
- len+=sprintf(page+len, "%s\n", hw->name);
- } else if (strcmp(file->name, FILENAME_PROTOCOLLIST) == 0) {
- for(line=comx_lines;line;line=line->next)
- len+=sprintf(page+len, "%s\n", line->name);
- }
-
- if (off >= len) {
- *eof = 1;
- return 0;
- }
-
- *start = page + off;
- if (count >= len - off) {
- *eof = 1;
- }
- return min_t(int, count, len - off);
-}
-
-
-
-static int comx_write_proc(struct file *file, const char *buffer, u_long count,
- void *data)
-{
- struct proc_dir_entry *entry = (struct proc_dir_entry *)data;
- struct net_device *dev = (struct net_device *)entry->parent->data;
- struct comx_channel *ch = dev->priv;
- char *page;
- struct comx_hardware *hw = comx_channels;
- struct comx_protocol *line = comx_lines;
- int ret=0;
-
- if (count > PAGE_SIZE) {
- printk(KERN_ERR "count is %lu > %d!!!\n", count, (int)PAGE_SIZE);
- return -ENOSPC;
- }
-
- if (!(page = (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM;
-
- if(copy_from_user(page, buffer, count))
- {
- count = -EFAULT;
- goto out;
- }
-
- if (page[count-1] == '\n')
- page[count-1] = '\0';
- else if (count < PAGE_SIZE)
- page[count] = '\0';
- else if (page[count]) {
- count = -EINVAL;
- goto out;
- }
-
- if (strcmp(entry->name, FILENAME_DEBUG) == 0) {
- int i;
- int ret = 0;
-
- if ((i = simple_strtoul(page, NULL, 10)) != 0) {
- unsigned long flags;
-
- save_flags(flags); cli();
- if (ch->debug_area) kfree(ch->debug_area);
- if ((ch->debug_area = kmalloc(ch->debug_size = i,
- GFP_KERNEL)) == NULL) {
- ret = -ENOMEM;
- }
- ch->debug_start = ch->debug_end = 0;
- restore_flags(flags);
- free_page((unsigned long)page);
- return ret ? ret : count;
- }
-
- if (*page != '+' && *page != '-') {
- free_page((unsigned long)page);
- return -EINVAL;
- }
- while (comx_debugflags[i].value &&
- strncmp(comx_debugflags[i].name, page + 1,
- strlen(comx_debugflags[i].name))) {
- i++;
- }
-
- if (comx_debugflags[i].value == 0) {
- printk(KERN_ERR "Invalid debug option\n");
- free_page((unsigned long)page);
- return -EINVAL;
- }
- if (*page == '+') {
- ch->debug_flags |= comx_debugflags[i].value;
- } else {
- ch->debug_flags &= ~comx_debugflags[i].value;
- }
- } else if (strcmp(entry->name, FILENAME_HARDWARE) == 0) {
- if(strlen(page)>10) {
- free_page((unsigned long)page);
- return -EINVAL;
- }
- while (hw) {
- if (strcmp(hw->name, page) == 0) {
- break;
- } else {
- hw = hw->next;
- }
- }
-#ifdef CONFIG_KMOD
- if(!hw && comx_strcasecmp(HWNAME_NONE,page) != 0){
- request_module("comx-hw-%s",page);
- }
- hw=comx_channels;
- while (hw) {
- if (comx_strcasecmp(hw->name, page) == 0) {
- break;
- } else {
- hw = hw->next;
- }
- }
-#endif
-
- if (comx_strcasecmp(HWNAME_NONE, page) != 0 && !hw) {
- free_page((unsigned long)page);
- return -ENODEV;
- }
- if (ch->init_status & HW_OPEN) {
- free_page((unsigned long)page);
- return -EBUSY;
- }
- if (ch->hardware && ch->hardware->hw_exit &&
- (ret=ch->hardware->hw_exit(dev))) {
- free_page((unsigned long)page);
- return ret;
- }
- ch->hardware = hw;
- entry->size = strlen(page) + 1;
- if (hw && hw->hw_init) hw->hw_init(dev);
- } else if (strcmp(entry->name, FILENAME_PROTOCOL) == 0) {
- if(strlen(page)>10) {
- free_page((unsigned long)page);
- return -EINVAL;
- }
- while (line) {
- if (comx_strcasecmp(line->name, page) == 0) {
- break;
- } else {
- line = line->next;
- }
- }
-#ifdef CONFIG_KMOD
- if(!line && comx_strcasecmp(PROTONAME_NONE, page) != 0) {
- request_module("comx-proto-%s",page);
- }
- line=comx_lines;
- while (line) {
- if (comx_strcasecmp(line->name, page) == 0) {
- break;
- } else {
- line = line->next;
- }
- }
-#endif
-
- if (comx_strcasecmp(PROTONAME_NONE, page) != 0 && !line) {
- free_page((unsigned long)page);
- return -ENODEV;
- }
-
- if (ch->init_status & LINE_OPEN) {
- free_page((unsigned long)page);
- return -EBUSY;
- }
-
- if (ch->protocol && ch->protocol->line_exit &&
- (ret=ch->protocol->line_exit(dev))) {
- free_page((unsigned long)page);
- return ret;
- }
- ch->protocol = line;
- entry->size = strlen(page) + 1;
- comx_reset_dev(dev);
- if (line && line->line_init) line->line_init(dev);
- } else if (strcmp(entry->name, FILENAME_LINEUPDELAY) == 0) {
- int i;
-
- if ((i = simple_strtoul(page, NULL, 10)) != 0) {
- if (i >=0 && i < 10) {
- ch->lineup_delay = i;
- } else {
- printk(KERN_ERR "comx: invalid lineup_delay value\n");
- }
- }
- }
-out:
- free_page((unsigned long)page);
- return count;
-}
-
-static int comx_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
- struct proc_dir_entry *new_dir, *debug_file;
- struct net_device *dev;
- struct comx_channel *ch;
- int ret = -EIO;
-
- if ((dev = kmalloc(sizeof(struct net_device), GFP_KERNEL)) == NULL) {
- return -ENOMEM;
- }
- memset(dev, 0, sizeof(struct net_device));
-
- lock_kernel();
- if ((new_dir = create_proc_entry(dentry->d_name.name, mode | S_IFDIR,
- comx_root_dir)) == NULL) {
- goto cleanup_dev;
- }
-
- new_dir->nlink = 2;
- new_dir->data = NULL; // ide jon majd a struct dev
-
- /* Ezek kellenek */
- if (!create_comx_proc_entry(FILENAME_HARDWARE, 0644,
- strlen(HWNAME_NONE) + 1, new_dir)) {
- goto cleanup_new_dir;
- }
- if (!create_comx_proc_entry(FILENAME_PROTOCOL, 0644,
- strlen(PROTONAME_NONE) + 1, new_dir)) {
- goto cleanup_filename_hardware;
- }
- if (!create_comx_proc_entry(FILENAME_STATUS, 0444, 0, new_dir)) {
- goto cleanup_filename_protocol;
- }
- if (!create_comx_proc_entry(FILENAME_LINEUPDELAY, 0644, 2, new_dir)) {
- goto cleanup_filename_status;
- }
-
- if ((debug_file = create_proc_entry(FILENAME_DEBUG,
- S_IFREG | 0644, new_dir)) == NULL) {
- goto cleanup_filename_lineupdelay;
- }
- debug_file->data = (void *)debug_file;
- debug_file->read_proc = NULL; // see below
- debug_file->write_proc = &comx_write_proc;
- debug_file->nlink = 1;
-
- strcpy(dev->name, (char *)new_dir->name);
- dev->init = comx_init_dev;
-
- if (register_netdevice(dev)) {
- goto cleanup_filename_debug;
- }
- ch = dev->priv;
- if((ch->if_ptr = (void *)kmalloc(sizeof(struct ppp_device),
- GFP_KERNEL)) == NULL) {
- goto cleanup_register;
- }
- memset(ch->if_ptr, 0, sizeof(struct ppp_device));
- ch->debug_file = debug_file;
- ch->procdir = new_dir;
- new_dir->data = dev;
-
- ch->debug_start = ch->debug_end = 0;
- if ((ch->debug_area = kmalloc(ch->debug_size = DEFAULT_DEBUG_SIZE,
- GFP_KERNEL)) == NULL) {
- ret = -ENOMEM;
- goto cleanup_if_ptr;
- }
-
- ch->lineup_delay = DEFAULT_LINEUP_DELAY;
-
- MOD_INC_USE_COUNT;
- unlock_kernel();
- return 0;
-cleanup_if_ptr:
- kfree(ch->if_ptr);
-cleanup_register:
- unregister_netdevice(dev);
-cleanup_filename_debug:
- remove_proc_entry(FILENAME_DEBUG, new_dir);
-cleanup_filename_lineupdelay:
- remove_proc_entry(FILENAME_LINEUPDELAY, new_dir);
-cleanup_filename_status:
- remove_proc_entry(FILENAME_STATUS, new_dir);
-cleanup_filename_protocol:
- remove_proc_entry(FILENAME_PROTOCOL, new_dir);
-cleanup_filename_hardware:
- remove_proc_entry(FILENAME_HARDWARE, new_dir);
-cleanup_new_dir:
- remove_proc_entry(dentry->d_name.name, comx_root_dir);
-cleanup_dev:
- kfree(dev);
- unlock_kernel();
- return ret;
-}
-
-static int comx_rmdir(struct inode *dir, struct dentry *dentry)
-{
- struct proc_dir_entry *entry = PDE(dentry->d_inode);
- struct net_device *dev;
- struct comx_channel *ch;
- int ret;
-
- lock_kernel();
- dev = entry->data;
- ch = dev->priv;
- if (dev->flags & IFF_UP) {
- printk(KERN_ERR "%s: down interface before removing it\n", dev->name);
- unlock_kernel();
- return -EBUSY;
- }
-
- if (ch->protocol && ch->protocol->line_exit &&
- (ret=ch->protocol->line_exit(dev))) {
- unlock_kernel();
- return ret;
- }
- if (ch->hardware && ch->hardware->hw_exit &&
- (ret=ch->hardware->hw_exit(dev))) {
- if(ch->protocol && ch->protocol->line_init) {
- ch->protocol->line_init(dev);
- }
- unlock_kernel();
- return ret;
- }
- ch->protocol = NULL;
- ch->hardware = NULL;
-
- del_timer(&ch->loadavg_timer);
- kfree(ch->avg_bytes);
-
- unregister_netdev(dev);
- if (ch->debug_area) {
- kfree(ch->debug_area);
- }
- if (dev->priv) {
- kfree(dev->priv);
- }
- free_netdev(dev);
-
- remove_proc_entry(FILENAME_DEBUG, entry);
- remove_proc_entry(FILENAME_LINEUPDELAY, entry);
- remove_proc_entry(FILENAME_STATUS, entry);
- remove_proc_entry(FILENAME_HARDWARE, entry);
- remove_proc_entry(FILENAME_PROTOCOL, entry);
- remove_proc_entry(dentry->d_name.name, comx_root_dir);
-
- MOD_DEC_USE_COUNT;
- unlock_kernel();
- return 0;
-}
-
-static struct dentry *comx_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
- struct proc_dir_entry *de;
- struct inode *inode = NULL;
-
- lock_kernel();
- if ((de = PDE(dir)) != NULL) {
- for (de = de->subdir ; de ; de = de->next) {
- if ((de->namelen == dentry->d_name.len) &&
- (memcmp(dentry->d_name.name, de->name,
- de->namelen) == 0)) {
- if ((inode = proc_get_inode(dir->i_sb,
- de->low_ino, de)) == NULL) {
- printk(KERN_ERR "COMX: lookup error\n");
- unlock_kernel();
- return ERR_PTR(-EINVAL);
- }
- break;
- }
- }
- }
- unlock_kernel();
- dentry->d_op = &comx_dentry_operations;
- d_add(dentry, inode);
- return NULL;
-}
-
-int comx_strcasecmp(const char *cs, const char *ct)
-{
- register signed char __res;
-
- while (1) {
- if ((__res = toupper(*cs) - toupper(*ct++)) != 0 || !*cs++) {
- break;
- }
- }
- return __res;
-}
-
-static int comx_delete_dentry(struct dentry *dentry)
-{
- return 1;
-}
-
-static struct proc_dir_entry *create_comx_proc_entry(char *name, int mode,
- int size, struct proc_dir_entry *dir)
-{
- struct proc_dir_entry *new_file;
-
- if ((new_file = create_proc_entry(name, S_IFREG | mode, dir)) != NULL) {
- new_file->data = (void *)new_file;
- new_file->read_proc = &comx_read_proc;
- new_file->write_proc = &comx_write_proc;
- new_file->size = size;
- new_file->nlink = 1;
- }
- return(new_file);
-}
-
-int comx_register_hardware(struct comx_hardware *comx_hw)
-{
- struct comx_hardware *hw = comx_channels;
-
- if (!hw) {
- comx_channels = comx_hw;
- } else {
- while (hw->next != NULL && strcmp(comx_hw->name, hw->name) != 0) {
- hw = hw->next;
- }
- if (strcmp(comx_hw->name, hw->name) == 0) {
- return -1;
- }
- hw->next = comx_hw;
- }
-
- printk(KERN_INFO "COMX: driver for hardware type %s, version %s\n", comx_hw->name, comx_hw->version);
- return 0;
-}
-
-int comx_unregister_hardware(char *name)
-{
- struct comx_hardware *hw = comx_channels;
-
- if (!hw) {
- return -1;
- }
-
- if (strcmp(hw->name, name) == 0) {
- comx_channels = comx_channels->next;
- return 0;
- }
-
- while (hw->next != NULL && strcmp(hw->next->name,name) != 0) {
- hw = hw->next;
- }
-
- if (hw->next != NULL && strcmp(hw->next->name, name) == 0) {
- hw->next = hw->next->next;
- return 0;
- }
- return -1;
-}
-
-int comx_register_protocol(struct comx_protocol *comx_line)
-{
- struct comx_protocol *pr = comx_lines;
-
- if (!pr) {
- comx_lines = comx_line;
- } else {
- while (pr->next != NULL && strcmp(comx_line->name, pr->name) !=0) {
- pr = pr->next;
- }
- if (strcmp(comx_line->name, pr->name) == 0) {
- return -1;
- }
- pr->next = comx_line;
- }
-
- printk(KERN_INFO "COMX: driver for protocol type %s, version %s\n", comx_line->name, comx_line->version);
- return 0;
-}
-
-int comx_unregister_protocol(char *name)
-{
- struct comx_protocol *pr = comx_lines;
-
- if (!pr) {
- return -1;
- }
-
- if (strcmp(pr->name, name) == 0) {
- comx_lines = comx_lines->next;
- return 0;
- }
-
- while (pr->next != NULL && strcmp(pr->next->name,name) != 0) {
- pr = pr->next;
- }
-
- if (pr->next != NULL && strcmp(pr->next->name, name) == 0) {
- pr->next = pr->next->next;
- return 0;
- }
- return -1;
-}
-
-static int __init comx_init(void)
-{
- struct proc_dir_entry *new_file;
-
- comx_root_dir = create_proc_entry("comx",
- S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, &proc_root);
- if (!comx_root_dir)
- return -ENOMEM;
- comx_root_dir->proc_iops = &comx_root_inode_ops;
-
- if ((new_file = create_proc_entry(FILENAME_HARDWARELIST,
- S_IFREG | 0444, comx_root_dir)) == NULL) {
- return -ENOMEM;
- }
-
- new_file->data = new_file;
- new_file->read_proc = &comx_root_read_proc;
- new_file->write_proc = NULL;
- new_file->nlink = 1;
-
- if ((new_file = create_proc_entry(FILENAME_PROTOCOLLIST,
- S_IFREG | 0444, comx_root_dir)) == NULL) {
- return -ENOMEM;
- }
-
- new_file->data = new_file;
- new_file->read_proc = &comx_root_read_proc;
- new_file->write_proc = NULL;
- new_file->nlink = 1;
-
-
- printk(KERN_INFO "COMX: driver version %s (C) 1995-1999 ITConsult-Pro Co. <info@itc.hu>\n",
- VERSION);
- return 0;
-}
-
-static void __exit comx_exit(void)
-{
- remove_proc_entry(FILENAME_HARDWARELIST, comx_root_dir);
- remove_proc_entry(FILENAME_PROTOCOLLIST, comx_root_dir);
- remove_proc_entry(comx_root_dir->name, &proc_root);
-}
-
-module_init(comx_init);
-module_exit(comx_exit);
-
-EXPORT_SYMBOL(comx_register_hardware);
-EXPORT_SYMBOL(comx_unregister_hardware);
-EXPORT_SYMBOL(comx_register_protocol);
-EXPORT_SYMBOL(comx_unregister_protocol);
-EXPORT_SYMBOL(comx_debug_skb);
-EXPORT_SYMBOL(comx_debug_bytes);
-EXPORT_SYMBOL(comx_debug);
-EXPORT_SYMBOL(comx_lineup_func);
-EXPORT_SYMBOL(comx_status);
-EXPORT_SYMBOL(comx_rx);
-EXPORT_SYMBOL(comx_strcasecmp);
-EXPORT_SYMBOL(comx_root_dir);
===== drivers/net/wan/comx.h 1.2 vs edited =====
--- 1.2/drivers/net/wan/comx.h Tue Feb 5 08:44:27 2002
+++ edited/drivers/net/wan/comx.h Fri May 7 13:05:54 2004
@@ -1,232 +1 @@
-/*
- * General definitions for the COMX driver
- *
- * Original authors: Arpad Bakay <bakay.arpad@synergon.hu>,
- * Peter Bajan <bajan.peter@synergon.hu>,
- * Previous maintainer: Tivadar Szemethy <tiv@itc.hu>
- * Currently maintained by: Gergely Madarasz <gorgo@itc.hu>
- *
- * Copyright (C) 1995-1999 ITConsult-Pro Co. <info@itc.hu>
- *
- * 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.
- *
- *
- * net_device_stats:
- * rx_length_errors rec_len < 4 || rec_len > 2000
- * rx_over_errors receive overrun (OVR)
- * rx_crc_errors rx crc error
- * rx_frame_errors aborts rec'd (ABO)
- * rx_fifo_errors status fifo overrun (PBUFOVR)
- * rx_missed_errors receive buffer overrun (BUFOVR)
- * tx_aborted_errors ?
- * tx_carrier_errors modem line status changes
- * tx_fifo_errors tx underrun (locomx)
- */
-#include <linux/config.h>
-struct comx_protocol {
- char *name;
- char *version;
- unsigned short encap_type;
- int (*line_init)(struct net_device *dev);
- int (*line_exit)(struct net_device *dev);
- struct comx_protocol *next;
- };
-
-struct comx_hardware {
- char *name;
- char *version;
- int (*hw_init)(struct net_device *dev);
- int (*hw_exit)(struct net_device *dev);
- int (*hw_dump)(struct net_device *dev);
- struct comx_hardware *next;
- };
-
-struct comx_channel {
- void *if_ptr; // General purpose pointer
- struct net_device *dev; // Where we belong to
- struct net_device *twin; // On dual-port cards
- struct proc_dir_entry *procdir; // the directory
-
- unsigned char init_status;
- unsigned char line_status;
-
- struct timer_list lineup_timer; // against line jitter
- long int lineup_pending;
- unsigned char lineup_delay;
-
-#if 0
- struct timer_list reset_timer; // for board resetting
- long reset_pending;
- int reset_timeout;
-#endif
-
- struct net_device_stats stats;
- struct net_device_stats *current_stats;
-#if 0
- unsigned long board_resets;
-#endif
- unsigned long *avg_bytes;
- int loadavg_counter, loadavg_size;
- int loadavg[3];
- struct timer_list loadavg_timer;
- int debug_flags;
- char *debug_area;
- int debug_start, debug_end, debug_size;
- struct proc_dir_entry *debug_file;
-#ifdef CONFIG_COMX_DEBUG_RAW
- char *raw;
- int raw_len;
-#endif
- // LINE specific
- struct comx_protocol *protocol;
- void (*LINE_rx)(struct net_device *dev, struct sk_buff *skb);
- int (*LINE_tx)(struct net_device *dev);
- void (*LINE_status)(struct net_device *dev, u_short status);
- int (*LINE_open)(struct net_device *dev);
- int (*LINE_close)(struct net_device *dev);
- int (*LINE_xmit)(struct sk_buff *skb, struct net_device *dev);
- int (*LINE_header)(struct sk_buff *skb, struct net_device *dev,
- u_short type,void *daddr, void *saddr,
- unsigned len);
- int (*LINE_rebuild_header)(struct sk_buff *skb);
- int (*LINE_statistics)(struct net_device *dev, char *page);
- int (*LINE_parameter_check)(struct net_device *dev);
- int (*LINE_ioctl)(struct net_device *dev, struct ifreq *ifr,
- int cmd);
- void (*LINE_mod_use)(int);
- void * LINE_privdata;
-
- // HW specific
-
- struct comx_hardware *hardware;
- void (*HW_board_on)(struct net_device *dev);
- void (*HW_board_off)(struct net_device *dev);
- struct net_device *(*HW_access_board)(struct net_device *dev);
- void (*HW_release_board)(struct net_device *dev, struct net_device *savep);
- int (*HW_txe)(struct net_device *dev);
- int (*HW_open)(struct net_device *dev);
- int (*HW_close)(struct net_device *dev);
- int (*HW_send_packet)(struct net_device *dev,struct sk_buff *skb);
- int (*HW_statistics)(struct net_device *dev, char *page);
-#if 0
- int (*HW_reset)(struct net_device *dev, char *page);
-#endif
- int (*HW_load_board)(struct net_device *dev);
- void (*HW_set_clock)(struct net_device *dev);
- void *HW_privdata;
- };
-
-struct comx_debugflags_struct {
- char *name;
- int value;
- };
-
-#define COMX_ROOT_DIR_NAME "comx"
-
-#define FILENAME_HARDWARE "boardtype"
-#define FILENAME_HARDWARELIST "boardtypes"
-#define FILENAME_PROTOCOL "protocol"
-#define FILENAME_PROTOCOLLIST "protocols"
-#define FILENAME_DEBUG "debug"
-#define FILENAME_CLOCK "clock"
-#define FILENAME_STATUS "status"
-#define FILENAME_IO "io"
-#define FILENAME_IRQ "irq"
-#define FILENAME_KEEPALIVE "keepalive"
-#define FILENAME_LINEUPDELAY "lineup_delay"
-#define FILENAME_CHANNEL "channel"
-#define FILENAME_FIRMWARE "firmware"
-#define FILENAME_MEMADDR "memaddr"
-#define FILENAME_TWIN "twin"
-#define FILENAME_T1 "t1"
-#define FILENAME_T2 "t2"
-#define FILENAME_N2 "n2"
-#define FILENAME_WINDOW "window"
-#define FILENAME_MODE "mode"
-#define FILENAME_DLCI "dlci"
-#define FILENAME_MASTER "master"
-#ifdef CONFIG_COMX_DEBUG_RAW
-#define FILENAME_RAW "raw"
-#endif
-
-#define PROTONAME_NONE "none"
-#define HWNAME_NONE "none"
-#define KEEPALIVE_OFF "off"
-
-#define FRAME_ACCEPTED 0 /* sending and xmitter busy */
-#define FRAME_DROPPED 1
-#define FRAME_ERROR 2 /* xmitter error */
-#define FRAME_QUEUED 3 /* sending but more can come */
-
-#define LINE_UP 1 /* Modem UP */
-#define PROTO_UP 2
-#define PROTO_LOOP 4
-
-#define HW_OPEN 1
-#define LINE_OPEN 2
-#define FW_LOADED 4
-#define IRQ_ALLOCATED 8
-
-#define DEBUG_COMX_RX 2
-#define DEBUG_COMX_TX 4
-#define DEBUG_HW_TX 16
-#define DEBUG_HW_RX 32
-#define DEBUG_HDLC_KEEPALIVE 64
-#define DEBUG_COMX_PPP 128
-#define DEBUG_COMX_LAPB 256
-#define DEBUG_COMX_DLCI 512
-
-#define DEBUG_PAGESIZE 3072
-#define DEFAULT_DEBUG_SIZE 4096
-#define DEFAULT_LINEUP_DELAY 1
-#define FILE_PAGESIZE 3072
-
-#ifndef COMX_PPP_MAJOR
-#define COMX_PPP_MAJOR 88
-#endif
-
-
-#define COMX_CHANNEL(dev) ((struct comx_channel*)dev->priv)
-
-#define TWIN(dev) (COMX_CHANNEL(dev)->twin)
-
-
-#ifndef byte
-typedef u8 byte;
-#endif
-#ifndef word
-typedef u16 word;
-#endif
-
-#ifndef SEEK_SET
-#define SEEK_SET 0
-#endif
-#ifndef SEEK_CUR
-#define SEEK_CUR 1
-#endif
-#ifndef SEEK_END
-#define SEEK_END 2
-#endif
-
-extern struct proc_dir_entry * comx_root_dir;
-
-extern int comx_register_hardware(struct comx_hardware *comx_hw);
-extern int comx_unregister_hardware(char *name);
-extern int comx_register_protocol(struct comx_protocol *comx_line);
-extern int comx_unregister_protocol(char *name);
-
-extern int comx_rx(struct net_device *dev, struct sk_buff *skb);
-extern void comx_status(struct net_device *dev, int status);
-extern void comx_lineup_func(unsigned long d);
-
-extern int comx_debug(struct net_device *dev, char *fmt, ...);
-extern int comx_debug_skb(struct net_device *dev, struct sk_buff *skb, char *msg);
-extern int comx_debug_bytes(struct net_device *dev, unsigned char *bytes, int len,
- char *msg);
-extern int comx_strcasecmp(const char *cs, const char *ct);
-
-extern struct inode_operations comx_normal_inode_ops;
===== drivers/net/wan/comxhw.h 1.1 vs edited =====
--- 1.1/drivers/net/wan/comxhw.h Tue Feb 5 18:40:01 2002
+++ edited/drivers/net/wan/comxhw.h Fri May 7 13:05:54 2004
@@ -1,113 +1 @@
-/*
- * Defines for comxhw.c
- *
- * Original authors: Arpad Bakay <bakay.arpad@synergon.hu>,
- * Peter Bajan <bajan.peter@synergon.hu>,
- * Previous maintainer: Tivadar Szemethy <tiv@itc.hu>
- * Current maintainer: Gergely Madarasz <gorgo@itc.hu>
- *
- * Copyright (C) 1995-1999 ITConsult-Pro Co. <info@itc.hu>
- *
- * 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.
- *
- */
-
-#define LOCOMX_IO_EXTENT 8
-#define COMX_IO_EXTENT 4
-#define HICOMX_IO_EXTENT 16
-
-#define COMX_MAX_TX_SIZE 1600
-#define COMX_MAX_RX_SIZE 2048
-
-#define COMX_JAIL_OFFSET 0xffff
-#define COMX_JAIL_VALUE 0xfe
-#define COMX_MEMORY_SIZE 65536
-#define HICOMX_MEMORY_SIZE 16384
-#define COMX_MEM_MIN 0xa0000
-#define COMX_MEM_MAX 0xf0000
-
-#define COMX_DEFAULT_IO 0x360
-#define COMX_DEFAULT_IRQ 10
-#define COMX_DEFAULT_MEMADDR 0xd0000
-#define HICOMX_DEFAULT_IO 0x320
-#define HICOMX_DEFAULT_IRQ 10
-#define HICOMX_DEFAULT_MEMADDR 0xd0000
-#define LOCOMX_DEFAULT_IO 0x368
-#define LOCOMX_DEFAULT_IRQ 7
-
-#define MAX_CHANNELNO 2
-
-#define COMX_CHANNEL_OFFSET 0x2000
-
-#define COMX_ENABLE_BOARD_IT 0x40
-#define COMX_BOARD_RESET 0x20
-#define COMX_ENABLE_BOARD_MEM 0x10
-#define COMX_DISABLE_BOARD_MEM 0
-#define COMX_DISABLE_ALL 0x00
-
-#define HICOMX_DISABLE_ALL 0x00
-#define HICOMX_ENABLE_BOARD_MEM 0x02
-#define HICOMX_DISABLE_BOARD_MEM 0x0
-#define HICOMX_BOARD_RESET 0x01
-#define HICOMX_PRG_MEM 4
-#define HICOMX_DATA_MEM 0
-#define HICOMX_ID_BYTE 0x55
-
-#define CMX_ID_BYTE 0x31
-#define COMX_CLOCK_CONST 8000
-
-#define LINKUP_READY 3
-
-#define OFF_FW_L1_ID 0x01e /* ID bytes */
-#define OFF_FW_L2_ID 0x1006
-#define FW_L1_ID_1 0xab
-#define FW_L1_ID_2_COMX 0xc0
-#define FW_L1_ID_2_HICOMX 0xc1
-#define FW_L2_ID_1 0xab
-
-#define OFF_A_L2_CMD 0x130 /* command register for L2 */
-#define OFF_A_L2_CMDPAR 0x131 /* command parameter byte */
-#define OFF_A_L1_STATB 0x122 /* stat. block for L1 */
-#define OFF_A_L1_ABOREC 0x122 /* receive ABORT counter */
-#define OFF_A_L1_OVERRUN 0x123 /* receive overrun counter */
-#define OFF_A_L1_CRCREC 0x124 /* CRC error counter */
-#define OFF_A_L1_BUFFOVR 0x125 /* buffer overrun counter */
-#define OFF_A_L1_PBUFOVR 0x126 /* priority buffer overrun counter */
-#define OFF_A_L1_MODSTAT 0x127 /* current state of modem ctrl lines */
-#define OFF_A_L1_STATE 0x127 /* end of stat. block for L1 */
-#define OFF_A_L1_TXPC 0x128 /* Tx counter for the PC */
-#define OFF_A_L1_TXZ80 0x129 /* Tx counter for the Z80 */
-#define OFF_A_L1_RXPC 0x12a /* Rx counter for the PC */
-#define OFF_A_L1_RXZ80 0x12b /* Rx counter for the Z80 */
-#define OFF_A_L1_REPENA 0x12c /* IT rep disable */
-#define OFF_A_L1_CHNR 0x12d /* L1 channel logical number */
-#define OFF_A_L1_CLKINI 0x12e /* Timer Const */
-#define OFF_A_L2_LINKUP 0x132 /* Linkup byte */
-#define OFF_A_L2_DAV 0x134 /* Rx DAV */
-#define OFF_A_L2_RxBUFP 0x136 /* Rx buff relative to membase */
-#define OFF_A_L2_TxEMPTY 0x138 /* Tx Empty */
-#define OFF_A_L2_TxBUFP 0x13a /* Tx Buf */
-#define OFF_A_L2_NBUFFS 0x144 /* Number of buffers to fetch */
-
-#define OFF_A_L2_SABMREC 0x164 /* LAPB no. of SABMs received */
-#define OFF_A_L2_SABMSENT 0x165 /* LAPB no. of SABMs sent */
-#define OFF_A_L2_REJREC 0x166 /* LAPB no. of REJs received */
-#define OFF_A_L2_REJSENT 0x167 /* LAPB no. of REJs sent */
-#define OFF_A_L2_FRMRREC 0x168 /* LAPB no. of FRMRs received */
-#define OFF_A_L2_FRMRSENT 0x169 /* LAPB no. of FRMRs sent */
-#define OFF_A_L2_PROTERR 0x16A /* LAPB no. of protocol errors rec'd */
-#define OFF_A_L2_LONGREC 0x16B /* LAPB no. of long frames */
-#define OFF_A_L2_INVNR 0x16C /* LAPB no. of invalid N(R)s rec'd */
-#define OFF_A_L2_UNDEFFR 0x16D /* LAPB no. of invalid frames */
-
-#define OFF_A_L2_T1 0x174 /* T1 timer */
-#define OFF_A_L2_ADDR 0x176 /* DCE = 1, DTE = 3 */
-
-#define COMX_CMD_INIT 1
-#define COMX_CMD_EXIT 2
-#define COMX_CMD_OPEN 16
-#define COMX_CMD_CLOSE 17
next reply other threads:[~2004-05-07 11:17 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-05-07 11:17 Christoph Hellwig [this message]
2004-05-14 17:32 ` [PATCH] remove comx drivers from tree Jeff Garzik
2004-05-15 21:41 ` Krzysztof Halasa
2004-05-16 21:54 ` Jeff Garzik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040507111725.GA11575@lst.de \
--to=hch@lst.de \
--cc=netdev@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).