From mboxrd@z Thu Jan 1 00:00:00 1970 From: Christoph Hellwig Subject: [PATCH] remove comx drivers from tree Date: Fri, 7 May 2004 13:17:25 +0200 Sender: netdev-bounce@oss.sgi.com Message-ID: <20040507111725.GA11575@lst.de> Mime-Version: 1.0 Content-Type: text/plain; charset=unknown-8bit Content-Transfer-Encoding: quoted-printable Return-path: To: netdev@oss.sgi.com Content-Disposition: inline Errors-to: netdev-bounce@oss.sgi.com List-Id: netdev.vger.kernel.org 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. =20 -# -# 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 for help on configuring - and using COMX interfaces. Further info on these cards can be found - at or . - - 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 . - - 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 - . - - 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 for help on - configuring and using SliceCOM interfaces. Further info on these - cards can be found at or . - - 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!=3Dn && LAPB=3Dm && LAPB || LAPB=3Dy && 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 =3D=3D=3D=3D=3D drivers/net/wan/Makefile 1.18 vs edited =3D=3D=3D=3D=3D --- 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 @@ =20 obj-$(CONFIG_HOSTESS_SV11) +=3D z85230.o syncppp.o hostess_sv11.o obj-$(CONFIG_SEALEVEL_4021) +=3D z85230.o syncppp.o sealevel.o -obj-$(CONFIG_COMX) +=3D comx.o -obj-$(CONFIG_COMX_HW_COMX) +=3D comx-hw-comx.o -obj-$(CONFIG_COMX_HW_LOCOMX) +=3D z85230.o syncppp.o comx-hw-locomx.o -obj-$(CONFIG_COMX_HW_MIXCOM) +=3D comx-hw-mixcom.o -obj-$(CONFIG_COMX_HW_MUNICH) +=3D comx-hw-munich.o -obj-$(CONFIG_COMX_PROTO_PPP) +=3D syncppp.o comx-proto-ppp.o -obj-$(CONFIG_COMX_PROTO_LAPB) +=3D comx-proto-lapb.o -obj-$(CONFIG_COMX_PROTO_FR) +=3D comx-proto-fr.o obj-$(CONFIG_COSA) +=3D syncppp.o cosa.o obj-$(CONFIG_FARSYNC) +=3D syncppp.o farsync.o obj-$(CONFIG_DSCC4) +=3D dscc4.o =3D=3D=3D=3D=3D drivers/net/wan/comx-hw-comx.c 1.13 vs edited =3D=3D=3D=3D= =3D --- 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 , - * Peter Bajan , - * Rewritten by: Tivadar Szemethy - * Currently maintained by: Gergely Madarasz - * - * Copyright (C) 1995-2000 ITConsult-Pro Co. - * - * Contributors: - * Arnaldo Carvalho de Melo - 0.86 - * Daniele Bellucci - 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=20 - * - 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 - *=20 - * 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 - */ =20 -#define VERSION "0.87" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "comx.h" -#include "comxhw.h" - -MODULE_AUTHOR("Gergely Madarasz , Tivadar Szemethy , Arpad Bakay"); -MODULE_DESCRIPTION("Hardware-level driver for the COMX and HICOMX adapte= rs\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 + o= ffset \ - + (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) / 0x= 10000]; -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) |=20 - 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) |=20 - COMX_ENABLE_BOARD_IT), dev->base_addr); -} - -static void HICOMX_board_on(struct net_device *dev) -{ - outb_p( (byte) (((dev->mem_start & 0xf0000) >> 12) |=20 - HICOMX_ENABLE_BOARD_MEM), dev->base_addr); -} - -static void HICOMX_board_off(struct net_device *dev) -{ - outb_p( (byte) (((dev->mem_start & 0xf0000) >> 12) |=20 - HICOMX_DISABLE_BOARD_MEM), dev->base_addr); -} - -static void COMX_set_clock(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct comx_privdata *hw =3D 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 =3D dev->priv; - struct net_device *ret; - int mempos =3D (dev->mem_start - COMX_MEM_MIN) >> 16; - unsigned long flags; - - - save_flags(flags); cli(); -=09 - ret =3D memory_used[mempos]; - - if(ret =3D=3D dev) { - goto out; - } - - memory_used[mempos] =3D dev; - - if (!ch->twin || ret !=3D 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 =3D (dev->mem_start - COMX_MEM_MIN) >> 16; - struct comx_channel *ch =3D dev->priv; - - save_flags(flags); cli(); - - if (memory_used[mempos] =3D=3D savep) { - goto out; - } - - memory_used[mempos] =3D savep; - if (!ch->twin || ch->twin !=3D 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)=20 -{ - struct net_device *savep; - struct comx_channel *ch =3D dev->priv; - int rc =3D 0; - - savep =3D ch->HW_access_board(dev); - if (COMX_readw(dev,OFF_A_L2_LINKUP) =3D=3D LINKUP_READY) { - rc =3D COMX_readw(dev,OFF_A_L2_TxEMPTY); - }=20 - ch->HW_release_board(dev,savep); - if(rc=3D=3D0xffff) { - 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 =3D dev->priv; - struct comx_privdata *hw =3D ch->HW_privdata; - int ret =3D FRAME_DROPPED; - word tmp; - - savep =3D ch->HW_access_board(dev);=09 - - 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=3DFRAME_DROPPED; - goto out; - } - - tmp=3DCOMX_readw(dev, OFF_A_L2_TxEMPTY); - if ((ch->line_status & LINE_UP) && tmp=3D=3D1) { - int lensave =3D skb->len; - int dest =3D COMX_readw(dev, OFF_A_L2_TxBUFP); - word *data =3D (word *)skb->data; - - if(dest=3D=3D0xffff) { - printk(KERN_ERR "%s: OFF_A_L2_TxBUFP is %d\n", dev->name, dest); - ret=3DFRAME_DROPPED; - goto out; - } - =09 - writew((unsigned short)skb->len, dev->mem_start + dest); - dest +=3D 2; - while (skb->len > 1) { - writew(*data++, dev->mem_start + dest); - dest +=3D 2; skb->len -=3D 2; - } - if (skb->len =3D=3D 1) { - writew(*((byte *)data), dev->mem_start + dest); - } - writew(0, dev->mem_start + (int)hw->channel *=20 - COMX_CHANNEL_OFFSET + OFF_A_L2_TxEMPTY); - ch->stats.tx_packets++;=09 - ch->stats.tx_bytes +=3D lensave;=20 - ret =3D 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); - } - } -=09 -out: - ch->HW_release_board(dev, savep); - dev_kfree_skb(skb); - return ret; -} - -static inline int comx_read_buffer(struct net_device *dev)=20 -{ - struct comx_channel *ch =3D dev->priv; - word rbuf_offs; - struct sk_buff *skb; - word len; - int i=3D0; - word *writeptr; - - i =3D 0; - rbuf_offs =3D COMX_readw(dev, OFF_A_L2_RxBUFP); - if(rbuf_offs =3D=3D 0xffff) { - printk(KERN_ERR "%s: OFF_A_L2_RxBUFP is %d\n",dev->name,rbuf_offs); - return 0; - } - len =3D 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 =3D dev_alloc_skb(len + 16)) =3D=3D NULL) { - ch->stats.rx_dropped++; - COMX_WRITE(dev, OFF_A_L2_DAV, 0); - return 0; - } - rbuf_offs +=3D 2; - skb_reserve(skb, 16); - skb_put(skb, len); - skb->dev =3D dev; - writeptr =3D (word *)skb->data; - while (i < len) { - *writeptr++ =3D readw(dev->mem_start + rbuf_offs); - rbuf_offs +=3D 2;=20 - i +=3D 2; - } - COMX_WRITE(dev, OFF_A_L2_DAV, 0); - ch->stats.rx_packets++; - ch->stats.rx_bytes +=3D 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 linesta= t) -{ - struct comx_channel *ch=3Ddev->priv; - char idle=3D1; -=09 -=09 - if (linestat & LINE_UP) { /* Vonal fol */ - if (ch->lineup_delay) { - if (!test_and_set_bit(0, &ch->lineup_pending)) { - ch->lineup_timer.function =3D comx_lineup_func; - ch->lineup_timer.data =3D (unsigned long)dev; - ch->lineup_timer.expires =3D jiffies + - HZ*ch->lineup_delay; - add_timer(&ch->lineup_timer); - idle=3D0; - } - } else { - idle=3D0; - ch->LINE_status(dev, ch->line_status |=3D LINE_UP); - } - } else { /* Vonal le */ - idle=3D0; - if (test_and_clear_bit(0, &ch->lineup_pending)) { - del_timer(&ch->lineup_timer); - } else { - ch->line_status &=3D ~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 =3D dev_id; - struct comx_channel *ch =3D dev->priv; - struct comx_privdata *hw =3D ch->HW_privdata; - struct net_device *interrupted; - unsigned long jiffs; - char idle =3D 0; - int count =3D 0; - word tmp; - - if (dev =3D=3D NULL) { - printk(KERN_ERR "COMX_interrupt: irq %d for unknown device\n", irq); - return IRQ_NONE; - } - - jiffs =3D jiffies; - - interrupted =3D ch->HW_access_board(dev); - - while (!idle && count < 5000) { - char channel =3D 0; - idle =3D 1; - - while (channel < 2) { - char linestat =3D 0; - char buffers_emptied =3D 0; - - if (channel =3D=3D 1) { - if (ch->twin) { - dev =3D ch->twin; - ch =3D dev->priv; - hw =3D ch->HW_privdata; - } else { - break; - } - } else { - COMX_WRITE(dev, OFF_A_L1_REPENA,=20 - COMX_readw(dev, OFF_A_L1_REPENA) & 0xFF00); - } - channel++; - - if ((ch->init_status & (HW_OPEN | LINE_OPEN)) !=3D=20 - (HW_OPEN | LINE_OPEN)) { - continue; - } -=09 - /* Collect stats */ - tmp =3D COMX_readw(dev, OFF_A_L1_ABOREC); - COMX_WRITE(dev, OFF_A_L1_ABOREC, 0); - if(tmp=3D=3D0xffff) { - printk(KERN_ERR "%s: OFF_A_L1_ABOREC is %d\n",dev->name,tmp); - break; - } else { - ch->stats.rx_missed_errors +=3D (tmp >> 8) & 0xff; - ch->stats.rx_over_errors +=3D tmp & 0xff; - } - tmp =3D COMX_readw(dev, OFF_A_L1_CRCREC); - COMX_WRITE(dev, OFF_A_L1_CRCREC, 0); - if(tmp=3D=3D0xffff) { - printk(KERN_ERR "%s: OFF_A_L1_CRCREC is %d\n",dev->name,tmp); - break; - } else { - ch->stats.rx_crc_errors +=3D (tmp >> 8) & 0xff; - ch->stats.rx_missed_errors +=3D tmp & 0xff; - } - =09 - if ((ch->line_status & LINE_UP) && ch->LINE_rx) { - tmp=3DCOMX_readw(dev, OFF_A_L2_DAV);=20 - while (tmp=3D=3D1) { - idle=3D0; - buffers_emptied+=3Dcomx_read_buffer(dev); - tmp=3DCOMX_readw(dev, OFF_A_L2_DAV);=20 - } - if(tmp) { - printk(KERN_ERR "%s: OFF_A_L2_DAV is %d\n", dev->name, tmp); - break; - } - } - - tmp=3DCOMX_readw(dev, OFF_A_L2_TxEMPTY); - if (tmp=3D=3D1 && ch->LINE_tx) { - ch->LINE_tx(dev); - }=20 - if(tmp=3D=3D0xffff) { - 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 &=3D ~LINE_UP; - } else { - linestat |=3D LINE_UP; - } - - if ((linestat & LINE_UP) !=3D (ch->line_status & LINE_UP)) { - ch->stats.tx_carrier_errors++; - idle &=3D comx_line_change(dev,linestat); - } - =09 - hw->histogram[(int)buffers_emptied]++; - } - count++; - } - - if(count=3D=3D5000) { - 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 =3D dev->priv; - struct comx_privdata *hw =3D ch->HW_privdata; - struct proc_dir_entry *procfile =3D ch->procdir->subdir; - unsigned long jiffs; - int twin_open=3D0; - 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=3D1; - } - - 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,=20 - (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 |=3D IRQ_ALLOCATED; - if (!ch->HW_load_board || ch->HW_load_board(dev)) { - ch->init_status &=3D ~IRQ_ALLOCATED; - retval=3D-ENODEV; - goto error; - } - } - - savep =3D 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);=20 - jiffs =3D jiffies; - while (COMX_readw(dev, OFF_A_L2_LINKUP) !=3D 1 && time_before(jiffies, = jiffs + HZ)) { - schedule_timeout(1); - } -=09 - 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=3D-EIO; - goto error; - } - udelay(1000); - - COMX_CMD(dev, COMX_CMD_OPEN); - - jiffs =3D jiffies; - while (COMX_readw(dev, OFF_A_L2_LINKUP) !=3D 3 && time_before(jiffies, = jiffs + HZ)) { - schedule_timeout(1); - } -=09 - 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=3D-EIO; - goto error; - } -=09 - ch->init_status |=3D HW_OPEN; -=09 - /* Ez eleg ciki, de ilyen a rendszer */ - if (COMX_readw(dev, OFF_A_L1_PBUFOVR) >> 8) { - ch->line_status &=3D ~LINE_UP; - } else { - ch->line_status |=3D LINE_UP; - } -=09 - if (ch->LINE_status) { - ch->LINE_status(dev, ch->line_status); - } - - ch->HW_release_board(dev, savep); - - for ( ; procfile ; procfile =3D procfile->next) { - if (strcmp(procfile->name, FILENAME_IRQ) =3D=3D 0=20 - || strcmp(procfile->name, FILENAME_IO) =3D=3D 0 - || strcmp(procfile->name, FILENAME_MEMADDR) =3D=3D 0 - || strcmp(procfile->name, FILENAME_CHANNEL) =3D=3D 0 - || strcmp(procfile->name, FILENAME_FIRMWARE) =3D=3D 0 - || strcmp(procfile->name, FILENAME_CLOCK) =3D=3D 0) { - procfile->mode =3D S_IFREG | 0444; - =09 - } - }=09 -=09 - return 0;=09 - -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 =3D dev->priv; - struct proc_dir_entry *procfile =3D ch->procdir->subdir; - struct comx_privdata *hw =3D ch->HW_privdata; - struct comx_channel *twin_ch; - struct net_device *savep; - - savep =3D 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 &=3D ~IRQ_ALLOCATED; - } - release_region(dev->base_addr, hw->io_extent); - - if (ch->twin && (twin_ch =3D ch->twin->priv) &&=20 - (twin_ch->init_status & HW_OPEN)) { - /* Pass the irq to the twin */ - if (request_irq(dev->irq, COMX_interrupt, 0, ch->twin->name,=20 - (void *)ch->twin) =3D=3D 0) { - twin_ch->init_status |=3D IRQ_ALLOCATED; - } - } - - for ( ; procfile ; procfile =3D procfile->next) { - if (strcmp(procfile->name, FILENAME_IRQ) =3D=3D 0=20 - || strcmp(procfile->name, FILENAME_IO) =3D=3D 0 - || strcmp(procfile->name, FILENAME_MEMADDR) =3D=3D 0 - || strcmp(procfile->name, FILENAME_CHANNEL) =3D=3D 0 - || strcmp(procfile->name, FILENAME_FIRMWARE) =3D=3D 0 - || strcmp(procfile->name, FILENAME_CLOCK) =3D=3D 0) { - procfile->mode =3D S_IFREG | 0644; - } - } -=09 - ch->init_status &=3D ~HW_OPEN; - return 0; -} - -static int COMX_statistics(struct net_device *dev, char *page) -{ - struct comx_channel *ch =3D dev->priv; - struct comx_privdata *hw =3D ch->HW_privdata; - struct net_device *savep; - int len =3D 0; - - savep =3D ch->HW_access_board(dev); - - len +=3D 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 +=3D 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 =3D dev->priv; - struct comx_privdata *hw =3D ch->HW_privdata; - struct comx_firmware *fw =3D hw->firmware; - word board_segment =3D dev->mem_start >> 16; - int mempos =3D (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 =3D ch->twin ? ch->twin->priv : NULL; - struct comx_privdata *twin_hw; - - if (!twin_ch || !(twin_hw =3D twin_ch->HW_privdata)) { - return -EAGAIN; - } - - if (!(fw =3D twin_hw->firmware) || !fw->len) { - return -EAGAIN; - } - } - - id1 =3D fw->data[OFF_FW_L1_ID];=20 - id2 =3D fw->data[OFF_FW_L1_ID + 1]; - - if (id1 !=3D FW_L1_ID_1 || id2 !=3D FW_L1_ID_2_COMX) { - printk(KERN_ERR "%s: incorrect firmware, load aborted\n",=20 - dev->name); - return -EAGAIN; - } - - printk(KERN_INFO "%s: Loading COMX Layer 1 firmware %s\n", dev->name,=20 - (char *)(fw->data + OFF_FW_L1_ID + 2)); - - id1 =3D fw->data[OFF_FW_L2_ID];=20 - id2 =3D fw->data[OFF_FW_L2_ID + 1]; - if (id1 =3D=3D FW_L2_ID_1 && (id2 =3D=3D 0xc0 || id2 =3D=3D 0xc1 || id2= =3D=3D 0xc2)) { - printk(KERN_INFO "with Layer 2 code %s\n",=20 - (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=3Dmemory_used[mempos]; - if(saved) { - ((struct comx_channel *)saved->priv)->HW_board_off(saved); - } - memory_used[mempos]=3Ddev; - - outb_p(board_segment | COMX_ENABLE_BOARD_MEM, dev->base_addr); - - writeb(0, dev->mem_start + COMX_JAIL_OFFSET);=09 - - loopcount=3D0; - while(loopcount++ < 10000 &&=20 - readb(dev->mem_start + COMX_JAIL_OFFSET) !=3D COMX_JAIL_VALUE) { - udelay(100); - }=09 -=09 - if (readb(dev->mem_start + COMX_JAIL_OFFSET) !=3D 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=3D-ENODEV; - goto out; - } - - writeb(0x55, dev->mem_start + 0x18ff); -=09 - loopcount=3D0; - while(loopcount++ < 10000 && readb(dev->mem_start + 0x18ff) !=3D 0) { - udelay(100); - } - - if(readb(dev->mem_start + 0x18ff) !=3D 0) { - printk(KERN_ERR "%s: Can't reset board, reset timeout\n", - dev->name); - retval=3D-ENODEV; - goto out; - } =09 - - len =3D 0; - COMX_address =3D (byte *)dev->mem_start; - while (fw->len > len) { - writeb(fw->data[len++], COMX_address++); - } - - len =3D 0; - COMX_address =3D (byte *)dev->mem_start; - while (len !=3D fw->len && readb(COMX_address++) =3D=3D fw->data[len]) = { - len++; - } - - if (len !=3D fw->len) { - printk(KERN_ERR "%s: error loading firmware: [%d] is 0x%02x " - "instead of 0x%02x\n", dev->name, len,=20 - readb(COMX_address - 1), fw->data[len]); - retval=3D-EAGAIN; - goto out; - } - - writeb(0, dev->mem_start + COMX_JAIL_OFFSET); - - loopcount =3D 0; - while ( loopcount++ < 10000 && COMX_readw(dev, OFF_A_L2_LINKUP) !=3D 1 = ) { - udelay(100); - } - - if (COMX_readw(dev, OFF_A_L2_LINKUP) !=3D 1) { - printk(KERN_ERR "%s: error starting firmware, linkup word is %04x\n", - dev->name, COMX_readw(dev, OFF_A_L2_LINKUP)); - retval=3D-EAGAIN; - goto out; - } - - - ch->init_status |=3D FW_LOADED; - retval=3D0; - -out:=20 - outb_p(board_segment | COMX_DISABLE_ALL, dev->base_addr); - if(saved) { - ((struct comx_channel *)saved->priv)->HW_board_on(saved); - } - memory_used[mempos]=3Dsaved; - restore_flags(flags); - return retval; -} - -static int CMX_load_board(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct comx_privdata *hw =3D ch->HW_privdata; - struct comx_firmware *fw =3D hw->firmware; - word board_segment =3D dev->mem_start >> 16; - int mempos =3D (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 =3D ch->twin ? ch->twin->priv : NULL; - struct comx_privdata *twin_hw; - - if (!twin_ch || !(twin_hw =3D twin_ch->HW_privdata)) { - return -EAGAIN; - } - - if (!(fw =3D twin_hw->firmware) || !fw->len) { - return -EAGAIN; - } - } - - /* Ide kell olyat tenni, hogy ellenorizze az ID-t */ - - if (inb_p(dev->base_addr) !=3D 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,=20 - (char *)(fw->data + OFF_FW_L1_ID + 2)); - - save_flags(flags); cli(); - saved=3Dmemory_used[mempos]; - if(saved) { - ((struct comx_channel *)saved->priv)->HW_board_off(saved); - } - memory_used[mempos]=3Ddev; -=09 - outb_p(board_segment | COMX_ENABLE_BOARD_MEM | COMX_BOARD_RESET,=20 - dev->base_addr); - - len =3D 0; - COMX_address =3D (byte *)dev->mem_start; - while (fw->len > len) { - writeb(fw->data[len++], COMX_address++); - } - - len =3D 0; - COMX_address =3D (byte *)dev->mem_start; - while (len !=3D fw->len && readb(COMX_address++) =3D=3D fw->data[len]) = { - len++; - } - - outb_p(board_segment | COMX_ENABLE_BOARD_MEM, dev->base_addr); - - if (len !=3D fw->len) { - printk(KERN_ERR "%s: error loading firmware: [%d] is 0x%02x " - "instead of 0x%02x\n", dev->name, len,=20 - readb(COMX_address - 1), fw->data[len]); - retval=3D-EAGAIN; - goto out; - } - - loopcount=3D0; - while( loopcount++ < 10000 && COMX_readw(dev, OFF_A_L2_LINKUP) !=3D 1 )= { - udelay(100); - } - - if (COMX_readw(dev, OFF_A_L2_LINKUP) !=3D 1) { - printk(KERN_ERR "%s: error starting firmware, linkup word is %04x\n", - dev->name, COMX_readw(dev, OFF_A_L2_LINKUP)); - retval=3D-EAGAIN; - goto out; - } - - ch->init_status |=3D FW_LOADED; - retval=3D0; - -out:=20 - outb_p(board_segment | COMX_DISABLE_ALL, dev->base_addr); - if(saved) { - ((struct comx_channel *)saved->priv)->HW_board_on(saved); - } - memory_used[mempos]=3Dsaved; - restore_flags(flags); - return retval; -} - -static int HICOMX_load_board(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct comx_privdata *hw =3D ch->HW_privdata; - struct comx_firmware *fw =3D hw->firmware; - word board_segment =3D dev->mem_start >> 12; - int mempos =3D (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 =3D 1; - - if (!fw || !fw->len) { - struct comx_channel *twin_ch =3D ch->twin ? ch->twin->priv : NULL; - struct comx_privdata *twin_hw; - - if (!twin_ch || !(twin_hw =3D twin_ch->HW_privdata)) { - return -EAGAIN; - } - - if (!(fw =3D twin_hw->firmware) || !fw->len) { - return -EAGAIN; - } - } - - while (id !=3D 4) { - if (inb_p(dev->base_addr + id++) !=3D HICOMX_ID_BYTE) { - break; - } - } - - if (id !=3D 4) { - printk(KERN_ERR "%s: can't find HICOMX at 0x%04x, id[%d] =3D %02x\n", - dev->name, (unsigned int)dev->base_addr, id - 1, - inb_p(dev->base_addr + id - 1)); - return -1;=09 - } - - id1 =3D fw->data[OFF_FW_L1_ID];=20 - id2 =3D fw->data[OFF_FW_L1_ID + 1]; - if (id1 !=3D FW_L1_ID_1 || id2 !=3D 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,= =20 - (char *)(fw->data + OFF_FW_L1_ID + 2)); - - id1 =3D fw->data[OFF_FW_L2_ID];=20 - id2 =3D fw->data[OFF_FW_L2_ID + 1]; - if (id1 =3D=3D FW_L2_ID_1 && (id2 =3D=3D 0xc0 || id2 =3D=3D 0xc1 || id2= =3D=3D 0xc2)) { - printk(KERN_INFO "with Layer 2 code %s\n",=20 - (char *)(fw->data + OFF_FW_L2_ID + 2)); - } - - outb_p(board_segment | HICOMX_BOARD_RESET, dev->base_addr); - udelay(10);=09 - - save_flags(flags); cli(); - saved=3Dmemory_used[mempos]; - if(saved) { - ((struct comx_channel *)saved->priv)->HW_board_off(saved); - } - memory_used[mempos]=3Ddev; - - outb_p(board_segment | HICOMX_ENABLE_BOARD_MEM, dev->base_addr); - outb_p(HICOMX_PRG_MEM, dev->base_addr + 1); - - len =3D 0; - HICOMX_address =3D (word *)dev->mem_start; - while (fw->len > len) { - writeb(fw->data[len++], HICOMX_address++); - } - - len =3D 0; - HICOMX_address =3D (word *)dev->mem_start; - while (len !=3D fw->len && (readw(HICOMX_address++) & 0xff) =3D=3D fw->= data[len]) { - len++; - } - - if (len !=3D fw->len) { - printk(KERN_ERR "%s: error loading firmware: [%d] is 0x%02x " - "instead of 0x%02x\n", dev->name, len,=20 - readw(HICOMX_address - 1) & 0xff, fw->data[len]); - retval=3D-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=3D0; - while(loopcount++ < 10000 && COMX_readw(dev, OFF_A_L2_LINKUP) !=3D 1) { - udelay(100); - } - - if ( COMX_readw(dev, OFF_A_L2_LINKUP) !=3D 1 ) { - printk(KERN_ERR "%s: error starting firmware, linkup word is %04x\n", - dev->name, COMX_readw(dev, OFF_A_L2_LINKUP)); - retval=3D-EAGAIN; - goto out; - } - - ch->init_status |=3D FW_LOADED; - retval=3D0; - -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]=3Dsaved; - restore_flags(flags); - return retval; -} - -static struct net_device *comx_twin_check(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct proc_dir_entry *procfile =3D ch->procdir->parent->subdir; - struct comx_privdata *hw =3D ch->HW_privdata; - - struct net_device *twin; - struct comx_channel *ch_twin; - struct comx_privdata *hw_twin; - - - for ( ; procfile ; procfile =3D procfile->next) { -=09 - if(!S_ISDIR(procfile->mode)) { - continue; - } -=09 - twin=3Dprocfile->data; - ch_twin=3Dtwin->priv; - hw_twin=3Dch_twin->HW_privdata; - - - if (twin !=3D dev && dev->irq && dev->base_addr && dev->mem_start && - dev->irq =3D=3D twin->irq && dev->base_addr =3D=3D twin->base_addr = && - dev->mem_start =3D=3D twin->mem_start && - hw->channel =3D=3D (1 - hw_twin->channel) && - ch->hardware =3D=3D ch_twin->hardware) { - return twin; - } - } - return NULL; -} - -static int comxhw_write_proc(struct file *file, const char *buffer,=20 - u_long count, void *data) -{ - struct proc_dir_entry *entry =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D entry->parent->data; - struct comx_channel *ch =3D dev->priv; - struct comx_privdata *hw =3D ch->HW_privdata; - char *page; - - - if(ch->init_status & HW_OPEN) { - return -EAGAIN;=09 - } -=09 - if (strcmp(FILENAME_FIRMWARE, entry->name) !=3D 0) { - if (!(page =3D (char *)__get_free_page(GFP_KERNEL))) { - return -ENOMEM; - } - if(copy_from_user(page, buffer, count =3D (min_t(int, count, PAGE_SIZE= )))) - { - count =3D -EFAULT; - goto out; - } - if (page[count-1] =3D=3D '\n') - page[count-1] =3D '\0'; - else if (count < PAGE_SIZE) - page[count] =3D '\0'; - else if (page[count]) { - count =3D -EINVAL; - goto out; - } - page[count]=3D0; /* Null terminate */ - } else { - byte *tmp; - - if (!hw->firmware) { - if ((hw->firmware =3D kmalloc(sizeof(struct comx_firmware),=20 - GFP_KERNEL)) =3D=3D NULL) { - return -ENOMEM; - } - hw->firmware->len =3D 0; - hw->firmware->data =3D NULL; - } - =09 - if ((tmp =3D kmalloc(count + file->f_pos, GFP_KERNEL)) =3D=3D NULL) { - return -ENOMEM; - } - =09 - /* Ha nem 0 a fpos, akkor meglevo file-t irunk. Gyenge trukk. */ - if (hw->firmware && hw->firmware->len && file->f_pos=20 - && 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 =3D entry->size =3D file->f_pos + count; - hw->firmware->data =3D tmp; - file->f_pos +=3D count; - return count; - } - - if (strcmp(entry->name, FILENAME_CHANNEL) =3D=3D 0) { - hw->channel =3D simple_strtoul(page, NULL, 0); - if (hw->channel >=3D MAX_CHANNELNO) { - printk(KERN_ERR "Invalid channel number\n"); - hw->channel =3D 0; - } - if ((ch->twin =3D comx_twin_check(dev)) !=3D NULL) { - struct comx_channel *twin_ch =3D ch->twin->priv; - twin_ch->twin =3D dev; - } - } else if (strcmp(entry->name, FILENAME_IRQ) =3D=3D 0) { - dev->irq =3D simple_strtoul(page, NULL, 0); - if (dev->irq =3D=3D 2) { - dev->irq =3D 9; - } - if (dev->irq < 3 || dev->irq > 15) { - printk(KERN_ERR "comxhw: Invalid irq number\n"); - dev->irq =3D 0; - } - if ((ch->twin =3D comx_twin_check(dev)) !=3D NULL) { - struct comx_channel *twin_ch =3D ch->twin->priv; - twin_ch->twin =3D dev; - } - } else if (strcmp(entry->name, FILENAME_IO) =3D=3D 0) { - dev->base_addr =3D simple_strtoul(page, NULL, 0); - if ((dev->base_addr & 3) !=3D 0 || dev->base_addr < 0x300=20 - || dev->base_addr > 0x3fc) { - printk(KERN_ERR "Invalid io value\n"); - dev->base_addr =3D 0; - } - if ((ch->twin =3D comx_twin_check(dev)) !=3D NULL) { - struct comx_channel *twin_ch =3D ch->twin->priv; - - twin_ch->twin =3D dev; - } - } else if (strcmp(entry->name, FILENAME_MEMADDR) =3D=3D 0) { - dev->mem_start =3D simple_strtoul(page, NULL, 0); - if (dev->mem_start <=3D 0xf000 && dev->mem_start >=3D 0xa000) { - dev->mem_start *=3D 16; - } - if ((dev->mem_start & 0xfff) !=3D 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 =3D 0; - } - dev->mem_end =3D dev->mem_start + hw->memory_size; - if ((ch->twin =3D comx_twin_check(dev)) !=3D NULL) { - struct comx_channel *twin_ch =3D ch->twin->priv; - - twin_ch->twin =3D dev; - } - } else if (strcmp(entry->name, FILENAME_CLOCK) =3D=3D 0) { - if (strncmp("ext", page, 3) =3D=3D 0) { - hw->clock =3D 0; - } else { - int kbps; - - kbps =3D simple_strtoul(page, NULL, 0); - hw->clock =3D 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 cou= nt, - int *eof, void *data) -{ - struct proc_dir_entry *file =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D file->parent->data; - struct comx_channel *ch =3D dev->priv; - struct comx_privdata *hw =3D ch->HW_privdata; - int len =3D 0; - - - if (strcmp(file->name, FILENAME_IO) =3D=3D 0) { - len =3D sprintf(page, "0x%03x\n", (unsigned int)dev->base_addr); - } else if (strcmp(file->name, FILENAME_IRQ) =3D=3D 0) { - len =3D sprintf(page, "0x%02x\n", dev->irq =3D=3D 9 ? 2 : dev->irq); - } else if (strcmp(file->name, FILENAME_CHANNEL) =3D=3D 0) { - len =3D sprintf(page, "%01d\n", hw->channel); - } else if (strcmp(file->name, FILENAME_MEMADDR) =3D=3D 0) { - len =3D sprintf(page, "0x%05x\n", (unsigned int)dev->mem_start); - } else if (strcmp(file->name, FILENAME_TWIN) =3D=3D 0) { - len =3D sprintf(page, "%s\n", ch->twin ? ch->twin->name : "none"); - } else if (strcmp(file->name, FILENAME_CLOCK) =3D=3D 0) { - if (hw->clock) { - len =3D sprintf(page, "%-8d\n", COMX_CLOCK_CONST/hw->clock); - } else { - len =3D sprintf(page, "external\n"); - } - } else if (strcmp(file->name, FILENAME_FIRMWARE) =3D=3D 0) { - len =3D min_t(int, FILE_PAGESIZE, - min_t(int, count,=20 - hw->firmware ? - (hw->firmware->len - off) : 0)); - if (len < 0) { - len =3D 0; - } - *start =3D hw->firmware ? (hw->firmware->data + off) : NULL; - if (off + len >=3D (hw->firmware ? hw->firmware->len : 0) || len =3D=3D= 0) { - *eof =3D 1; - } - return len; - }=09 - - if (off >=3D len) { - *eof =3D 1; - return 0; - } - - *start =3D page + off; - if (count >=3D len - off) { - *eof =3D 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 =3D dev->priv; - struct comx_privdata *hw; - struct proc_dir_entry *new_file; - - if ((ch->HW_privdata =3D kmalloc(sizeof(struct comx_privdata),=20 - GFP_KERNEL)) =3D=3D NULL) { - return -ENOMEM; - } - memset(hw =3D ch->HW_privdata, 0, sizeof(struct comx_privdata)); - - if (ch->hardware =3D=3D &comx_hw || ch->hardware =3D=3D &cmx_hw) { - hw->memory_size =3D COMX_MEMORY_SIZE; - hw->io_extent =3D COMX_IO_EXTENT; - dev->base_addr =3D COMX_DEFAULT_IO; - dev->irq =3D COMX_DEFAULT_IRQ; - dev->mem_start =3D COMX_DEFAULT_MEMADDR; - dev->mem_end =3D COMX_DEFAULT_MEMADDR + COMX_MEMORY_SIZE; - } else if (ch->hardware =3D=3D &hicomx_hw) { - hw->memory_size =3D HICOMX_MEMORY_SIZE; - hw->io_extent =3D HICOMX_IO_EXTENT; - dev->base_addr =3D HICOMX_DEFAULT_IO; - dev->irq =3D HICOMX_DEFAULT_IRQ; - dev->mem_start =3D HICOMX_DEFAULT_MEMADDR; - dev->mem_end =3D HICOMX_DEFAULT_MEMADDR + HICOMX_MEMORY_SIZE; - } else { - printk(KERN_ERR "SERIOUS INTERNAL ERROR in %s, line %d\n", __FILE__, _= _LINE__); - } - - if ((new_file =3D create_proc_entry(FILENAME_IO, S_IFREG | 0644, ch->pr= ocdir)) - =3D=3D NULL) { - goto cleanup_HW_privdata; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &comxhw_read_proc; - new_file->write_proc =3D &comxhw_write_proc; - new_file->size =3D 6; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_IRQ, S_IFREG | 0644, ch->p= rocdir)) - =3D=3D NULL) { - goto cleanup_filename_io; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &comxhw_read_proc; - new_file->write_proc =3D &comxhw_write_proc; - new_file->size =3D 5; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_CHANNEL, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_filename_irq; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &comxhw_read_proc; - new_file->write_proc =3D &comxhw_write_proc; - new_file->size =3D 2; // Ezt tudjuk - new_file->nlink =3D 1; - - if (ch->hardware =3D=3D &hicomx_hw || ch->hardware =3D=3D &cmx_hw) { - if ((new_file =3D create_proc_entry(FILENAME_CLOCK, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_filename_channel; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &comxhw_read_proc; - new_file->write_proc =3D &comxhw_write_proc; - new_file->size =3D 9; - new_file->nlink =3D 1; - } - - if ((new_file =3D create_proc_entry(FILENAME_MEMADDR, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_filename_clock; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &comxhw_read_proc; - new_file->write_proc =3D &comxhw_write_proc; - new_file->size =3D 8; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_TWIN, S_IFREG | 0444,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_filename_memaddr; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &comxhw_read_proc; - new_file->write_proc =3D NULL; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_FIRMWARE, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_filename_twin; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &comxhw_read_proc; - new_file->write_proc =3D &comxhw_write_proc; - new_file->nlink =3D 1; - - if (ch->hardware =3D=3D &comx_hw) { - ch->HW_board_on =3D COMX_board_on; - ch->HW_board_off =3D COMX_board_off; - ch->HW_load_board =3D COMX_load_board; - } else if (ch->hardware =3D=3D &cmx_hw) { - ch->HW_board_on =3D COMX_board_on; - ch->HW_board_off =3D COMX_board_off; - ch->HW_load_board =3D CMX_load_board; - ch->HW_set_clock =3D COMX_set_clock; - } else if (ch->hardware =3D=3D &hicomx_hw) { - ch->HW_board_on =3D HICOMX_board_on; - ch->HW_board_off =3D HICOMX_board_off; - ch->HW_load_board =3D HICOMX_load_board; - ch->HW_set_clock =3D COMX_set_clock; - } else { - printk(KERN_ERR "SERIOUS INTERNAL ERROR in %s, line %d\n", __FILE__, _= _LINE__); - } - - ch->HW_access_board =3D COMX_access_board; - ch->HW_release_board =3D COMX_release_board; - ch->HW_txe =3D COMX_txe; - ch->HW_open =3D COMX_open; - ch->HW_close =3D COMX_close; - ch->HW_send_packet =3D COMX_send_packet; - ch->HW_statistics =3D COMX_statistics; - - if ((ch->twin =3D comx_twin_check(dev)) !=3D NULL) { - struct comx_channel *twin_ch =3D ch->twin->priv; - - twin_ch->twin =3D 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 =3D=3D &hicomx_hw || ch->hardware =3D=3D &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 =3D dev->priv; - struct comx_privdata *hw =3D 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 =3D ch->twin->priv; - - twin_ch->twin =3D NULL; - } -=09 - 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 =3D=3D &hicomx_hw || ch->hardware =3D=3D &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 =3D { - "comx", - VERSION, - COMX_init, - COMX_exit, - COMX_dump, - NULL -}; - -static struct comx_hardware cmx_hw =3D { - "cmx", - VERSION, - COMX_init, - COMX_exit, - COMX_dump, - NULL -}; - -static struct comx_hardware hicomx_hw =3D { - "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); =3D=3D=3D=3D=3D drivers/net/wan/comx-hw-locomx.c 1.10 vs edited =3D=3D=3D= =3D=3D --- 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 - * - * Based on skeleton code and old LoCOMX driver by Tivadar Szemethy =20 - * and the hostess_sv11 driver - * - * Contributors: - * Arnaldo Carvalho de Melo (0.14) - * - * Copyright (C) 1999 ITConsult-Pro Co. - * - * 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 :)) - *=20 - * 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 - */ =20 -#define VERSION "0.14" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "comx.h" -#include "z85230.h" - -MODULE_AUTHOR("Gergely Madarasz "); -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[] =3D { - 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 =3D netdev_priv(dev); - struct locomx_data *hw =3D 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 =3D c->netdevice; - struct comx_channel *ch =3D netdev_priv(dev); -=09 - 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 *sk= b)=20 -{ - struct comx_channel *ch =3D netdev_priv(dev); - struct locomx_data *hw =3D 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 =3D (struct net_device *)d; - struct comx_channel *ch =3D netdev_priv(dev); - struct locomx_data *hw =3D 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 =3D netdev_priv(dev); - struct locomx_data *hw =3D ch->HW_privdata; - struct proc_dir_entry *procfile =3D 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=3Ddev->base_addr + 5; - hw->board.chanA.dataio=3Ddev->base_addr + 7; -=09 - hw->board.irq=3Ddev->irq; - hw->board.chanA.netdevice=3Ddev; - hw->board.chanA.dev=3D&hw->board; - hw->board.name=3Ddev->name; - hw->board.chanA.txdma=3DTX_DMA; - hw->board.chanA.rxdma=3DRX_DMA; - hw->board.chanA.irqs=3D&z8530_nop; - hw->board.chanB.irqs=3D&z8530_nop; - - if(request_irq(dev->irq, z8530_interrupt, SA_INTERRUPT,=20 - dev->name, &hw->board)) { - printk(KERN_ERR "%s: unable to obtain irq %d\n", dev->name,=20 - dev->irq); - ret=3D-EAGAIN; - goto irq_fail; - } - if(request_dma(TX_DMA,"LoCOMX (TX)")) { - printk(KERN_ERR "%s: unable to obtain TX DMA (DMA channel %d)\n",=20 - dev->name, TX_DMA); - ret=3D-EAGAIN; - goto dma1_fail; - } - - if(request_dma(RX_DMA,"LoCOMX (RX)")) { - printk(KERN_ERR "%s: unable to obtain RX DMA (DMA channel %d)\n",=20 - dev->name, RX_DMA); - ret=3D-EAGAIN; - goto dma2_fail; - } -=09 - save_flags(flags);=20 - cli(); - - if(z8530_init(&hw->board)!=3D0) - { - printk(KERN_ERR "%s: Z8530 device not found.\n",dev->name); - ret=3D-ENODEV; - goto z8530_fail; - } - - hw->board.chanA.dcdcheck=3DCTS; - - 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=3Dz8530_sync_dma_open(dev, &hw->board.chanA))!=3D0) { - goto z8530_fail; - } - - restore_flags(flags); - - - hw->board.active=3D1; - hw->board.chanA.rx_function=3Dlocomx_rx; - - ch->init_status |=3D HW_OPEN; - if (hw->board.chanA.status & DCD) { - ch->line_status |=3D LINE_UP; - } else { - ch->line_status &=3D ~LINE_UP; - } - - comx_status(dev, ch->line_status); - - init_timer(&hw->status_timer); - hw->status_timer.function=3Dlocomx_status_timerfun; - hw->status_timer.data=3D(unsigned long)dev; - hw->status_timer.expires=3Djiffies + ch->lineup_delay * HZ; - add_timer(&hw->status_timer); - - for (; procfile ; procfile =3D procfile->next) { - if (strcmp(procfile->name, FILENAME_IO) =3D=3D 0 || - strcmp(procfile->name, FILENAME_IRQ) =3D=3D 0) { - procfile->mode =3D 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 =3D netdev_priv(dev); - struct locomx_data *hw =3D ch->HW_privdata; - struct proc_dir_entry *procfile =3D ch->procdir->subdir; - - hw->board.chanA.rx_function=3Dz8530_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 =3D procfile->next) { - if (strcmp(procfile->name, FILENAME_IO) =3D=3D 0 || - strcmp(procfile->name, FILENAME_IRQ) =3D=3D 0) { - procfile->mode =3D S_IFREG | 0644; - } - } - - ch->init_status &=3D ~HW_OPEN; - return 0; -} - -static int LOCOMX_statistics(struct net_device *dev,char *page) -{ - int len =3D 0; - - len +=3D 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 cou= nt, - int *eof, void *data) -{ - struct proc_dir_entry *file =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D file->parent->data; - int len =3D 0; - - if (strcmp(file->name, FILENAME_IO) =3D=3D 0) { - len =3D sprintf(page, "0x%x\n", (unsigned int)dev->base_addr); - } else if (strcmp(file->name, FILENAME_IRQ) =3D=3D 0) { - len =3D sprintf(page, "%d\n", (unsigned int)dev->irq); - } else { - printk(KERN_ERR "hw_read_proc: internal error, filename %s\n",=20 - file->name); - return -EBADF; - } - - if (off >=3D len) { - *eof =3D 1; - return 0; - } - - *start =3D page + off; - if (count >=3D len - off) { - *eof =3D 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 =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D (struct net_device *)entry->parent->data; - int val; - char *page; - - if (!(page =3D (char *)__get_free_page(GFP_KERNEL))) { - return -ENOMEM; - } - - if (copy_from_user(page, buffer, count =3D min_t(unsigned long, count, = PAGE_SIZE))) { - free_page((unsigned long)page); - return -EBADF; - } - if (*(page + count - 1) =3D=3D '\n') { - *(page + count - 1) =3D 0; - } - - if (strcmp(entry->name, FILENAME_IO) =3D=3D 0) { - val =3D simple_strtoul(page, NULL, 0); - if (val !=3D 0x360 && val !=3D 0x368 && val !=3D 0x370 &&=20 - val !=3D 0x378) { - printk(KERN_ERR "LoCOMX: incorrect io address!\n");=09 - } else { - dev->base_addr =3D val; - } - } else if (strcmp(entry->name, FILENAME_IRQ) =3D=3D 0) { - val =3D simple_strtoul(page, NULL, 0); - if (val !=3D 3 && val !=3D 4 && val !=3D 5 && val !=3D 6 && val !=3D 7= ) { - printk(KERN_ERR "LoCOMX: incorrect irq value!\n"); - } else { - dev->irq =3D val; - }=09 - } else { - printk(KERN_ERR "locomx_write_proc: internal error, filename %s\n",=20 - entry->name); - free_page((unsigned long)page); - return -EBADF; - } - - free_page((unsigned long)page); - return count; -} - - - -static int LOCOMX_init(struct net_device *dev)=20 -{ - struct comx_channel *ch =3D netdev_priv(dev); - struct locomx_data *hw; - struct proc_dir_entry *new_file; - - /* Alloc data for private structure */ - if ((ch->HW_privdata =3D kmalloc(sizeof(struct locomx_data),=20 - GFP_KERNEL)) =3D=3D NULL) { - return -ENOMEM; - } - - memset(hw =3D ch->HW_privdata, 0, sizeof(struct locomx_data)); - hw->io_extent =3D LOCOMX_IO_EXTENT; - - /* Register /proc files */ - if ((new_file =3D create_proc_entry(FILENAME_IO, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_HW_privdata; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &locomx_read_proc; - new_file->write_proc =3D &locomx_write_proc; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_IRQ, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_filename_io; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &locomx_read_proc; - new_file->write_proc =3D &locomx_write_proc; - new_file->nlink =3D 1; - -/* No clock yet */ -/* - if ((new_file =3D create_proc_entry(FILENAME_CLOCK, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - return -EIO; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &locomx_read_proc; - new_file->write_proc =3D &locomx_write_proc; - new_file->nlink =3D 1; -*/ - - ch->HW_access_board =3D NULL; - ch->HW_release_board =3D NULL; - ch->HW_txe =3D LOCOMX_txe; - ch->HW_open =3D LOCOMX_open; - ch->HW_close =3D LOCOMX_close; - ch->HW_send_packet =3D LOCOMX_send_packet; - ch->HW_statistics =3D LOCOMX_statistics; - ch->HW_set_clock =3D NULL; - - ch->current_stats =3D &hw->board.chanA.stats; - memcpy(ch->current_stats, &ch->stats, sizeof(struct net_device_stats)); - - dev->base_addr =3D LOCOMX_DEFAULT_IO; - dev->irq =3D LOCOMX_DEFAULT_IRQ; -=09 -=09 - /* 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 =3D netdev_priv(dev); - - ch->HW_access_board =3D NULL; - ch->HW_release_board =3D NULL; - ch->HW_txe =3D NULL; - ch->HW_open =3D NULL; - ch->HW_close =3D NULL; - ch->HW_send_packet =3D NULL; - ch->HW_statistics =3D NULL; - ch->HW_set_clock =3D NULL; - memcpy(&ch->stats, ch->current_stats, sizeof(struct net_device_stats)); - ch->current_stats =3D &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 =3D { - "locomx", - VERSION, - LOCOMX_init,=20 - LOCOMX_exit, - LOCOMX_dump, - NULL -}; -=09 -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); =3D=3D=3D=3D=3D drivers/net/wan/comx-hw-mixcom.c 1.12 vs edited =3D=3D=3D= =3D=3D --- 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 @@ -/*=20 - * Hardware driver for the MixCom synchronous serial board=20 - * - * Author: Gergely Madarasz - * - * based on skeleton driver code and a preliminary hscx driver by=20 - * Tivadar Szemethy - * - * Copyright (C) 1998-1999 ITConsult-Pro Co. - * - * Contributors: - * Arnaldo Carvalho de Melo (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 =3D 0x13) - * - printk fixes - *=20 - * Version 0.62 (99/07/15): - * - fixes according to the new hw docs=20 - * - 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 - */ =20 -#define VERSION "0.65" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "comx.h" -#include "mixcom.h" -#include "hscx.h" - -MODULE_AUTHOR("Gergely Madarasz "); -MODULE_DESCRIPTION("Hardware-level driver for the serial port of the Mix= Com 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[]=3D{0xFF, 0xFF, 0xFF, 0x0, 0xFF, 0x= 2, 0x4, 0x6, 0xFF, 0xFF, 0x8, 0xA, 0xC, 0xFF, 0xE, 0xFF}; - -static unsigned char* hscx_versions[]=3D{"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 cha= r val)=20 -{ - 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 =3D jiffies; - unsigned char cec; - unsigned delay =3D 0; - - while ((cec =3D (rd_hscx(dev, HSCX_STAR) & HSCX_CEC) !=3D 0) &&=20 - 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 =3D dev->priv; - struct mixcom_privdata *hw =3D ch->HW_privdata; - register word to_send =3D 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 <=3D 32) { - hscx_cmd(dev, HSCX_XTF | HSCX_XME); - kfree_skb(hw->sending); - hw->sending =3D NULL;=20 - hw->tx_ptr =3D 0; - } else { - hscx_cmd(dev, HSCX_XTF); - hw->tx_ptr +=3D 32; - } -} - -static inline void hscx_empty_fifo(struct net_device *dev, int cnt) -{ - struct comx_channel *ch =3D dev->priv; - struct mixcom_privdata *hw =3D ch->HW_privdata; - - if (hw->recving =3D=3D NULL) { - if (!(hw->recving =3D 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 =3D 0; - } - if (cnt > 32 || !cnt || hw->recving =3D=3D NULL) { - printk(KERN_ERR "hscx_empty_fifo: cnt is %d, hw->recving %p\n", - cnt, (void *)hw->recving); - return; - } - =20 - insb(dev->base_addr + HSCX_FIFO, &(hw->recving->data[hw->rx_ptr]),cnt); - hw->rx_ptr +=3D cnt; - hscx_cmd(dev, HSCX_RMC); -} - - -static int MIXCOM_txe(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct mixcom_privdata *hw =3D ch->HW_privdata; - - return !test_bit(0, &hw->txbusy); -} - -static int mixcom_probe(struct net_device *dev) -{ - unsigned long flags; - int id, vstr, ret=3D0; - - save_flags(flags); cli(); - - id=3Dinb_p(MIXCOM_BOARD_BASE(dev) + MIXCOM_ID_OFFSET) & 0x7f; - - if (id !=3D MIXCOM_ID ) { - ret=3D-ENODEV; - printk(KERN_WARNING "%s: no MixCOM board found at 0x%04lx\n",dev->name= , dev->base_addr); - goto out; - } - - vstr=3Dinb_p(dev->base_addr + HSCX_VSTR) & 0x0f; - if(vstr>=3Dsizeof(hscx_versions)/sizeof(char*) ||=20 - hscx_versions[vstr]=3D=3DNULL) { - printk(KERN_WARNING "%s: board found but no HSCX chip detected at 0x%4= lx (vstr =3D 0x%1x)\n",dev->name,dev->base_addr,vstr); - ret =3D -ENODEV; - } else { - printk(KERN_INFO "%s: HSCX chip version %s\n",dev->name,hscx_versions[= vstr]); - ret =3D 0; - } - -out: - - restore_flags(flags); - return ret; -} - -#if 0 -static void MIXCOM_set_clock(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct mixcom_privdata *hw =3D 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,=20 - 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 =3D dev->priv; - - wr_hscx(dev, HSCX_CCR1, HSCX_PU | HSCX_ODS | HSCX_ITF); // power up, pu= sh-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 *sk= b)=20 -{ - struct comx_channel *ch =3D dev->priv; - struct mixcom_privdata *hw =3D 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++;=09 - 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 =3D skb; - hw->tx_ptr =3D 0; - hw->txbusy =3D 1; -// atomic_inc(&skb->users); // save it - hscx_fill_fifo(dev); - restore_flags(flags); - - ch->stats.tx_packets++; - ch->stats.tx_bytes +=3D skb->len;=20 - - 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)=20 -{ - struct comx_channel *ch=3Ddev->priv; - struct mixcom_privdata *hw=3Dch->HW_privdata; - register byte rsta; - register word length; - - rsta =3D rd_hscx(dev, HSCX_RSTA) & (HSCX_VFR | HSCX_RDO |=20 - HSCX_CRC | HSCX_RAB); - length =3D ((rd_hscx(dev, HSCX_RBCH) & 0x0f) << 8) |=20 - rd_hscx(dev, HSCX_RBCL); - - if ( length > hw->rx_ptr ) { - hscx_empty_fifo(dev, length - hw->rx_ptr); - } -=09 - 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++;=20 - ch->stats.rx_bytes +=3D length; - - if (rsta =3D=3D (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 =3D dev; - if (ch->LINE_rx) { - ch->LINE_rx(dev, hw->recving); - } - } - else if(hw->recving) { - kfree_skb(hw->recving); - } - hw->recving =3D NULL;=20 - hw->rx_ptr =3D 0; -} - - -static inline void mixcom_extended_interrupt(struct net_device *dev)=20 -{ - struct comx_channel *ch=3Ddev->priv; - struct mixcom_privdata *hw=3Dch->HW_privdata; - register byte exir; - - exir =3D 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 =3D NULL; hw->rx_ptr =3D 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 =3D NULL;=20 - hw->tx_ptr =3D 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) { =20 - ch->stats.tx_carrier_errors++; - if ((rd_hscx(dev, HSCX_STAR) & HSCX_CTS) =3D=3D 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 &=3D ~LINE_UP; - if (ch->LINE_status) { - ch->LINE_status(dev,ch->line_status); - } - } - } - if (!(ch->line_status & LINE_UP) && (rd_hscx(dev, HSCX_STAR) &=20 - HSCX_CTS)) { // Vonal fol - if (!test_and_set_bit(0,&ch->lineup_pending)) { - ch->lineup_timer.function =3D comx_lineup_func; - ch->lineup_timer.data =3D (unsigned long)dev; - ch->lineup_timer.expires =3D jiffies + HZ *=20 - 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=3DNULL; - hw->tx_ptr =3D 0; - } - } - } -} - - -static irqreturn_t MIXCOM_interrupt(int irq, void *dev_id, struct pt_reg= s *regs) -{ - unsigned long flags; - struct net_device *dev =3D (struct net_device *)dev_id; - struct comx_channel *ch, *twin_ch; - struct mixcom_privdata *hw, *twin_hw; - register unsigned char ista; - - if (dev=3D=3DNULL) { - printk(KERN_ERR "comx_interrupt: irq %d for unknown device\n",irq); - return IRQ_NONE; - } - - ch =3D dev->priv;=20 - hw =3D ch->HW_privdata; - - save_flags(flags); cli();=20 - - while((ista =3D (rd_hscx(dev, HSCX_ISTA) & (HSCX_RME | HSCX_RPF |=20 - HSCX_XPR | HSCX_EXB | HSCX_EXA | HSCX_ICA)))) { - register byte ista2 =3D 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); - } - } - =09 - if (ista & HSCX_EXB) { - mixcom_extended_interrupt(dev); - } - =09 - if ((ista & HSCX_EXA) && ch->twin) { - mixcom_extended_interrupt(ch->twin); - } -=09 - if ((ista & HSCX_ICA) && ch->twin && - (ista2 =3D 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=3Dch->twin->priv; - twin_hw=3Dtwin_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 =3D dev->priv; - struct mixcom_privdata *hw =3D ch->HW_privdata; - struct proc_dir_entry *procfile =3D ch->procdir->subdir; - unsigned long flags;=20 - int ret =3D -ENODEV; - - if (!dev->base_addr || !dev->irq) - goto err_ret; - - - if(hw->channel=3D=3D1) { - if(!TWIN(dev) || !(COMX_CHANNEL(TWIN(dev))->init_status &=20 - IRQ_ALLOCATED)) { - printk(KERN_ERR "%s: channel 0 not yet initialized\n",dev->name); - ret =3D -EAGAIN; - goto err_ret; - } - } - - - /* Is our hw present at all ? Not checking for channel 0 if it is alrea= dy=20 - open */ - if(hw->channel!=3D0 || !(ch->init_status & IRQ_ALLOCATED)) { - if (!request_region(dev->base_addr, MIXCOM_IO_EXTENT, dev->name)) { - ret =3D -EAGAIN; - goto err_ret; - } - if (mixcom_probe(dev)) { - ret =3D -ENODEV; - goto err_release_region; - } - } - - if(hw->channel=3D=3D0 && !(ch->init_status & IRQ_ALLOCATED)) { - if (request_irq(dev->irq, MIXCOM_interrupt, 0,=20 - dev->name, (void *)dev)) { - printk(KERN_ERR "MIXCOM: unable to obtain irq %d\n", dev->irq); - ret =3D -EAGAIN; - goto err_release_region; - } - } - - save_flags(flags); cli(); - - if(hw->channel=3D=3D0 && !(ch->init_status & IRQ_ALLOCATED)) { - ch->init_status|=3DIRQ_ALLOCATED; - mixcom_board_on(dev); - } - - mixcom_on(dev); - - - hw->status=3Dinb(MIXCOM_BOARD_BASE(dev) + MIXCOM_STATUS_OFFSET); - if(hw->status !=3D 0xff) { - printk(KERN_DEBUG "%s: board has status register, good\n", dev->name); - hw->card_has_status=3D1; - } - - hw->txbusy =3D 0; - ch->init_status |=3D HW_OPEN; -=09 - if (rd_hscx(dev, HSCX_STAR) & HSCX_CTS) { - ch->line_status |=3D LINE_UP; - } else { - ch->line_status &=3D ~LINE_UP; - } - - restore_flags(flags); - - ch->LINE_status(dev, ch->line_status); - - for (; procfile ; procfile =3D procfile->next) { - if (strcmp(procfile->name, FILENAME_IO) =3D=3D 0 || - strcmp(procfile->name, FILENAME_CHANNEL) =3D=3D 0 || - strcmp(procfile->name, FILENAME_CLOCK) =3D=3D 0 || - strcmp(procfile->name, FILENAME_IRQ) =3D=3D 0) { - procfile->mode =3D S_IFREG | 0444; - } - } - - return 0; -=09 -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 =3D dev->priv; - struct mixcom_privdata *hw =3D ch->HW_privdata; - struct proc_dir_entry *procfile =3D 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 everythi= ng */ - if(hw->channel=3D=3D0 && (!(TWIN(dev)) ||=20 - !(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 &=3D ~IRQ_ALLOCATED; - } - - /* This is channel 1, channel 0 has already been shutdown, we can relea= se - this one too */ - if(hw->channel=3D=3D1 && !(COMX_CHANNEL(TWIN(dev))->init_status & HW_OP= EN)) { - 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 &=3D ~IRQ_ALLOCATED; - } - } - - /* the ioports for channel 1 can be safely released */ - if(hw->channel=3D=3D1) { - 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 =3D procfile->next) { - if (strcmp(procfile->name, FILENAME_IO) =3D=3D 0 || - strcmp(procfile->name, FILENAME_CHANNEL) =3D=3D 0 || - strcmp(procfile->name, FILENAME_CLOCK) =3D=3D 0 || - strcmp(procfile->name, FILENAME_IRQ) =3D=3D 0) { - procfile->mode =3D S_IFREG | 0644; - } - } - } - - /* channel 0 was only waiting for us to close channel 1=20 - close it completely */ - =20 - if(hw->channel=3D=3D1 && !(COMX_CHANNEL(TWIN(dev))->init_status & HW_OP= EN)) { - for (procfile=3DCOMX_CHANNEL(TWIN(dev))->procdir->subdir;=20 - procfile ; procfile =3D procfile->next) { - if (strcmp(procfile->name, FILENAME_IO) =3D=3D 0 || - strcmp(procfile->name, FILENAME_CHANNEL) =3D=3D 0 || - strcmp(procfile->name, FILENAME_CLOCK) =3D=3D 0 || - strcmp(procfile->name, FILENAME_IRQ) =3D=3D 0) { - procfile->mode =3D S_IFREG | 0644; - } - } - } -=09 - ch->init_status &=3D ~HW_OPEN; - return 0; -} - -static int MIXCOM_statistics(struct net_device *dev,char *page) -{ - struct comx_channel *ch =3D dev->priv; - // struct mixcom_privdata *hw =3D ch->HW_privdata; - int len =3D 0; - - if(ch->init_status && IRQ_ALLOCATED) { - len +=3D 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 cou= nt, - int *eof, void *data) -{ - struct proc_dir_entry *file =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D file->parent->data; - struct comx_channel *ch =3D dev->priv; - struct mixcom_privdata *hw =3D ch->HW_privdata; - int len =3D 0; - - if (strcmp(file->name, FILENAME_IO) =3D=3D 0) { - len =3D sprintf(page, "0x%x\n",=20 - (unsigned int)MIXCOM_BOARD_BASE(dev)); - } else if (strcmp(file->name, FILENAME_IRQ) =3D=3D 0) { - len =3D sprintf(page, "%d\n", (unsigned int)dev->irq); - } else if (strcmp(file->name, FILENAME_CLOCK) =3D=3D 0) { - if (hw->clock) len =3D sprintf(page, "%d\n", hw->clock); - else len =3D sprintf(page, "external\n"); - } else if (strcmp(file->name, FILENAME_CHANNEL) =3D=3D 0) { - len =3D sprintf(page, "%01d\n", hw->channel); - } else if (strcmp(file->name, FILENAME_TWIN) =3D=3D 0) { - if (ch->twin) { - len =3D sprintf(page, "%s\n",ch->twin->name); - } else { - len =3D sprintf(page, "none\n"); - } - } else { - printk(KERN_ERR "mixcom_read_proc: internal error, filename %s\n", fil= e->name); - return -EBADF; - } - - if (off >=3D len) { - *eof =3D 1; - return 0; - } - *start =3D page + off; - if (count >=3D len - off) *eof =3D 1; - return min_t(int, count, len - off); -} - - -static struct net_device *mixcom_twin_check(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct proc_dir_entry *procfile =3D ch->procdir->parent->subdir; - struct mixcom_privdata *hw =3D ch->HW_privdata; - - struct net_device *twin; - struct comx_channel *ch_twin; - struct mixcom_privdata *hw_twin; - - - for ( ; procfile ; procfile =3D procfile->next) { - if(!S_ISDIR(procfile->mode)) continue; - =20 - twin =3D procfile->data; - ch_twin =3D twin->priv; - hw_twin =3D ch_twin->HW_privdata; - - - if (twin !=3D dev && dev->irq && dev->base_addr &&=20 - dev->irq =3D=3D twin->irq &&=20 - ch->hardware =3D=3D ch_twin->hardware && - dev->base_addr =3D=3D twin->base_addr +=20 - (1-2*hw->channel)*MIXCOM_CHANNEL_OFFSET && - hw->channel =3D=3D (1 - hw_twin->channel)) { - if (!TWIN(twin) || TWIN(twin)=3D=3Ddev) { - return twin; - } - } - } - return NULL; -} - - -static void setup_twin(struct net_device* dev)=20 -{ - - if(TWIN(dev) && TWIN(TWIN(dev))) { - TWIN(TWIN(dev))=3DNULL; - } - if ((TWIN(dev) =3D mixcom_twin_check(dev)) !=3D NULL) { - if (TWIN(TWIN(dev)) && TWIN(TWIN(dev)) !=3D dev) { - TWIN(dev)=3DNULL; - } else { - TWIN(TWIN(dev))=3Ddev; - } - }=09 -} - -static int mixcom_write_proc(struct file *file, const char *buffer, - u_long count, void *data) -{ - struct proc_dir_entry *entry =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D (struct net_device *)entry->parent->data; - struct comx_channel *ch =3D dev->priv; - struct mixcom_privdata *hw =3D ch->HW_privdata; - char *page; - int value; - - if (!(page =3D (char *)__get_free_page(GFP_KERNEL))) { - return -ENOMEM; - } - - if (copy_from_user(page, buffer, count =3D min_t(unsigned long, count, = PAGE_SIZE))) { - free_page((unsigned long)page); - return -EFAULT; - } - if (*(page + count - 1) =3D=3D '\n') { - *(page + count - 1) =3D 0; - } - - if (strcmp(entry->name, FILENAME_IO) =3D=3D 0) { - value =3D simple_strtoul(page, NULL, 0); - if (value !=3D 0x180 && value !=3D 0x280 && value !=3D 0x380) { - printk(KERN_ERR "MIXCOM: incorrect io address!\n"); - } else { - dev->base_addr =3D MIXCOM_DEV_BASE(value,hw->channel); - } - } else if (strcmp(entry->name, FILENAME_IRQ) =3D=3D 0) { - value =3D simple_strtoul(page, NULL, 0);=20 - if (value < 0 || value > 15 || mixcom_set_irq[value]=3D=3D0xFF) { - printk(KERN_ERR "MIXCOM: incorrect irq value!\n"); - } else { - dev->irq =3D value;=09 - } - } else if (strcmp(entry->name, FILENAME_CLOCK) =3D=3D 0) { - if (strncmp("ext", page, 3) =3D=3D 0) { - hw->clock =3D 0; - } else { - int kbps; - - kbps =3D simple_strtoul(page, NULL, 0); - if (!kbps) { - hw->clock =3D 0; - } else { - hw->clock =3D kbps; - } - if (hw->clock < 32 || hw->clock > 2000) { - hw->clock =3D 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) =3D=3D 0) { - value =3D simple_strtoul(page, NULL, 0); - if (value > 2) { - printk(KERN_ERR "Invalid channel number\n"); - } else { - dev->base_addr+=3D(hw->channel - value) * MIXCOM_CHANNEL_OFFSE= T; - hw->channel =3D value; - } =20 - } else { - printk(KERN_ERR "hw_read_proc: internal error, filename %s\n",=20 - 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 =3D dev->priv; - struct mixcom_privdata *hw; - struct proc_dir_entry *new_file; - - if ((ch->HW_privdata =3D kmalloc(sizeof(struct mixcom_privdata),=20 - GFP_KERNEL)) =3D=3D NULL) { - return -ENOMEM; - } - - memset(hw =3D ch->HW_privdata, 0, sizeof(struct mixcom_privdata)); - - if ((new_file =3D create_proc_entry(FILENAME_IO, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_HW_privdata; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &mixcom_read_proc; - new_file->write_proc =3D &mixcom_write_proc; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_IRQ, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_filename_io; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &mixcom_read_proc; - new_file->write_proc =3D &mixcom_write_proc; - new_file->nlink =3D 1; - -#if 0 - if ((new_file =3D create_proc_entry(FILENAME_CLOCK, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - return -EIO; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &mixcom_read_proc; - new_file->write_proc =3D &mixcom_write_proc; - new_file->nlink =3D 1; -#endif - - if ((new_file =3D create_proc_entry(FILENAME_CHANNEL, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_filename_irq; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &mixcom_read_proc; - new_file->write_proc =3D &mixcom_write_proc; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_TWIN, S_IFREG | 0444,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_filename_channel; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &mixcom_read_proc; - new_file->write_proc =3D &mixcom_write_proc; - new_file->nlink =3D 1; - - setup_twin(dev); - - /* Fill in ch_struct hw specific pointers */ - ch->HW_access_board =3D NULL; - ch->HW_release_board =3D NULL; - ch->HW_txe =3D MIXCOM_txe; - ch->HW_open =3D MIXCOM_open; - ch->HW_close =3D MIXCOM_close; - ch->HW_send_packet =3D MIXCOM_send_packet; - ch->HW_statistics =3D MIXCOM_statistics; - ch->HW_set_clock =3D NULL; - - dev->base_addr =3D MIXCOM_DEV_BASE(MIXCOM_DEFAULT_IO,0); - dev->irq =3D 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 =3D dev->priv; - struct mixcom_privdata *hw =3D ch->HW_privdata; - - if(hw->channel=3D=3D0 && TWIN(dev)) { - return -EBUSY; - } - - if(hw->channel=3D=3D1 && TWIN(dev)) { - TWIN(TWIN(dev))=3DNULL; - } - - 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 =3D { - "mixcom", - VERSION, - MIXCOM_init,=20 - MIXCOM_exit, - MIXCOM_dump, - NULL -}; -=09 -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); =3D=3D=3D=3D=3D drivers/net/wan/comx-hw-munich.c 1.17 vs edited =3D=3D=3D= =3D=3D --- 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 - * - * Original author: Bartok Istvan - * Based on skeleton by Tivadar Szemethy - * - * 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 - */ =20 -#define VERSION "0.51" -#define VERSIONSTR "SliceCOM v" VERSION ", 2002/01/07\n" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#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 , Gergely Madarasz , Szilard Pasztor "); -MODULE_DESCRIPTION("Hardware-level driver for the SliceCOM and PciCOM (W= elCOM) 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 /pro= c, - "error" is an indication that something went wrong, we have an undefi= ned value */ - -struct slicecom_stringtable slicecom_framings[] =3D -{ - {"crc4", SLICECOM_FRAMING_CRC4}, - {"no-crc4", SLICECOM_FRAMING_NO_CRC4}, - {"default", SLICECOM_FRAMING_DEFAULT}, - {"error", 0} -}; - -struct slicecom_stringtable slicecom_linecodes[] =3D -{ - {"hdb3", SLICECOM_LINECODE_HDB3}, - {"ami", SLICECOM_LINECODE_AMI}, - {"default", SLICECOM_LINECODE_DEFAULT}, - {"error", 0} -}; - -struct slicecom_stringtable slicecom_clock_sources[] =3D -{ - {"line", SLICECOM_CLOCK_SOURCE_LINE}, - {"internal", SLICECOM_CLOCK_SOURCE_INTERNAL}, - {"default", SLICECOM_CLOCK_SOURCE_DEFAULT}, - {"error", 0} -}; - -struct slicecom_stringtable slicecom_loopbacks[] =3D -{ - {"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 >=3D 4 = */ -#define TX_DESC_MAX 4 /* Tx ring size, must be >=3D 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 understandi= ng what is happening - */ - -#define UDELAY 20 /* We wait UDELAY usecs with disabled interrupts befo= re 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 =3D 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 =3D *CCBA; CCB =3D *CSA */ - /* MUNICH does it like: CCB =3D *( *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 Interru= pt Queue size in munich_intq_t's */ -#define MUNICH_INTQSIZE ( 4*MUNICH_INTQMAX ) /* Rx/Tx/Periph Interrupt Q= ueue 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=E9sz */ -typedef volatile u8 vol_u8; - -typedef volatile struct /* counters of E1-errors and errored seconds, s= ee 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: hdb= 3 violations */ - path_code_violations, /* FAS errors and CRC4 errors = */ - e_bit_errors, /* E-Bit Errors (the remote side received from us w= ith CRC4-error) */ - slip_secs, /* number of seconds with (receive) Controlled Slip(s)= */ - fr_loss_secs, /* number of seconds an Out Of Frame defect was det= ected */ - line_err_secs, /* number of seconds with one or more Line Code Vi= olations */ - 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: >=3D832 Path COde Violations || >0 Out Of Frame defects - - noCRC4: >=3D2048 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=20 - - (any) loopback has been set = */ - - /* - * we do not strictly comply to the rfc: we do not retroactively red= uce errored_secs, - * bursty_err_secs, severely_err_secs when 'unavailable state' is re= ached - */ - -} e1_stats_t; - -typedef volatile struct /* ezek board-adatok, nem lehetnek a slicecom_p= rivdata -ban */ -{ - int use_count; /* num. of interfaces using the board = */ - int irq; /* a kartya irq-ja. belemasoljuk a dev->irq -kba is, de c= sak hogy */ - /* szebb legyen az ifconfig outputja */ - /* ha !=3D 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 kar= tya */ - 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. Tim= e 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 i= nterrupt loop */ - unsigned stat_pri_races; /* number of special events, we try to hand= le them */ - unsigned stat_pti_races; - unsigned stat_pri_races_missed; /* when it can not be handled, becau= se of MAX_WORK */ - unsigned stat_pti_races_missed; - -#define SLICECOM_BOARD_INTERVALS_SIZE 97 - e1_stats_t intervals[SLICECOM_BOARD_INTERVALS_SIZE]; /* E1 line stat= istics */ - unsigned current_interval; /* pointer to the current interval = */ - unsigned elapsed_seconds; /* elapsed seconds from the start of the c= urrent interval */ - unsigned ses_seconds; /* counter of contiguous Severely Errored Seco= nds */ - unsigned is_unavailable; /* set to 1 after 10 contiguous Severely Er= rored 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 trans= mit */ - 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 r= egs if strtoul() fails */ -static u32 lbireg; -static u8 lbireg_ertek; /* why static: don't write stack trash into reg= s 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 n= ot used channels - * Should be called from the open and close, when the timeslot assignmen= t changes - */ - -void rework_idle_channels(struct net_device *dev) -{ - struct comx_channel *ch =3D netdev_priv(dev); - struct slicecom_privdata *hw =3D ch->HW_privdata; - munich_board_t *board =3D slicecom_boards + hw->boardnum; - munich_ccb_t *ccb =3D board->ccb; - - u8 *lbi =3D board->lbi; - int i, j, tmp; - - - spin_lock_irqsave(&mister_lock, flags); - - for (i =3D 0; i < 4; i++) - { - tmp =3D 0xFF; - for (j =3D 0; j < 8; j++) - if (ccb->timeslot_spec[8 * i + j].tti =3D=3D 0) tmp ^=3D (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 =3D slicecom_boards[boardnum].lbi; - - spin_lock_irqsave(&mister_lock, flags); - - slicecom_boards[boardnum].framing =3D 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 =3D slicecom_boards[boardnum].lbi; - - spin_lock_irqsave(&mister_lock, flags); - - slicecom_boards[boardnum].linecode =3D 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 =3D slicecom_boards[boardnum].lbi; - - spin_lock_irqsave(&mister_lock, flags); - - slicecom_boards[boardnum].clock_source =3D 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 =3D slicecom_boards[boardnum].lbi; - - spin_lock_irqsave(&mister_lock, flags); - - slicecom_boards[boardnum].loopback =3D 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 =3D board->bar1; - u8 *lbi =3D board->lbi; - u8 frs0; - u32 leds; - int i; - - spin_lock_irqsave(&mister_lock, flags); - - leds =3D 0; - frs0 =3D readb(lbi + FRS0); /* FRS0 bits described on page 137 */ - - if (!(frs0 & 0xa0)) - { - leds |=3D 0x2000; /* Green LED: Input signal seems to be OK, no LOS, n= o LFA */ - if (frs0 & 0x10) - leds |=3D 0x8000; /* Red LED: Receiving Remote Alarm = */ - } - writel(leds, MUNICH_VIRT(GPDATA)); - - if (leds =3D=3D 0x2000 && !board->lineup) - { /* line up */ - board->lineup =3D 1; - for (i =3D 0; i < 32; i++) - { - if (board->twins[i] && (board->twins[i]->flags & IFF_RUNNING)) - { - struct comx_channel *ch =3D board->twins[i]->priv; - - if (!test_and_set_bit(0, &ch->lineup_pending)) - { - ch->lineup_timer.function =3D comx_lineup_func; - ch->lineup_timer.data =3D (unsigned long)board->twins[i]; - ch->lineup_timer.expires =3D jiffies + HZ * ch->lineup_delay; - add_timer(&ch->lineup_timer); - } - } - } - } - else if (leds !=3D 0x2000 && board->lineup) - { /* line down */ - board->lineup =3D 0; - for (i =3D 0; i < 32; i++) - if (board->twins[i] && (board->twins[i]->flags & IFF_RUNNING)) - { - struct comx_channel *ch =3D 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 &=3D ~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 inter= rupt. - * Hardware counters contain error counts for last 1-second time interva= l. - * 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 =3D &board->intervals[board->current_interval]; - - u8 *lbi =3D 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 numbe= r of slips! */ - out_of_frame_defect, /* logical value */ - ais_defect, /* logical value */ - errored_sec, bursty_err_sec, severely_err_sec =3D 0, failure_sec; - u8 isr2, isr3, isr5, frs0; - - spin_lock_irqsave(&mister_lock, flags); - - isr2 =3D readb(lbi + ISR2); /* ISR0-5 described on page 156 */ - isr3 =3D readb(lbi + ISR3); - isr5 =3D readb(lbi + ISR5); - frs0 =3D readb(lbi + FRS0); /* FRS0 described on page 137 */ - - /* Error Events: */ - - code_violations =3D readb(lbi + CVCL) + (readb(lbi + CVCH) << 8); - framing_errors =3D readb(lbi + FECL) + (readb(lbi + FECH) << 8); - crc4_errors =3D readb(lbi + CEC1L) + (readb(lbi + CEC1H) << 8); - e_bit_errors =3D readb(lbi + EBCL) + (readb(lbi + EBCH) << 8); - slip_detected =3D isr3 & (ISR3_RSN | ISR3_RSP); - - path_code_violations =3D framing_errors + crc4_errors; - - curr_int->line_code_violations +=3D code_violations; - curr_int->path_code_violations +=3D path_code_violations; - curr_int->e_bit_errors +=3D e_bit_errors; - - /* Performance Defects: */ - - /* there was an LFA in the last second, but maybe disappeared: */ - out_of_frame_defect =3D (isr2 & ISR2_LFA) || (frs0 & FRS0_LFA); - - /* there was an AIS in the last second, but maybe disappeared: */ - ais_defect =3D (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 =3D ((board->framing =3D=3D SLICECOM_FRAMING_NO_CRC4) && - (code_violations)) || path_code_violations || - out_of_frame_defect || slip_detected || ais_defect; - - bursty_err_sec =3D !out_of_frame_defect && !ais_defect && - (path_code_violations > 1) && (path_code_violations < 320); - - switch (board->framing) - { - case SLICECOM_FRAMING_CRC4: - severely_err_sec =3D out_of_frame_defect || - (path_code_violations >=3D 832); - break; - case SLICECOM_FRAMING_NO_CRC4: - severely_err_sec =3D (code_violations >=3D 2048); - break; - } - - /* - * failure_sec: true if there was a condition leading to a failure - * (and leading to unavailable state) in this second: - */ - - failure_sec =3D (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 !=3D SLICECOM_LOOPBACK_NONE); /* Loopback has been = set */ - - if (board->is_unavailable) - { - if (severely_err_sec) - board->no_ses_seconds =3D 0; - else - board->no_ses_seconds++; - - if ((board->no_ses_seconds >=3D 10) && !failure_sec) - { - board->is_unavailable =3D 0; - board->ses_seconds =3D 0; - board->no_ses_seconds =3D 0; - } - } - else - { - if (severely_err_sec) - board->ses_seconds++; - else - board->ses_seconds =3D 0; - - if ((board->ses_seconds >=3D 10) || failure_sec) - { - board->is_unavailable =3D 1; - board->ses_seconds =3D 0; - board->no_ses_seconds =3D 0; - } - } - - if (board->is_unavailable) - curr_int->unavail_secs++; - else - { - if (slip_detected) - curr_int->slip_secs++; - curr_int->errored_secs +=3D errored_sec; - curr_int->bursty_err_secs +=3D bursty_err_sec; - curr_int->severely_err_secs +=3D severely_err_sec; - } - - /* the RFC does not say clearly which errors to count here, we try t= o count bit errors */ - - if (!board->is_unavailable && !severely_err_sec) - { - board->deg_cumulated_errors +=3D code_violations; - board->deg_elapsed_seconds++; - if (board->deg_elapsed_seconds >=3D 60) - { - if (board->deg_cumulated_errors >=3D 123) - curr_int->degraded_mins++; - board->deg_cumulated_errors =3D 0; - board->deg_elapsed_seconds =3D 0; - } - - } - - board->elapsed_seconds++; - if (board->elapsed_seconds >=3D 900) - { - board->current_interval =3D - (board->current_interval + 1) % SLICECOM_BOARD_INTERVALS_SIZE; - memset((void *)&board->intervals[board->current_interval], 0, - sizeof(e1_stats_t)); - board->elapsed_seconds =3D 0; - } - - spin_unlock_irqrestore(&mister_lock, flags); -} - -static void pcicom_modemline(unsigned long b) -{ - munich_board_t *board =3D (munich_board_t *) b; - struct net_device *dev =3D board->twins[0]; - struct comx_channel *ch =3D netdev_priv(dev); - unsigned long regs; - - regs =3D readl((void *)(&board->bar1[GPDATA])); - if ((ch->line_status & LINE_UP) && (regs & 0x0800)) - { - ch->line_status &=3D ~LINE_UP; - board->lineup =3D 0; - if (ch->LINE_status) - { - ch->LINE_status(dev, ch->line_status); - } - } - - if (!(ch->line_status & LINE_UP) && !(regs & 0x0800)) - { - ch->line_status |=3D LINE_UP; - board->lineup =3D 1; - if (ch->LINE_status) - { - ch->LINE_status(dev, ch->line_status); - } - } - - mod_timer((struct timer_list *)&board->modemline_timer, jiffies + HZ= ); -} - -/*=20 - * Is it possible to transmit ? - * Called (may be called) by the protocol layer=20 - */ - -static int MUNICH_txe(struct net_device *dev) -{ - struct comx_channel *ch =3D netdev_priv(dev); - struct slicecom_privdata *hw =3D ch->HW_privdata; - - return (hw->busy < TX_DESC_MAX - 1); -} - -/*=20 - * 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 =3D 0; boardnum < MAX_BOARDS; boardnum++) - { - pcicom_boards[boardnum].pci =3D 0; - pcicom_boards[boardnum].bar1 =3D 0; - pcicom_boards[boardnum].lbi =3D 0; - slicecom_boards[boardnum].pci =3D 0; - slicecom_boards[boardnum].bar1 =3D 0; - slicecom_boards[boardnum].lbi =3D 0; - } - - pci =3D NULL; - board =3D NULL; - slicecom_boardnum =3D 0; - pcicom_boardnum =3D 0; - - for (boardnum =3D 0; - boardnum < MAX_BOARDS && (pci =3D 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 =3D ioremap_nocache(pci->resource[0].start, 0x100); - lbi =3D 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) =3D=3D 0x13) || (readb(lbi + VSTR) =3D=3D 0x= 10)) - { - board =3D slicecom_boards + slicecom_boardnum; - sprintf((char *)board->devname, "slicecom%d", - slicecom_boardnum); - board->isx21 =3D 0; - slicecom_boardnum++; - } - else if ((readb(lbi + VSTR) =3D=3D 0x6) || (readb(lbi + GIS) =3D=3D= 0x6)) - { - board =3D pcicom_boards + pcicom_boardnum; - sprintf((char *)board->devname, "pcicom%d", pcicom_boardnum); - board->isx21 =3D 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 =3D pci; - board->bar1 =3D bar1; - board->lbi =3D lbi; - board->framing =3D SLICECOM_FRAMING_DEFAULT; - board->linecode =3D SLICECOM_LINECODE_DEFAULT; - board->clock_source =3D SLICECOM_CLOCK_SOURCE_DEFAULT; - board->loopback =3D SLICECOM_LOOPBACK_DEFAULT; - board->owner =3D 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 =3D 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 =3D=3D 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; -} - -/*=20 - * 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 =3D 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 - -/*=20 - * Transmit a packet.=20 - * Called by the protocol layer - * Return values:=09 - * 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 *sk= b) -{ - struct comx_channel *ch =3D netdev_priv(dev); - struct slicecom_privdata *hw =3D 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 >=3D TX_DESC_MAX - 1) - { - printk(KERN_ERR - "%s: Transmitter called while busy... dropping frame, busy =3D %= d\n", - dev->name, hw->busy); - spin_unlock_irqrestore(&mister_lock, flags); - kfree_skb(skb); - return FRAME_DROPPED; - } - - if (hw->busy >=3D 0) - hw->tx_ring_hist[hw->busy]++; - /* DELL: */ - else - printk("slicecom: %s: FATAL: busy =3D %d\n", dev->name, hw->busy); - -// /* DEL: */ -// printk("slicecom: %s: _send_packet called, busy =3D %d\n", dev->= name, hw->busy ); - - /* Packet can go, update stats: */ - - ch->stats.tx_packets++; - ch->stats.tx_bytes +=3D skb->len; - - /* Pass the packet to the HW: */ - /* Step forward with the transmit descriptors: */ - - hw->tx_desc_ptr =3D (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 =3D skb->len; - - /* We don't issue any command, just step with the HOLD bit */ - - hw->tx_desc[hw->tx_desc_ptr].hold =3D 1; - hw->tx_desc[(hw->tx_desc_ptr + TX_DESC_MAX - 1) % TX_DESC_MAX].hold = =3D 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 >=3D 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_reg= s *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 me= g kezelni */ - race_stat =3D 0, /* race eseten ebben uzenek magamnak hogy mit ke= ll meg lekezelni */ - ack; /* ezt fogom a vegen a STAT-ba irni, kiveszek belole 1-1 bi= tet 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 =3D (munich_board_t *) dev_id; - int channel; - - // , boardnum =3D (int)dev_id; - - // board =3D munich_boards + boardnum; - bar1 =3D board->bar1; - lbi =3D board->lbi; - - // Do not uncomment this under heavy load! :-> - // printk("MUNICH_interrupt: masked STAT=3D0x%08x, tiq=3D0x%08x= , riq=3D0x%08x, piq=3D0x%08x\n", stat, board->tiq[0].all, board->riq[0].a= ll, board->piq[0].all ); - - for (work =3D 0; (stat =3D (race_stat | (readl(MUNICH_VIRT(STAT)) & = ~STAT_NOT_HANDLED_BY_INTERRUPT))) && (work < MAX_WORK - 1); work++) - { - ack =3D stat & (STAT_PRI | STAT_PTI | STAT_LBII); - - /* Handle the interrupt information in the Rx queue. We don't really tr= ust */ - /* 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 =3D board->riq[board->riq_ptr]; - if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info= van */ - { - ack &=3D ~STAT_PRI; /* don't ack the interrupt, we had some work to= do */ - - channel =3D PCM_INT_CHANNEL(int_info.all); - dev =3D board->twins[channel]; - - if (dev =3D=3D NULL) - { - printk - ("MUNICH_interrupt: got an Rx interrupt info for NULL device " - "%s.twins[%d], int_info =3D 0x%08x\n", board->devname, - channel, int_info.all); - goto go_for_next_interrupt; - } - - ch =3D netdev_priv(dev); - hw =3D (struct slicecom_privdata *)ch->HW_privdata; - - // printk("Rx STAT=3D0x%08x int_info=3D0x%08x rx_desc_ptr=3D%d= rx_desc.status=3D0x%01x\n", - // stat, int_info.all, hw->rx_desc_ptr, hw->rx_desc[ h= w->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 belol= e hogy mikor ad a masik oldal */ - /* TOD: ilyen IT most nem is jon, mert ki van maszkolva az interrup= t, 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 lehete= tt, hanem esemeny, stb. is. lasd page 247. Ezzel a 'cat status'-hoz igazo= dok, de a netdevice.h szerint nem egyertelmu hogy ide ez kellene. Nem leh= et hogy rx_missed ? */ - /* DE: nem gotozok sehova, elvileg jo igy */ - /* kesobb meg visszaterek az FO-ra, ha packet-FO volt. Keresd a "packe= t-FO"-t. */ - if (int_info.all & PCM_INT_FI) /* frame received, but we do not tru= st 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 =3D 0; /* megjelolom hogy itt meg ne= m jart a hw */ - board->riq_ptr =3D (board->riq_ptr + 1) % MUNICH_INTQMAX; - - } - - /* Check every Rx ring for incomed packets: */ - - for (channel =3D 0; channel < 32; channel++) - { - dev =3D board->twins[channel]; - - if (dev !=3D NULL) - { - ch =3D netdev_priv(dev); - hw =3D (struct slicecom_privdata *)ch->HW_privdata; - - rx_status =3D hw->rx_desc[hw->rx_desc_ptr].status; - - if (!(rx_status & 0x80)) /* mar jart itt a hardver */ - { - ack &=3D ~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 thi= s one, see page 246 */ - ch->stats.rx_length_errors++; - goto go_for_next_frame; - } - - if (rx_status !=3D 0) - { - printk("SliceCOM: %s: unhandled rx_status: 0x%02x\n", - dev->name, rx_status); - goto go_for_next_frame; - } - - /* frame received without errors: */ - - length =3D hw->rx_desc[hw->rx_desc_ptr].bno; - ch->stats.rx_packets++; /* Count only 'good' packets */ - ch->stats.rx_bytes +=3D length; - - /* Allocate a larger skb and reserve the heading for efficiency: *= / - - if ((skb =3D dev_alloc_skb(length + 16)) =3D=3D NULL) - { - ch->stats.rx_dropped++; - goto go_for_next_frame; - } - - /* Do bookkeeping: */ - - skb_reserve(skb, 16); - skb_put(skb, length); - skb->dev =3D 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) =3D=3D 0x02000000 && - *(((int *)skb->data) + 1) =3D=3D 0x3580008f) - { - printk("%s: swapping hack\n", dev->name); - *((int *)skb->data) =3D 0x3580008f; - *(((int *)skb->data) + 1) =3D 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 !=3D 0xff) - hw->rafutott++; /* rafutott: hanyszor volt olyan hogy a current d= escriptoron HOLD bit volt, es a hw mar befejezte az irast (azaz a hw rafu= tott 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].hol= d =3D 1; - hw->rx_desc[hw->rx_desc_ptr].status =3D 0xFF; /* megjelolom hogy i= tt meg nem jart a hw */ - hw->rx_desc[(hw->rx_desc_ptr + RX_DESC_MAX - 2) % RX_DESC_MAX].hol= d =3D 0; - hw->rx_desc_ptr =3D (hw->rx_desc_ptr + 1) % RX_DESC_MAX; - // } - } - } - } - - stat &=3D ~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 =3D board->tiq[board->tiq_ptr]; - if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info= van */ - { - ack &=3D ~STAT_PTI; /* don't ack the interrupt, we had some work to= do */ - - channel =3D PCM_INT_CHANNEL(int_info.all); - dev =3D board->twins[channel]; - - if (dev =3D=3D NULL) - { - printk("MUNICH_interrupt: got a Tx interrupt for NULL device " - "%s.twins[%d], int_info =3D 0x%08x\n", - board->isx21 ? "pcicom" : "slicecom", channel, int_info.all); - goto go_for_next_tx_interrupt; - } - - ch =3D netdev_priv(dev); - hw =3D (struct slicecom_privdata *)ch->HW_privdata; - - // printk("Tx STAT=3D0x%08x int_info=3D0x%08x tiq_ptr=3D%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 =3D 0; - board->tiq_ptr =3D (board->tiq_ptr + 1) % MUNICH_INTQMAX; - } - - /* Check every Tx ring for incoming packets: */ - - for (channel =3D 0; channel < 32; channel++) - { - dev =3D board->twins[channel]; - - if (dev !=3D NULL) - { - int newbusy; - - ch =3D netdev_priv(dev); - hw =3D (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 =3D ( 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 =3D %d, HW: 0x%p, S= W: 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 &=3D ~STAT_PTI; /* Don't ack, we ha= d some work */ - hw->busy =3D 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 &=3D ~STAT_PTI; - - int_info =3D board->piq[board->piq_ptr]; - if (int_info.all & 0xF0000000) /* ha ez nem 0, akkor itt interrupt_info= van */ - { - ack &=3D ~STAT_LBII; /* don't ack the interrupt, we had some work t= o do */ - - /* We do not really use (yet) the interrupt info from this queue, *= / - - // printk("slicecom: %s: LBI Interrupt event: %08x\n", board->devna= me, 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 la= bel */ - - go_for_next_lbi_interrupt: /* One step in the interrupt queue */ - board->piq[board->piq_ptr].all =3D 0; /* megjelolom hogy itt meg ne= m jart a hw */ - board->piq_ptr =3D (board->piq_ptr + 1) % MUNICH_PIQMAX; - } - stat &=3D ~STAT_LBII; - - writel(ack, MUNICH_VIRT(STAT)); - - if (stat & STAT_TSPA) - { - // printk("slicecom: %s: PCM TSP Asynchronous\n", board->devna= me); - writel(STAT_TSPA, MUNICH_VIRT(STAT)); - stat &=3D ~STAT_TSPA; - } - - if (stat & STAT_RSPA) - { - // printk("slicecom: %s: PCM RSP Asynchronous\n", board->devna= me); - writel(STAT_RSPA, MUNICH_VIRT(STAT)); - stat &=3D ~STAT_RSPA; - } - if (stat) - { - printk("MUNICH_interrupt: unhandled interrupt, STAT=3D0x%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; -} - -/*=20 - * Hardware open routine. - * Called by comx (upper) layer when the user wants to bring up the inte= rface - * 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 =3D netdev_priv(dev); - struct slicecom_privdata *hw =3D ch->HW_privdata; - struct proc_dir_entry *procfile =3D 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 =3D hw->timeslots; - - board =3D hw->boardnum + (ch->hardware =3D=3D &pcicomhw ? pcicom_boa= rds : slicecom_boards); - - bar1 =3D board->bar1; - lbi =3D 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 =3D %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 =3D=3D 0) /* bring up the board if it was unuse= d */ - /* 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 =3D 0; i < 32; i++) - board->twins[i] =3D NULL; - for (i =3D 0; i < MAX_WORK; i++) - board->histogram[i] =3D 0; - - board->lineup =3D 0; - - /* Allocate CCB: */ - board->ccb =3D kmalloc(sizeof(munich_ccb_t), GFP_KERNEL); - if (board->ccb =3D=3D NULL) - { - spin_unlock_irqrestore(&mister_lock, flags); - return -ENOMEM; - } - memset((void *)board->ccb, 0, sizeof(munich_ccb_t)); - board->ccb->csa =3D virt_to_phys(board->ccb); - ccb =3D board->ccb; - for (i =3D 0; i < 32; i++) - { - ccb->timeslot_spec[i].tti =3D 1; - ccb->timeslot_spec[i].rti =3D 1; - } - - /* Interrupt queues: */ - - board->tiq =3D kmalloc(MUNICH_INTQSIZE, GFP_KERNEL); - if (board->tiq =3D=3D NULL) - { - spin_unlock_irqrestore(&mister_lock, flags); - return -ENOMEM; - } - memset((void *)board->tiq, 0, MUNICH_INTQSIZE); - - board->riq =3D kmalloc(MUNICH_INTQSIZE, GFP_KERNEL); - if (board->riq =3D=3D NULL) - { - spin_unlock_irqrestore(&mister_lock, flags); - return -ENOMEM; - } - memset((void *)board->riq, 0, MUNICH_INTQSIZE); - - board->piq =3D kmalloc(MUNICH_PIQSIZE, GFP_KERNEL); - if (board->piq =3D=3D NULL) - { - spin_unlock_irqrestore(&mister_lock, flags); - return -ENOMEM; - } - memset((void *)board->piq, 0, MUNICH_PIQSIZE); - - board->tiq_ptr =3D 0; - board->riq_ptr =3D 0; - board->piq_ptr =3D 0; - - /* Request irq: */ - - board->irq =3D 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 =3D board->pci->irq; /* csak akkor legyen !=3D 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)); - =20 - /* 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_V= IRT(STAT)); - - ccb->action_spec =3D 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 =3D 0; /* Wait for the action to complete max. 1 second */ - jiffs =3D jiffies; - while (!((stat =3D 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=3D0x%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 t= oo *//* maybe shut down hw? */ - board->irq =3D 0; - spin_unlock_irqrestore(&mister_lock, flags); - return -EAGAIN; - } - else if (!(stat & STAT_PCMA)) - { - printk(KERN_ERR - "MUNICH_open: %s: Initial ARPCM timeout. STAT=3D0x%08x\n", - board->devname, stat); - free_irq(board->irq, (void *)board); /* TOD: free other resources t= oo *//* maybe shut off the hw? */ - board->irq =3D 0; - spin_unlock_irqrestore(&mister_lock, flags); - return -EIO; - } - - writel(readl(MUNICH_VIRT(STAT)) & STAT_PCMA, MUNICH_VIRT(STAT)); /* Ack= nowledge */ - - 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 ou= tput, 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 =3D 0; - board->elapsed_seconds =3D 0; - board->ses_seconds =3D 0; - board->is_unavailable =3D 0; - board->no_ses_seconds =3D 0; - board->deg_elapsed_seconds =3D 0; - board->deg_cumulated_errors =3D 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 =3D board->irq; /* hogy szep legyen az ifconfig outputja */ - ccb =3D 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 =3D 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 =3D 0; channel <=3D 32; channel++) - { - if (channel =3D=3D 32) - { /* not found a free one */ - printk - ("MUNICH_open: %s: FATAL: can not find a free channel - this should no= t happen!\n", - dev->name); - spin_unlock_irqrestore(&mister_lock, flags); - return -ENODEV; - } - if (board->twins[channel] =3D=3D NULL) - break; /* found the first free one */ - } - - board->lastcheck =3D jiffies; /* avoid checking uninitialized hardwa= re channel */ - - /* Open the channel. If fails, calls MUNICH_close() to properly free= resources and stop the HW */ - - hw->channel =3D channel; - board->twins[channel] =3D dev; - - board->use_count++; /* meg nem nyitottuk meg a csatornat, de a twin= s-ben - mar elfoglaltunk egyet, es ha a _close-t akarjuk hivni, akkor ez = kell. */ - for (i =3D 0; i < 32; i++) - if ((1 << i) & timeslots) - { - ccb->timeslot_spec[i].tti =3D 0; - ccb->timeslot_spec[i].txchannel =3D channel; - ccb->timeslot_spec[i].txfillmask =3D ~0; - - ccb->timeslot_spec[i].rti =3D 0; - ccb->timeslot_spec[i].rxchannel =3D channel; - ccb->timeslot_spec[i].rxfillmask =3D ~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 =3D 0; i < TX_DESC_MAX; i++) - { - hw->tx_desc[i].fe =3D 1; - hw->tx_desc[i].fnum =3D 2; - hw->tx_desc[i].data =3D virt_to_phys( & (hw->tx_data= [i][0]) ); - hw->tx_desc[i].next =3D virt_to_phys( & (hw->tx_desc= [ (i+1) % TX_DESC_MAX ]) ); - - } - hw->tx_desc_ptr =3D 0; /* we will send an initial packet so it is co= rrect: "oda irtunk utoljara" */ - hw->busy =3D 0; - hw->tx_desc[hw->tx_desc_ptr].hold =3D 1; - hw->tx_desc[hw->tx_desc_ptr].no =3D 1; /* TOD: inkabb csak 0 hosszut= kuldjunk ki az initkor? */ - - for (i =3D 0; i < RX_DESC_MAX; i++) - { - hw->rx_desc[i].no =3D RXBUFFER_SIZE; - hw->rx_desc[i].data =3D virt_to_phys(&(hw->rx_data[i][0])); - hw->rx_desc[i].next =3D virt_to_phys(&(hw->rx_desc[(i+1) % RX_DESC_MAX]= )); - hw->rx_desc[i].status =3D 0xFF; - } - hw->rx_desc_ptr =3D 0; - - hw->rx_desc[(hw->rx_desc_ptr + RX_DESC_MAX - 2) % RX_DESC_MAX].hold = =3D 1; - - memset((void *)&ccb->channel_spec[channel], 0, sizeof(channel_spec_t= )); - - ccb->channel_spec[channel].ti =3D 0; /* Transmit off */ - ccb->channel_spec[channel].to =3D 1; - ccb->channel_spec[channel].ta =3D 0; - - ccb->channel_spec[channel].th =3D 1; /* Transmit hold */ - - ccb->channel_spec[channel].ri =3D 0; /* Receive off */ - ccb->channel_spec[channel].ro =3D 1; - ccb->channel_spec[channel].ra =3D 0; - - ccb->channel_spec[channel].mode =3D 3; /* HDLC */ - - ccb->action_spec =3D 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 =3D 0; - jiffs =3D jiffies; - while (!((stat =3D readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCM= F)) && 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 jiff= ies\n", board->devname, jiffies-jiffs); - - spin_lock_irqsave(&mister_lock, flags); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - - ccb->channel_spec[channel].ifc =3D 1; /* 1 .. 'Idle/Flag change' int= errupt letiltva */ - ccb->channel_spec[channel].fit =3D 1; - ccb->channel_spec[channel].nitbs =3D 1; - ccb->channel_spec[channel].itbs =3D 2; - - /* TODOO: lehet hogy jo lenne igy, de utana kellene nezni hogy nem o= koz-e fragmentaciot */ - // ccb->channel_spec[channel].itbs =3D 2 * number_of_timeslots; - // printk("open: %s: number_of_timeslots: %d\n", dev->name, num= ber_of_timeslots); - - ccb->channel_spec[channel].mode =3D 3; /* HDLC */ - ccb->channel_spec[channel].ftda =3D virt_to_phys(&(hw->tx_desc)); - ccb->channel_spec[channel].frda =3D virt_to_phys(&(hw->rx_desc[0])); - - ccb->channel_spec[channel].ti =3D 1; /* Transmit init */ - ccb->channel_spec[channel].to =3D 0; - ccb->channel_spec[channel].ta =3D 1; - - ccb->channel_spec[channel].th =3D 0; - - ccb->channel_spec[channel].ri =3D 1; /* Receive init */ - ccb->channel_spec[channel].ro =3D 0; - ccb->channel_spec[channel].ra =3D 1; - - ccb->action_spec =3D 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 =3D 0; /* Wait for the action to complete max. 1 second */ - jiffs =3D jiffies; - while (!((stat =3D readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCM= F)) && 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 jif= fies\n", board->devname, jiffies-jiffs); - - spin_lock_irqsave(&mister_lock, flags); - - ccb->channel_spec[channel].nitbs =3D 0; /* once ITBS defined, these = must be 0 */ - ccb->channel_spec[channel].itbs =3D 0; - - if (board->isx21) - { - init_timer(&board->modemline_timer); - board->modemline_timer.data =3D (unsigned long)board; - board->modemline_timer.function =3D pcicom_modemline; - board->modemline_timer.expires =3D jiffies + HZ; - add_timer((struct timer_list *)&board->modemline_timer); - } - - /* It is done. Declare that we're open: */ - hw->busy =3D 0; /* It may be 1 if the frame at Tx init already ende= d, but it is not */ - /* a real problem: we compute hw->busy on every interrupt = */ - hw->rafutott =3D 0; - ch->init_status |=3D HW_OPEN; - - /* Initialize line state: */ - if (board->lineup) - ch->line_status |=3D LINE_UP; - else - ch->line_status &=3D ~LINE_UP; - - /* Remove w attribute from /proc files associated to hw parameters: - no write when the device is open */ - - for (; procfile; procfile =3D procfile->next) - if (strcmp(procfile->name, FILENAME_BOARDNUM) =3D=3D 0 || - strcmp(procfile->name, FILENAME_TIMESLOTS) =3D=3D 0) - procfile->mode =3D 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 in= terface - * 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 =3D netdev_priv(dev); - struct slicecom_privdata *hw =3D ch->HW_privdata; - struct proc_dir_entry *procfile =3D ch->procdir->subdir; - munich_board_t *board; - munich_ccb_t *ccb; - - u32 *bar1; - u32 timeslots =3D hw->timeslots; - int stat, i, channel =3D hw->channel; - unsigned long jiffs; - - board =3D hw->boardnum + (ch->hardware =3D=3D &pcicomhw ? pcicom_boa= rds : slicecom_boards); - - ccb =3D board->ccb; - bar1 =3D 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 =3D 0; i < 32; i++) - if ((1 << i) & timeslots) - { - ccb->timeslot_spec[i].tti =3D 1; - ccb->timeslot_spec[i].txfillmask =3D 0; /* just to be double-sure := ) */ - - ccb->timeslot_spec[i].rti =3D 1; - ccb->timeslot_spec[i].rxfillmask =3D 0; - } - - if (!board->isx21) rework_idle_channels(dev); - - ccb->channel_spec[channel].ti =3D 0; /* Receive off, Transmit off */ - ccb->channel_spec[channel].to =3D 1; - ccb->channel_spec[channel].ta =3D 0; - ccb->channel_spec[channel].th =3D 1; - - ccb->channel_spec[channel].ri =3D 0; - ccb->channel_spec[channel].ro =3D 1; - ccb->channel_spec[channel].ra =3D 0; - - board->twins[channel] =3D NULL; - - ccb->action_spec =3D 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 =3D 0; - jiffs =3D jiffies; - while (!((stat =3D readl(MUNICH_VIRT(STAT))) & (STAT_PCMA | STAT_PCM= F)) && 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", b= oard->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 =3D=3D &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 =3D 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 =3D NULL; - board->tiq =3D board->riq =3D board->piq =3D NULL; - } - - /* Enable setting of hw parameters */ - for (; procfile; procfile =3D procfile->next) - if (strcmp(procfile->name, FILENAME_BOARDNUM) =3D=3D 0 || - strcmp(procfile->name, FILENAME_TIMESLOTS) =3D=3D 0) - procfile->mode =3D S_IFREG | 0644; - - /* We're not open anymore */ - ch->init_status &=3D ~HW_OPEN; - - spin_unlock_irqrestore(&mister_lock, flags); - - return 0; -} - -/*=20 - * 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=20 - * 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 =3D netdev_priv(dev); - struct slicecom_privdata *hw =3D 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 =3D 0; - u8 frs0, frs1; - u8 fmr2; - int i, j; - u32 timeslots; - - board =3D hw->boardnum + (ch->hardware =3D=3D &pcicomhw ? pcicom_boa= rds : slicecom_boards); - - lbi =3D board->lbi; - curr_int =3D &board->intervals[board->current_interval]; - prev_int =3D - &board-> - intervals[(board->current_interval + SLICECOM_BOARD_INTERVALS_SIZE - - 1) % SLICECOM_BOARD_INTERVALS_SIZE]; - - if (!board->isx21) - { - frs0 =3D readb(lbi + FRS0); - fmr2 =3D readb(lbi + FMR2); - len +=3D scnprintf(page + len, PAGE_SIZE - len, "Controller status:\n")= ; - if (frs0 =3D=3D 0) - len +=3D scnprintf(page + len, PAGE_SIZE - len, "\tNo alarms\n"); - else - { - if (frs0 & FRS0_LOS) - len +=3D scnprintf(page + len, PAGE_SIZE - len, "\tLoss Of = Signal\n"); - else - { - if (frs0 & FRS0_AIS) - len +=3D scnprintf(page + len, PAGE_SIZE - len, - "\tAlarm Indication Signal\n"); - else - { - if (frs0 & FRS0_AUXP) - len +=3D scnprintf(page + len, PAGE_SIZE - len, - "\tAuxiliary Pattern Indication\n"); - if (frs0 & FRS0_LFA) - len +=3D scnprintf(page + len, PAGE_SIZE - len, - "\tLoss of Frame Alignment\n"); - else - { - if (frs0 & FRS0_RRA) - len +=3D 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 =3D=3D SLICECOM_FRAMING_CRC4) && - (frs0 & FRS0_LMFA)) - len +=3D scnprintf(page + len, PAGE_SIZE - len, - "\tLoss of CRC4 Multiframe Alignment\n"); - - if (((fmr2 & 0xc0) =3D=3D 0xc0) && (frs0 & FRS0_NMF)) - len +=3D scnprintf(page + len, PAGE_SIZE - len, - "\tNo CRC4 Multiframe alignment Found after 400 msec\n"); - } - } - } - } - - frs1 =3D readb(lbi + FRS1); - if (FRS1_XLS & frs1) - len +=3D scnprintf(page + len, PAGE_SIZE - len, - "\tTransmit Line Short\n"); - - /* debug Rx ring: DEL: - vagy meghagyni, de akkor legyen kicsit altalan= osabb */ - } - - len +=3D scnprintf(page + len, PAGE_SIZE - len, "Rx ring:\n"); - len +=3D scnprintf(page + len, PAGE_SIZE - len, "\trafutott: %d\n", = hw->rafutott); - len +=3D scnprintf(page + len, PAGE_SIZE - len, - "\tlastcheck: %ld, jiffies: %ld\n", board->lastcheck, jiffies); - len +=3D scnprintf(page + len, PAGE_SIZE - len, "\tbase: %08x\n", - (u32) virt_to_phys(&hw->rx_desc[0])); - len +=3D scnprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %d\n= ", - hw->rx_desc_ptr); - len +=3D scnprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %08x= \n", - (u32) virt_to_phys(&hw->rx_desc[hw->rx_desc_ptr])); - len +=3D scnprintf(page + len, PAGE_SIZE - len, "\thw_curr_ptr: %08x= \n", - board->ccb->current_rx_desc[hw->channel]); - - for (i =3D 0; i < RX_DESC_MAX; i++) - len +=3D 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 +=3D scnprintf(page + len, PAGE_SIZE - len, - "Interfaces using this board: (channel-group, interface, timeslot= s)\n"); - for (i =3D 0; i < 32; i++) - { - devp =3D board->twins[i]; - if (devp !=3D NULL) - { - timeslots =3D - ((struct slicecom_privdata *)((struct comx_channel *)devp-> - priv)->HW_privdata)-> - timeslots; - len +=3D scnprintf(page + len, PAGE_SIZE - len, "\t%2d %s: ", i, - devp->name); - for (j =3D 0; j < 32; j++) - if ((1 << j) & timeslots) - len +=3D scnprintf(page + len, PAGE_SIZE - len, "%d ", j); - len +=3D scnprintf(page + len, PAGE_SIZE - len, "\n"); - } - } - } - - len +=3D scnprintf(page + len, PAGE_SIZE - len, "Interrupt work hist= ogram:\n"); - for (i =3D 0; i < MAX_WORK; i++) - len +=3D scnprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i, - board->histogram[i], (i && - ((i + 1) % 4 =3D=3D 0 || - i =3D=3D MAX_WORK - 1)) ? '\n' : ' '); - - len +=3D scnprintf(page + len, PAGE_SIZE - len, "Tx ring histogram:\= n"); - for (i =3D 0; i < TX_DESC_MAX; i++) - len +=3D scnprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i, - hw->tx_ring_hist[i], (i && - ((i + 1) % 4 =3D=3D 0 || - i =3D=3D - 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 =3D 1; i <=3D 4; i++) - { - p =3D (unsigned *)&board->intervals[(board->current_interval + - SLICECOM_BOARD_INTERVALS_SIZE - - i) % SLICECOM_BOARD_INTERVALS_SIZE]; - sump =3D (unsigned *)&last4; - for (j =3D 0; j < (sizeof(e1_stats_t) / sizeof(unsigned)); j++) - sump[j] +=3D p[j]; - } - - /* Calculate the sum of last 96 intervals: */ - - for (i =3D 1; i <=3D 96; i++) - { - p =3D (unsigned *)&board->intervals[(board->current_interval + - SLICECOM_BOARD_INTERVALS_SIZE - - i) % SLICECOM_BOARD_INTERVALS_SIZE]; - sump =3D (unsigned *)&last96; - for (j =3D 0; j < (sizeof(e1_stats_t) / sizeof(unsigned)); j++) - sump[j] +=3D p[j]; - } - - len +=3D scnprintf(page + len, PAGE_SIZE - len, - "Data in current interval (%d seconds elapsed):\n", - board->elapsed_seconds); - len +=3D scnprintf(page + len, PAGE_SIZE - len, - " %d Line Code Violations, %d Path Code Violations, %d E-Bit Er= rors\n", - curr_int->line_code_violations, - curr_int->path_code_violations, curr_int->e_bit_errors); - len +=3D 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 +=3D 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 +=3D scnprintf(page + len, PAGE_SIZE - len, - "Data in Interval 1 (15 minutes):\n"); - len +=3D scnprintf(page + len, PAGE_SIZE - len, - " %d Line Code Violations, %d Path Code Violations, %d E-Bit Er= rors\n", - prev_int->line_code_violations, - prev_int->path_code_violations, prev_int->e_bit_errors); - len +=3D 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 +=3D 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 +=3D scnprintf(page + len, PAGE_SIZE - len, - "Data in last 4 intervals (1 hour):\n"); - len +=3D scnprintf(page + len, PAGE_SIZE - len, - " %d Line Code Violations, %d Path Code Violations, %d E-Bit Er= rors\n", - last4.line_code_violations, last4.path_code_violations, - last4.e_bit_errors); - len +=3D 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 +=3D 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 +=3D scnprintf(page + len, PAGE_SIZE - len, - "Data in last 96 intervals (24 hours):\n"); - len +=3D scnprintf(page + len, PAGE_SIZE - len, - " %d Line Code Violations, %d Path Code Violations, %d E-Bit Er= rors\n", - last96.line_code_violations, last96.path_code_violations, - last96.e_bit_errors); - len +=3D 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 +=3D 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 +=3Dscnprintf( page + len, PAGE_SIZE - len, "Special events:= \n" ); -// len +=3Dscnprintf( page + len, PAGE_SIZE - len, "\tstat_pri/miss= ed: %u / %u\n", board->stat_pri_races, board->stat_pri_races_missed ); -// len +=3Dscnprintf( page + len, PAGE_SIZE - len, "\tstat_pti/miss= ed: %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); -} - -/*=20 - * /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 cou= nt, - int *eof, void *data) -{ - struct proc_dir_entry *file =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D file->parent->data; - struct comx_channel *ch =3D netdev_priv(dev); - struct slicecom_privdata *hw =3D ch->HW_privdata; - munich_board_t *board; - - int len =3D 0, i; - u32 timeslots =3D hw->timeslots; - - board =3D hw->boardnum + (ch->hardware =3D=3D &pcicomhw ? pcicom_boa= rds : slicecom_boards); - - if (!strcmp(file->name, FILENAME_BOARDNUM)) - len =3D sprintf(page, "%d\n", hw->boardnum); - else if (!strcmp(file->name, FILENAME_TIMESLOTS)) - { - for (i =3D 0; i < 32; i++) - if ((1 << i) & timeslots) - len +=3D scnprintf(page + len, PAGE_SIZE - len, "%d ", i); - len +=3D scnprintf(page + len, PAGE_SIZE - len, "\n"); - } - else if (!strcmp(file->name, FILENAME_FRAMING)) - { - i =3D 0; - while (slicecom_framings[i].value && - slicecom_framings[i].value !=3D board->framing) - i++; - len +=3D scnprintf(page + len, PAGE_SIZE - len, "%s\n", - slicecom_framings[i].name); - } - else if (!strcmp(file->name, FILENAME_LINECODE)) - { - i =3D 0; - while (slicecom_linecodes[i].value && - slicecom_linecodes[i].value !=3D board->linecode) - i++; - len +=3D scnprintf(page + len, PAGE_SIZE - len, "%s\n", - slicecom_linecodes[i].name); - } - else if (!strcmp(file->name, FILENAME_CLOCK_SOURCE)) - { - i =3D 0; - while (slicecom_clock_sources[i].value && - slicecom_clock_sources[i].value !=3D board->clock_source) - i++; - len +=3D - scnprintf(page + len, PAGE_SIZE - len, "%s\n", - slicecom_clock_sources[i].name); - } - else if (!strcmp(file->name, FILENAME_LOOPBACK)) - { - i =3D 0; - while (slicecom_loopbacks[i].value && - slicecom_loopbacks[i].value !=3D board->loopback) - i++; - len +=3D 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 +=3D scnprintf(page + len, PAGE_SIZE - len, - "%s: " FILENAME_REG ": write-only file\n", dev->name); - } - else if (!strcmp(file->name, FILENAME_LBIREG)) - { - len +=3D 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 add= ress - and count: */ - - if (off >=3D len) - { - *eof =3D 1; - return 0; - } - - *start =3D page + off; - if (count >=3D len - off) - *eof =3D 1; - return min((off_t) count, (off_t) len - off); -} - -/*=20 - * 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 =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D (struct net_device *)entry->parent->data; - struct comx_channel *ch =3D netdev_priv(dev); - struct slicecom_privdata *hw =3D ch->HW_privdata; - munich_board_t *board; - - unsigned long ts, tmp_boardnum; - - u32 tmp_timeslots =3D 0; - char *page, *p; - int i; - - board =3D hw->boardnum + (ch->hardware =3D=3D &pcicomhw ? pcicom_boa= rds : slicecom_boards); - - /* Paranoia checking: */ - - if (PDE(file->f_dentry->d_inode) !=3D entry) - { - printk(KERN_ERR "munich_write_proc: file <-> data internal error\n"); - return -EIO; - } - - /* Request tmp buffer */ - if (!(page =3D (char *)__get_free_page(GFP_KERNEL))) - return -ENOMEM; - - /* Copy user data and cut trailing \n */ - if (copy_from_user(page, buffer, count =3D min(count, PAGE_SIZE))) { - free_page((unsigned long)page); - return -EFAULT; - } - if (*(page + count - 1) =3D=3D '\n') - *(page + count - 1) =3D 0; - *(page + PAGE_SIZE - 1) =3D 0; - - if (!strcmp(entry->name, FILENAME_BOARDNUM)) - { - tmp_boardnum =3D simple_strtoul(page, NULL, 0); - if (0 <=3D tmp_boardnum && tmp_boardnum < MAX_BOARDS) - hw->boardnum =3D 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 =3D page; - while (*p) - { - if (isspace(*p)) - p++; - else - { - ts =3D simple_strtoul(p, &p, 10); /* base =3D 10: Don't read 09 as an = octal number */ - /* ts =3D 0 ha nem tudta beolvasni a stringet, erre egy kicsit epitek = itt: */ - if (0 <=3D ts && ts < 32) - { - tmp_timeslots |=3D (1 << ts); - } - else - { - printk("%s: " FILENAME_TIMESLOTS " range is 1...31\n", - dev->name); - free_page((unsigned long)page); - return -EINVAL; - } - } - } - hw->timeslots =3D tmp_timeslots; - } - else if (!strcmp(entry->name, FILENAME_FRAMING)) - { - i =3D 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 t= he framing for board 0 - * Workaround: allow to set it only if interface is administrative U= P - */ - 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 =3D 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 =3D 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 =3D 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 =3D board->bar1; - - reg =3D simple_strtoul(page, &p, 0); - reg_ertek =3D simple_strtoul(p + 1, NULL, 0); - - if (reg < 0x100) - { - printk("reg(0x%02x) :=3D 0x%08x jiff: %lu\n", reg, reg_ertek, jiff= ies); - 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 =3D board->lbi; - - lbireg =3D simple_strtoul(page, &p, 0); - lbireg_ertek =3D simple_strtoul(p + 1, NULL, 0); - - if (lbireg < 0x100) - { - printk("lbireg(0x%02x) :=3D 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; -} - -/*=20 - * 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 =3D netdev_priv(dev); - struct slicecom_privdata *hw; - struct proc_dir_entry *new_file; - - /* Alloc data for private structure */ - if ((ch->HW_privdata =3D - kmalloc(sizeof(struct slicecom_privdata), GFP_KERNEL)) =3D=3D NULL) - return -ENOMEM; - =20 - memset(hw =3D ch->HW_privdata, 0, sizeof(struct slicecom_privdata)); - - /* Register /proc files */ - if ((new_file =3D create_proc_entry(FILENAME_BOARDNUM, S_IFREG | 064= 4, - ch->procdir)) =3D=3D NULL) - return init_escape(ch); - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &munich_read_proc; - new_file->write_proc =3D &munich_write_proc; -// new_file->proc_iops =3D &comx_normal_inode_ops; - new_file->nlink =3D 1; - - if (ch->hardware =3D=3D &slicecomhw) - { - if ((new_file =3D create_proc_entry(FILENAME_TIMESLOTS, S_IFREG | 0644, - ch->procdir)) =3D=3D NULL) - return init_escape(ch); - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &munich_read_proc; - new_file->write_proc =3D &munich_write_proc; -// new_file->proc_iops =3D &comx_normal_inode_ops; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_FRAMING, S_IFREG | 0644, - ch->procdir)) =3D=3D NULL) - return init_escape(ch); - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &munich_read_proc; - new_file->write_proc =3D &munich_write_proc; -// new_file->proc_iops =3D &comx_normal_inode_ops; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_LINECODE, S_IFREG | 0644, - ch->procdir)) =3D=3D NULL) - return init_escape(ch); - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &munich_read_proc; - new_file->write_proc =3D &munich_write_proc; -// new_file->proc_iops =3D &comx_normal_inode_ops; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_CLOCK_SOURCE, S_IFREG | 06= 44, - ch->procdir)) =3D=3D NULL) - return init_escape(ch); - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &munich_read_proc; - new_file->write_proc =3D &munich_write_proc; -// new_file->proc_iops =3D &comx_normal_inode_ops; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_LOOPBACK, S_IFREG | 0644, - ch->procdir)) =3D=3D NULL) - return init_escape(ch); - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &munich_read_proc; - new_file->write_proc =3D &munich_write_proc; -// new_file->proc_iops =3D &comx_normal_inode_ops; - new_file->nlink =3D 1; - } - - /* DEL: ez itt csak fejlesztesi celokra!! */ - if ((new_file =3D create_proc_entry(FILENAME_REG, S_IFREG | 0200, ch= ->procdir)) =3D=3D NULL) - return init_escape(ch); - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &munich_read_proc; - new_file->write_proc =3D &munich_write_proc; -// new_file->proc_iops =3D &comx_normal_inode_ops; - new_file->nlink =3D 1; - - /* DEL: ez itt csak fejlesztesi celokra!! */ - if ((new_file =3D create_proc_entry(FILENAME_LBIREG, S_IFREG | 0200, - ch->procdir)) =3D=3D NULL) - return init_escape(ch); - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &munich_read_proc; - new_file->write_proc =3D &munich_write_proc; -// new_file->proc_iops =3D &comx_normal_inode_ops; - new_file->nlink =3D 1; - - /* Fill in ch_struct hw specific pointers: */ - - ch->HW_txe =3D MUNICH_txe; - ch->HW_open =3D MUNICH_open; - ch->HW_close =3D MUNICH_close; - ch->HW_send_packet =3D MUNICH_send_packet; -#ifndef COMX_NEW - ch->HW_minden =3D MUNICH_minden; -#else - ch->HW_statistics =3D MUNICH_minden; -#endif - - hw->boardnum =3D SLICECOM_BOARDNUM_DEFAULT; - hw->timeslots =3D ch->hardware =3D=3D &pcicomhw ? 0xffffffff : 2; - - /* O.K. Count one more user on this module */ - MOD_INC_USE_COUNT; - return 0; -} - -/*=20 - * Boardtype exit function. - * Called by the comx (upper) layer, when you clear boardtype from munic= h. - * 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 =3D netdev_priv(dev); - - /* Free private data area */ -// board =3D hw->boardnum + (ch->hardware =3D=3D &pcicomhw ? pcicom_b= oards : slicecom_boards); - - kfree(ch->HW_privdata); - /* Remove /proc files */ - remove_proc_entry(FILENAME_BOARDNUM, ch->procdir); - if (ch->hardware =3D=3D &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 =3D -{ - "slicecom", -#ifdef COMX_NEW - VERSION, -#endif - BOARD_init, - BOARD_exit, - BOARD_dump, - NULL -}; - -static struct comx_hardware pcicomhw =3D -{ - "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 =3D 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); =3D=3D=3D=3D=3D drivers/net/wan/comx-proto-fr.c 1.13 vs edited =3D=3D=3D=3D= =3D --- 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=20 - * for Linux 2.2.X - * - * Original author: Tivadar Szemethy - * Maintainer: Gergely Madarasz - * - * Copyright (C) 1998-1999 ITConsult-Pro Co. - *=20 - * Contributors: - * Arnaldo Carvalho de Melo (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=20 - * - * 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 - *=20 - * 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 =20 - */ =20 -#define VERSION "0.73" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "comx.h" -#include "comxhw.h" - -MODULE_AUTHOR("Author: Tivadar Szemethy "); -MODULE_DESCRIPTION("Frame Relay protocol implementation for the COMX dri= vers" - "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=09 -#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)=20 -{ - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D ch->LINE_privdata; - struct sk_buff *skb; - u8 *fr_packet; -=09 - skb=3Dalloc_skb(dev->hard_header_len + 13, GFP_ATOMIC); -=09 - if(skb=3D=3DNULL) - return; - =20 - skb_reserve(skb, dev->hard_header_len); - =20 - fr_packet=3D(u8*)skb_put(skb, 13); - =20 - fr_packet[0] =3D (fr->dlci & (1024 - 15)) >> 2; - fr_packet[1] =3D (fr->dlci & 15) << 4 | 1; // EA bit 1 - fr_packet[2] =3D FRAD_UI; - fr_packet[3] =3D NLPID_Q933_LMI; - fr_packet[4] =3D 0; - fr_packet[5] =3D Q933_ENQ; - fr_packet[6] =3D Q933_LINESTAT; - fr_packet[7] =3D 0x01; - fr_packet[8] =3D 0x01; - fr_packet[9] =3D Q933_COUNTERS; - fr_packet[10] =3D 0x02; - fr_packet[11] =3D ++fr->local_cnt; - fr_packet[12] =3D fr->remote_cnt; - - skb->dev =3D dev; - skb->priority =3D TC_PRIO_CONTROL; - dev_queue_xmit(skb); -} - -static void fr_keepalive_timerfun(unsigned long d)=20 -{ - struct net_device *dev =3D (struct net_device *)d; - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D ch->LINE_privdata; - struct proc_dir_entry *dir =3D 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 =3D=3D MAXALIVECNT) { - comx_status(dev, ch->line_status & ~PROTO_UP); - dev->flags &=3D ~IFF_RUNNING; - for (; dir ; dir =3D dir->next) { - if(!S_ISDIR(dir->mode)) { - continue; - } -=09 - if ((sdev =3D dir->data) && (sch =3D sdev->priv) &&=20 - (sdev->type =3D=3D ARPHRD_DLCI) &&=20 - (sfr =3D sch->LINE_privdata)=20 - && (sfr->master =3D=3D dev) &&=20 - (sdev->flags & IFF_UP)) { - sdev->flags &=3D ~IFF_RUNNING; - comx_status(sdev,=20 - sch->line_status & ~PROTO_UP); - } - } - } - if (fr->keepalivecnt <=3D 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,=20 - u16 dlci, u8 nlpid)=20 -{ - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D ch->LINE_privdata; - struct proc_dir_entry *dir =3D ch->procdir->parent->subdir; - struct comx_channel *sch; - struct fr_data *sfr; - struct net_device *sdev; - - if (dlci !=3D fr->dlci || nlpid !=3D NLPID_Q933_LMI || !fr->keepa_freq)= { - return; - } - - fr->remote_cnt =3D skb->data[7]; - if (skb->data[8] =3D=3D fr->local_cnt) { // keepalive UP! - fr->keepalivecnt =3D 0; - if ((ch->line_status & LINE_UP) &&=20 - !(ch->line_status & PROTO_UP)) { - comx_status(dev, ch->line_status |=3D PROTO_UP); - dev->flags |=3D IFF_RUNNING; - for (; dir ; dir =3D dir->next) { - if(!S_ISDIR(dir->mode)) { - continue; - } -=09 - if ((sdev =3D dir->data) && (sch =3D sdev->priv) &&=20 - (sdev->type =3D=3D ARPHRD_DLCI) &&=20 - (sfr =3D sch->LINE_privdata)=20 - && (sfr->master =3D=3D dev) &&=20 - (sdev->flags & IFF_UP)) { - sdev->flags |=3D IFF_RUNNING; - comx_status(sdev,=20 - sch->line_status | PROTO_UP); - } - } - } - } -} - -static void fr_set_keepalive(struct net_device *dev, int keepa)=20 -{ - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D ch->LINE_privdata; - - if (!keepa && fr->keepa_freq) { // switch off - fr->keepa_freq =3D 0; - if (ch->line_status & LINE_UP) { - comx_status(dev, ch->line_status | PROTO_UP); - dev->flags |=3D 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 =3D keepa; - fr->local_cnt =3D fr->remote_cnt =3D 0; - init_timer(&fr->keepa_timer); - fr->keepa_timer.expires =3D jiffies + HZ; - fr->keepa_timer.function =3D fr_keepalive_timerfun; - fr->keepa_timer.data =3D (unsigned long)dev; - ch->line_status &=3D ~(PROTO_UP | PROTO_LOOP); - dev->flags &=3D ~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)=20 -{ - struct comx_channel *ch =3D dev->priv; - struct proc_dir_entry *dir =3D ch->procdir->parent->subdir; - struct net_device *sdev =3D dev; - struct comx_channel *sch; - struct fr_data *sfr; - u16 dlci; - u8 nlpid; - - if(skb->len <=3D 4 || skb->data[2] !=3D FRAD_UI) { - kfree_skb(skb); - return; - } - - /* Itt majd ki kell talalni, melyik slave kapja a csomagot */ - dlci =3D ((skb->data[0] & 0xfc) << 2) | ((skb->data[1] & 0xf0) >> 4); - if ((nlpid =3D skb->data[3]) =3D=3D 0) { // Optional padding=20 - nlpid =3D 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",=20 - dlci, nlpid); - comx_debug_skb(dev, skb, "Contents"); - } - - /* Megkeressuk, kihez tartozik */ - for (; dir ; dir =3D dir->next) { - if(!S_ISDIR(dir->mode)) { - continue; - } - if ((sdev =3D dir->data) && (sch =3D sdev->priv) &&=20 - (sdev->type =3D=3D ARPHRD_DLCI) && (sfr =3D sch->LINE_privdata) && - (sfr->master =3D=3D dev) && (sfr->dlci =3D=3D dlci)) { - skb->dev =3D sdev;=09 - if (ch->debug_flags & DEBUG_COMX_DLCI) { - comx_debug(dev, "Passing it to %s\n",sdev->name); - } - if (dev !=3D sdev) { - sch->stats.rx_packets++; - sch->stats.rx_bytes +=3D skb->len; - } - break; - } - } - switch(nlpid) { - case NLPID_IP: - skb->protocol =3D htons(ETH_P_IP); - skb->mac.raw =3D 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)=20 -{ - struct comx_channel *ch =3D dev->priv; - struct proc_dir_entry *dir =3D ch->procdir->parent->subdir; - struct net_device *sdev; - struct comx_channel *sch; - struct fr_data *sfr; - int cnt =3D 1; - - /* Ha minden igaz, 2 helyen fog allni a tbusy: a masternel,=20 - es annal a slave-nel aki eppen kuldott. - Egy helyen akkor all, ha a master kuldott. - Ez megint jo lesz majd, ha utemezni akarunk */ - =20 - /* This should be fixed, the slave tbusy should be set when=20 - the masters queue is full and reset when not */ - - for (; dir ; dir =3D dir->next) { - if(!S_ISDIR(dir->mode)) { - continue; - } - if ((sdev =3D dir->data) && (sch =3D sdev->priv) &&=20 - (sdev->type =3D=3D ARPHRD_DLCI) && (sfr =3D sch->LINE_privdata) && - (sfr->master =3D=3D 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 =3D dev->priv; - struct fr_data *fr =3D ch->LINE_privdata; - struct proc_dir_entry *dir =3D 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 |=3D PROTO_UP; - } - } else { - status &=3D ~(PROTO_UP | PROTO_LOOP); - } - - if (dev =3D=3D fr->master && fr->keepa_freq) { - if (status & LINE_UP) { - fr->keepa_timer.expires =3D jiffies + HZ; - add_timer(&fr->keepa_timer); - fr->keepalivecnt =3D MAXALIVECNT + 1; - fr->keeploopcnt =3D 0; - } else { - del_timer(&fr->keepa_timer); - } - } - =09 - /* Itt a status valtozast vegig kell vinni az osszes slave-n */ - for (; dir ; dir =3D dir->next) { - if(!S_ISDIR(dir->mode)) { - continue; - } -=09 - if ((sdev =3D dir->data) && (sch =3D sdev->priv) &&=20 - (sdev->type =3D=3D ARPHRD_FRAD || sdev->type =3D=3D ARPHRD_DLCI) &= &=20 - (sfr =3D sch->LINE_privdata) && (sfr->master =3D=3D dev)) { - if(status & LINE_UP) { - netif_wake_queue(sdev); - } - comx_status(sdev, status); - if(status & (PROTO_UP | PROTO_LOOP)) { - dev->flags |=3D IFF_RUNNING; - } else { - dev->flags &=3D ~IFF_RUNNING; - } - } - } -} - -static int fr_open(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D ch->LINE_privdata; - struct proc_dir_entry *comxdir =3D ch->procdir; - struct comx_channel *mch; - - if (!(ch->init_status & HW_OPEN)) { - return -ENODEV; - } - - if ((ch->hardware =3D=3D &fr_dlci && ch->protocol !=3D &fr_slave_protoc= ol) || - (ch->protocol =3D=3D &fr_slave_protocol && ch->hardware !=3D &fr_dl= ci)) { - printk(KERN_ERR "Trying to open an improperly set FR interface, giving= up\n"); - return -EINVAL; - } - - if (!fr->master) { - return -ENODEV; - } - mch =3D fr->master->priv; - if (fr->master !=3D dev && (!(mch->init_status & LINE_OPEN)=20 - || (mch->protocol !=3D &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 |=3D LINE_OPEN; - ch->line_status &=3D ~(PROTO_UP | PROTO_LOOP); - dev->flags &=3D ~IFF_RUNNING; - - if (fr->master =3D=3D dev) { - if (fr->keepa_freq) { - fr->keepa_timer.function =3D fr_keepalive_timerfun; - fr->keepa_timer.data =3D (unsigned long)dev; - add_timer(&fr->keepa_timer); - } else { - if (ch->line_status & LINE_UP) { - ch->line_status |=3D PROTO_UP; - dev->flags |=3D IFF_RUNNING; - } - } - } else { - ch->line_status =3D mch->line_status; - if(fr->master->flags & IFF_RUNNING) { - dev->flags |=3D IFF_RUNNING; - } - } - - for (; comxdir ; comxdir =3D comxdir->next) { - if (strcmp(comxdir->name, FILENAME_DLCI) =3D=3D 0 || - strcmp(comxdir->name, FILENAME_MASTER) =3D=3D 0 || - strcmp(comxdir->name, FILENAME_KEEPALIVE) =3D=3D 0) { - comxdir->mode =3D S_IFREG | 0444; - } - } -// comx_status(dev, ch->line_status); - return 0; -} - -static int fr_close(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D ch->LINE_privdata; - struct proc_dir_entry *comxdir =3D ch->procdir; - - if (fr->master =3D=3D dev) { // Ha master=20 - struct proc_dir_entry *dir =3D ch->procdir->parent->subdir; - struct net_device *sdev =3D 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); - } - =09 - for (; dir ; dir =3D dir->next) { - if(!S_ISDIR(dir->mode)) { - continue; - } - if ((sdev =3D dir->data) && (sch =3D sdev->priv) &&=20 - (sdev->type =3D=3D ARPHRD_DLCI) &&=20 - (sfr =3D sch->LINE_privdata) && - (sfr->master =3D=3D dev) &&=20 - (sch->init_status & LINE_OPEN)) { - dev_close(sdev); - } - } - } - - ch->init_status &=3D ~LINE_OPEN; - ch->line_status &=3D ~(PROTO_UP | PROTO_LOOP); - dev->flags &=3D ~IFF_RUNNING; - - for (; comxdir ; comxdir =3D comxdir->next) { - if (strcmp(comxdir->name, FILENAME_DLCI) =3D=3D 0 || - strcmp(comxdir->name, FILENAME_MASTER) =3D=3D 0 || - strcmp(comxdir->name, FILENAME_KEEPALIVE) =3D=3D 0) { - comxdir->mode =3D S_IFREG | 0444; - } - } - - return 0; -} - -static int fr_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct comx_channel *sch, *mch; - struct fr_data *fr =3D ch->LINE_privdata; - struct fr_data *sfr; - struct net_device *sdev; - struct proc_dir_entry *dir =3D ch->procdir->parent->subdir; - - if (!fr->master) { - printk(KERN_ERR "BUG: fr_xmit without a master!!! dev: %s\n", dev->nam= e); - return 0; - } - - mch =3D 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 !=3D fr->master) { - struct sk_buff *newskb=3Dskb_clone(skb, GFP_ATOMIC); - if (!newskb) - return -ENOMEM; - newskb->dev=3Dfr->master; - dev_queue_xmit(newskb); - ch->stats.tx_bytes +=3D skb->len; - ch->stats.tx_packets++; - dev_kfree_skb(skb); - } else { - netif_stop_queue(dev); - for (; dir ; dir =3D dir->next) { - if(!S_ISDIR(dir->mode)) { - continue; - } - if ((sdev =3D dir->data) && (sch =3D sdev->priv) &&=20 - (sdev->type =3D=3D ARPHRD_DLCI) && (sfr =3D sch->LINE_privdata) &= & - (sfr->master =3D=3D dev) && (netif_queue_stopped(sdev))) { - netif_stop_queue(sdev); - } - } - =09 - 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",=20 - dev->name, skb->len); - break; - } - } - return 0; -} - -static int fr_header(struct sk_buff *skb, struct net_device *dev,=20 - unsigned short type, void *daddr, void *saddr, unsigned len)=20 -{ - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D ch->LINE_privdata; - - skb_push(skb, dev->hard_header_len); =20 - /* Put in DLCI */ - skb->data[0] =3D (fr->dlci & (1024 - 15)) >> 2; - skb->data[1] =3D (fr->dlci & 15) << 4 | 1; // EA bit 1 - skb->data[2] =3D FRAD_UI; - skb->data[3] =3D NLPID_IP; - - return dev->hard_header_len; =20 -} - -static int fr_statistics(struct net_device *dev, char *page)=20 -{ - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D ch->LINE_privdata; - int len =3D 0; - - if (fr->master =3D=3D dev) { - struct proc_dir_entry *dir =3D ch->procdir->parent->subdir; - struct net_device *sdev; - struct comx_channel *sch; - struct fr_data *sfr; - int slaves =3D 0; - - len +=3D sprintf(page + len,=20 - "This is a Frame Relay master device\nSlaves: "); - for (; dir ; dir =3D dir->next) { - if(!S_ISDIR(dir->mode)) { - continue; - } - if ((sdev =3D dir->data) && (sch =3D sdev->priv) &&=20 - (sdev->type =3D=3D ARPHRD_DLCI) && - (sfr =3D sch->LINE_privdata) &&=20 - (sfr->master =3D=3D dev) && (sdev !=3D dev)) { - slaves++; - len +=3D sprintf(page + len, "%s ", sdev->name); - } - } - len +=3D sprintf(page + len, "%s\n", slaves ? "" : "(none)"); - if (fr->keepa_freq) { - len +=3D sprintf(page + len, "Line keepalive (value %d) " - "status %s [%d]\n", fr->keepa_freq,=20 - ch->line_status & PROTO_LOOP ? "LOOP" : - ch->line_status & PROTO_UP ? "UP" : "DOWN",=20 - fr->keepalivecnt); - } else { - len +=3D sprintf(page + len, "Line keepalive protocol " - "is not set\n"); - } - } else { // if slave - len +=3D sprintf(page + len,=20 - "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 =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D file->parent->data; - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D NULL; - int len =3D 0; - - if (ch) { - fr =3D ch->LINE_privdata; - } - - if (strcmp(file->name, FILENAME_DLCI) =3D=3D 0) { - len =3D sprintf(page, "%04d\n", fr->dlci); - } else if (strcmp(file->name, FILENAME_MASTER) =3D=3D 0) { - len =3D sprintf(page, "%-9s\n", fr->master ? fr->master->name : - "(none)"); - } else if (strcmp(file->name, FILENAME_KEEPALIVE) =3D=3D 0) { - len =3D fr->keepa_freq ? sprintf(page, "% 3d\n", fr->keepa_freq)=20 - : sprintf(page, "off\n"); - } else { - printk(KERN_ERR "comxfr: internal error, filename %s\n", file->name); - return -EBADF; - } - - if (off >=3D len) { - *eof =3D 1; - return 0; - } - - *start =3D page + off; - if (count >=3D len - off) *eof =3D 1; - return min_t(int, count, len - off); -} - -static int fr_write_proc(struct file *file, const char *buffer,=20 - u_long count, void *data) -{ - struct proc_dir_entry *entry =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D entry->parent->data; - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D NULL;=20 - char *page; - - if (ch) { - fr =3D ch->LINE_privdata; - } - - if (!(page =3D (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) =3D=3D '\n') { - *(page + count - 1) =3D 0; - } - - if (strcmp(entry->name, FILENAME_DLCI) =3D=3D 0) { - u16 dlci_new =3D simple_strtoul(page, NULL, 10); - - if (dlci_new > 1023) { - printk(KERN_ERR "Invalid DLCI value\n"); - } - else fr->dlci =3D dlci_new; - } else if (strcmp(entry->name, FILENAME_MASTER) =3D=3D 0) { - struct net_device *new_master =3D dev_get_by_name(page); - - if (new_master && new_master->type =3D=3D ARPHRD_FRAD) { - struct comx_channel *sch =3D new_master->priv; - struct fr_data *sfr =3D sch->LINE_privdata; - - if (sfr && sfr->master =3D=3D new_master) { - if(fr->master) - dev_put(fr->master); - fr->master =3D new_master; - /* Megorokli a master statuszat */ - ch->line_status =3D sch->line_status; - } - } - } else if (strcmp(entry->name, FILENAME_KEEPALIVE) =3D=3D 0) { - int keepa_new =3D -1; - - if (strcmp(page, KEEPALIVE_OFF) =3D=3D 0) { - keepa_new =3D 0; - } else { - keepa_new =3D 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 !=3D 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",=20 - entry->name); - count =3D -EBADF; - } - - free_page((unsigned long)page); - return count; -} - -static int fr_exit(struct net_device *dev)=20 -{ - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D ch->LINE_privdata; - struct net_device *sdev =3D dev; - struct comx_channel *sch; - struct fr_data *sfr; - struct proc_dir_entry *dir =3D ch->procdir->parent->subdir; - - /* Ha lezarunk egy master-t, le kell kattintani a slave-eket is */ - if (fr->master && fr->master =3D=3D dev) { - for (; dir ; dir =3D dir->next) { - if(!S_ISDIR(dir->mode)) { - continue; - } - if ((sdev =3D dir->data) && (sch =3D sdev->priv) &&=20 - (sdev->type =3D=3D ARPHRD_DLCI) &&=20 - (sfr =3D sch->LINE_privdata) && (sfr->master =3D=3D dev)) { - dev_close(sdev); - sfr->master =3D NULL; - } - } - } - dev->flags =3D 0; - dev->type =3D 0; - dev->mtu =3D 0; - dev->hard_header_len =3D 0; - - ch->LINE_rx =3D NULL; - ch->LINE_tx =3D NULL; - ch->LINE_status =3D NULL; - ch->LINE_open =3D NULL; - ch->LINE_close =3D NULL; - ch->LINE_xmit =3D NULL; - ch->LINE_header =3D NULL; - ch->LINE_rebuild_header =3D NULL; - ch->LINE_statistics =3D NULL; - - ch->LINE_status =3D 0; - - if (fr->master !=3D 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 =3D NULL; - - MOD_DEC_USE_COUNT; - return 0; -} - -static int fr_master_init(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr; - struct proc_dir_entry *new_file; - - if ((fr =3D ch->LINE_privdata =3D kmalloc(sizeof(struct fr_data),=20 - GFP_KERNEL)) =3D=3D NULL) { - return -ENOMEM; - } - memset(fr, 0, sizeof(struct fr_data)); - fr->master =3D dev; // this means master - fr->dlci =3D 0; // let's say default - - dev->flags =3D IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; - dev->type =3D ARPHRD_FRAD; - dev->mtu =3D 1500; - dev->hard_header_len =3D 4; =09 - dev->addr_len =3D 0; - - ch->LINE_rx =3D fr_rx; - ch->LINE_tx =3D fr_tx; - ch->LINE_status =3D fr_status; - ch->LINE_open =3D fr_open; - ch->LINE_close =3D fr_close; - ch->LINE_xmit =3D fr_xmit; - ch->LINE_header =3D fr_header; - ch->LINE_rebuild_header =3D NULL; - ch->LINE_statistics =3D fr_statistics; - - if ((new_file =3D create_proc_entry(FILENAME_DLCI, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_LINE_privdata; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &fr_read_proc; - new_file->write_proc =3D &fr_write_proc; - new_file->size =3D 5; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_KEEPALIVE, S_IFREG | 0644,= =20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_filename_dlci; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &fr_read_proc; - new_file->write_proc =3D &fr_write_proc; - new_file->size =3D 4; - new_file->nlink =3D 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 =3D dev->priv; - struct fr_data *fr; - struct proc_dir_entry *new_file; - - if ((fr =3D ch->LINE_privdata =3D kmalloc(sizeof(struct fr_data),=20 - GFP_KERNEL)) =3D=3D NULL) { - return -ENOMEM; - } - memset(fr, 0, sizeof(struct fr_data)); - - dev->flags =3D IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; - dev->type =3D ARPHRD_DLCI; - dev->mtu =3D 1500; - dev->hard_header_len =3D 4; =09 - dev->addr_len =3D 0; - - ch->LINE_rx =3D fr_rx; - ch->LINE_tx =3D fr_tx; - ch->LINE_status =3D fr_status; - ch->LINE_open =3D fr_open; - ch->LINE_close =3D fr_close; - ch->LINE_xmit =3D fr_xmit; - ch->LINE_header =3D fr_header; - ch->LINE_rebuild_header =3D NULL; - ch->LINE_statistics =3D fr_statistics; - - if ((new_file =3D create_proc_entry(FILENAME_DLCI, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_LINE_privdata; - } -=09 - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &fr_read_proc; - new_file->write_proc =3D &fr_write_proc; - new_file->size =3D 5; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_MASTER, S_IFREG | 0644,=20 - ch->procdir)) =3D=3D NULL) { - goto cleanup_filename_dlci; - } - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &fr_read_proc; - new_file->write_proc =3D &fr_write_proc; - new_file->size =3D 10; - new_file->nlink =3D 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 =3D dev->priv; - - ch->init_status |=3D HW_OPEN; - - MOD_INC_USE_COUNT; - return 0; -} - -static int dlci_close(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - - ch->init_status &=3D ~HW_OPEN; - - MOD_DEC_USE_COUNT; - return 0; -} - -static int dlci_txe(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct fr_data *fr =3D ch->LINE_privdata; - - if (!fr->master) { - return 0; - } - - ch =3D fr->master->priv; - fr =3D ch->LINE_privdata; - return ch->HW_txe(fr->master); -} - -static int dlci_statistics(struct net_device *dev, char *page)=20 -{ - return 0; -} - -static int dlci_init(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - - ch->HW_open =3D dlci_open; - ch->HW_close =3D dlci_close; - ch->HW_txe =3D dlci_txe; - ch->HW_statistics =3D dlci_statistics; - - /* Nincs egyeb hw info, mert ugyis a fr->master-bol fog minden kideruln= i */ - - MOD_INC_USE_COUNT; - return 0; -} - -static int dlci_exit(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - - ch->HW_open =3D NULL; - ch->HW_close =3D NULL; - ch->HW_txe =3D NULL; - ch->HW_statistics =3D 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 =3D { - .name =3D "frad",=20 - .version =3D VERSION, - .encap_type =3D ARPHRD_FRAD,=20 - .line_init =3D fr_master_init,=20 - .line_exit =3D fr_exit,=20 -}; - -static struct comx_protocol fr_slave_protocol =3D { - .name =3D "ietf-ip",=20 - .version =3D VERSION, - .encap_type =3D ARPHRD_DLCI,=20 - .line_init =3D fr_slave_init,=20 - .line_exit =3D fr_exit,=20 -}; - -static struct comx_hardware fr_dlci =3D {=20 - .name =3D "dlci",=20 - .version =3D VERSION, - .hw_init =3D dlci_init,=20 - .hw_exit =3D dlci_exit,=20 - .hw_dump =3D dlci_dump,=20 -}; - -static int __init comx_proto_fr_init(void) -{ - int ret;=20 - - if ((ret =3D comx_register_hardware(&fr_dlci))) { - return ret; - } - if ((ret =3D 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); =3D=3D=3D=3D=3D drivers/net/wan/comx-proto-lapb.c 1.12 vs edited =3D=3D=3D= =3D=3D --- 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=20 - * for Linux kernel 2.2.X - * - * Original author: Tivadar Szemethy - * Maintainer: Gergely Madarasz - * - * Copyright (C) 1997-1999 (C) ITConsult-Pro Co. - * - * 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. - *=20 - */ =20 -#define VERSION "0.80" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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)=20 -{ - if (!dev || !dev->priv) { - dev_kfree_skb(skb); - } else { - lapb_data_received(dev, skb); - } -} - -static int comxlapb_tx(struct net_device *dev)=20 -{ - netif_wake_queue(dev); - return 0; -} - -static int comxlapb_header(struct sk_buff *skb, struct net_device *dev,=20 - unsigned short type, void *daddr, void *saddr, unsigned len)=20 -{ - return dev->hard_header_len; =20 -} - -static void comxlapb_status(struct net_device *dev, unsigned short statu= s) -{ - struct comx_channel *ch; - - if (!dev || !(ch =3D 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 =3D dev->priv; - int err =3D 0; - - if (!(ch->init_status & HW_OPEN)) { - return -ENODEV; - } - - err =3D lapb_connect_request(dev); - - if (ch->debug_flags & DEBUG_COMX_LAPB) { - comx_debug(dev, "%s: lapb opened, error code: %d\n",=20 - dev->name, err); - } - - if (!err) { - ch->init_status |=3D LINE_OPEN; - MOD_INC_USE_COUNT; - } - return err; -} - -static int comxlapb_close(struct net_device *dev) -{ - struct comx_channel *ch =3D 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 &=3D ~LINE_OPEN; - ch->line_status &=3D ~PROTO_UP; - MOD_DEC_USE_COUNT; - return 0; -} - -static int comxlapb_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct sk_buff *skb2; - - if (!dev || !(ch =3D dev->priv) || !(dev->flags & (IFF_UP | IFF_RUNNING= ))) { - return -ENODEV; - } - - if (dev->type =3D=3D ARPHRD_X25) { // first byte tells what to do=20 - switch(skb->data[0]) { - case 0x00:=09 - break; // transmit - case 0x01:=09 - lapb_connect_request(dev); - kfree_skb(skb); - return 0; - case 0x02:=09 - lapb_disconnect_request(dev); - default: - kfree_skb(skb); - return 0; - } - skb_pull(skb,1); - } - - netif_stop_queue(dev); -=09 - if ((skb2 =3D skb_clone(skb, GFP_ATOMIC)) !=3D NULL) { - lapb_data_request(dev, skb2); - } - - return FRAME_ACCEPTED; -} - -static int comxlapb_statistics(struct net_device *dev, char *page)=20 -{ - struct lapb_parms_struct parms; - int len =3D 0; - - len +=3D sprintf(page + len, "Line status: "); - if (lapb_getparms(dev, &parms) !=3D LAPB_OK) { - len +=3D sprintf(page + len, "not initialized\n"); - return len; - } - len +=3D sprintf(page + len, "%s (%s), T1: %d/%d, T2: %d/%d, N2: %d/%d,= " - "window: %d\n", parms.mode & LAPB_DCE ? "DCE" : "DTE",=20 - parms.mode & LAPB_EXTENDED ? "EXTENDED" : "STANDARD", - parms.t1timer, parms.t1, parms.t2timer, parms.t2,=20 - parms.n2count, parms.n2, parms.window); - - return len; -} - -static int comxlapb_read_proc(char *page, char **start, off_t off, int c= ount, - int *eof, void *data) -{ - struct proc_dir_entry *file =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D file->parent->data; - struct lapb_parms_struct parms; - int len =3D 0; - - if (lapb_getparms(dev, &parms)) { - return -ENODEV; - } - - if (strcmp(file->name, FILENAME_T1) =3D=3D 0) { - len +=3D sprintf(page + len, "%02u / %02u\n",=20 - parms.t1timer, parms.t1); - } else if (strcmp(file->name, FILENAME_T2) =3D=3D 0) { - len +=3D sprintf(page + len, "%02u / %02u\n",=20 - parms.t2timer, parms.t2); - } else if (strcmp(file->name, FILENAME_N2) =3D=3D 0) { - len +=3D sprintf(page + len, "%02u / %02u\n",=20 - parms.n2count, parms.n2); - } else if (strcmp(file->name, FILENAME_WINDOW) =3D=3D 0) { - len +=3D sprintf(page + len, "%u\n", parms.window); - } else if (strcmp(file->name, FILENAME_MODE) =3D=3D 0) { - len +=3D sprintf(page + len, "%s, %s\n",=20 - 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 >=3D len) { - *eof =3D 1; - return 0; - } - - *start =3D page + off; - if (count >=3D len - off) { - *eof =3D 1; - } - return min_t(int, count, len - off); -} - -static int comxlapb_write_proc(struct file *file, const char *buffer,=20 - u_long count, void *data) -{ - struct proc_dir_entry *entry =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D entry->parent->data; - struct lapb_parms_struct parms; - unsigned long parm; - char *page; - - if (lapb_getparms(dev, &parms)) { - return -ENODEV; - } - - if (!(page =3D (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) =3D=3D '\n') { - *(page + count - 1) =3D 0; - } - - if (strcmp(entry->name, FILENAME_T1) =3D=3D 0) { - parm=3Dsimple_strtoul(page,NULL,10); - if (parm > 0 && parm < 100) { - parms.t1=3Dparm; - lapb_setparms(dev, &parms); - } - } else if (strcmp(entry->name, FILENAME_T2) =3D=3D 0) { - parm=3Dsimple_strtoul(page, NULL, 10); - if (parm > 0 && parm < 100) { - parms.t2=3Dparm; - lapb_setparms(dev, &parms); - } - } else if (strcmp(entry->name, FILENAME_N2) =3D=3D 0) { - parm=3Dsimple_strtoul(page, NULL, 10); - if (parm > 0 && parm < 100) { - parms.n2=3Dparm; - lapb_setparms(dev, &parms); - } - } else if (strcmp(entry->name, FILENAME_WINDOW) =3D=3D 0) { - parms.window =3D simple_strtoul(page, NULL, 10); - lapb_setparms(dev, &parms); - } else if (strcmp(entry->name, FILENAME_MODE) =3D=3D 0) { - if (comx_strcasecmp(page, "dte") =3D=3D 0) { - parms.mode &=3D ~(LAPB_DCE | LAPB_DTE);=20 - parms.mode |=3D LAPB_DTE; - } else if (comx_strcasecmp(page, "dce") =3D=3D 0) { - parms.mode &=3D ~(LAPB_DTE | LAPB_DCE);=20 - parms.mode |=3D LAPB_DCE; - } else if (comx_strcasecmp(page, "std") =3D=3D 0 ||=20 - comx_strcasecmp(page, "standard") =3D=3D 0) { - parms.mode &=3D ~LAPB_EXTENDED;=20 - parms.mode |=3D LAPB_STANDARD; - } else if (comx_strcasecmp(page, "ext") =3D=3D 0 ||=20 - comx_strcasecmp(page, "extended") =3D=3D 0) { - parms.mode &=3D ~LAPB_STANDARD;=20 - parms.mode |=3D LAPB_EXTENDED; - } - lapb_setparms(dev, &parms); - } else { - printk(KERN_ERR "comxlapb_write_proc: internal error, filename %s\n",=20 - 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 =3D dev->priv;=20 - struct proc_dir_entry *comxdir =3D ch->procdir->subdir; - - if (ch->debug_flags & DEBUG_COMX_LAPB) { - comx_debug(ch->dev, "%s: lapb connected, reason: %d\n",=20 - ch->dev->name, reason); - } - - if (ch->dev->type =3D=3D ARPHRD_X25) { - unsigned char *p; - struct sk_buff *skb; - - if ((skb =3D dev_alloc_skb(1)) =3D=3D NULL) { - printk(KERN_ERR "comxlapb: out of memory!\n"); - return; - } - p =3D skb_put(skb,1); - *p =3D 0x01; // link established - skb->dev =3D ch->dev; - skb->protocol =3D htons(ETH_P_X25); - skb->mac.raw =3D skb->data; - skb->pkt_type =3D PACKET_HOST; - - netif_rx(skb); - ch->dev->last_rx =3D jiffies; - } - - for (; comxdir; comxdir =3D comxdir->next) { - if (strcmp(comxdir->name, FILENAME_MODE) =3D=3D 0) { - comxdir->mode =3D S_IFREG | 0444; - } - } - - - ch->line_status |=3D PROTO_UP; - comx_status(ch->dev, ch->line_status); -} - -static void comxlapb_disconnected(struct net_device *dev, int reason) -{ - struct comx_channel *ch =3D dev->priv;=20 - struct proc_dir_entry *comxdir =3D ch->procdir->subdir; - - if (ch->debug_flags & DEBUG_COMX_LAPB) { - comx_debug(ch->dev, "%s: lapb disconnected, reason: %d\n",=20 - ch->dev->name, reason); - } - - if (ch->dev->type =3D=3D ARPHRD_X25) { - unsigned char *p; - struct sk_buff *skb; - - if ((skb =3D dev_alloc_skb(1)) =3D=3D NULL) { - printk(KERN_ERR "comxlapb: out of memory!\n"); - return; - } - p =3D skb_put(skb,1); - *p =3D 0x02; // link disconnected - skb->dev =3D ch->dev; - skb->protocol =3D htons(ETH_P_X25); - skb->mac.raw =3D skb->data; - skb->pkt_type =3D PACKET_HOST; - - netif_rx(skb); - ch->dev->last_rx =3D jiffies; - } - - for (; comxdir; comxdir =3D comxdir->next) { - if (strcmp(comxdir->name, FILENAME_MODE) =3D=3D 0) { - comxdir->mode =3D S_IFREG | 0644; - } - } -=09 - ch->line_status &=3D ~PROTO_UP; - comx_status(ch->dev, ch->line_status); -} - -static int comxlapb_data_indication(struct net_device *dev, struct sk_bu= ff *skb) -{ - struct comx_channel *ch =3D dev->priv;=20 - - if (ch->dev->type =3D=3D ARPHRD_X25) { - skb_push(skb, 1); - - if (skb_cow(skb, 1)) - return NET_RX_DROP; - - skb->data[0] =3D 0; // indicate data for X25 - skb->protocol =3D htons(ETH_P_X25); - } else { - skb->protocol =3D htons(ETH_P_IP); - } - - skb->dev =3D ch->dev; - skb->mac.raw =3D skb->data; - return comx_rx(ch->dev, skb); -} - -static void comxlapb_data_transmit(struct net_device *dev, struct sk_buf= f *skb) -{ - struct comx_channel *ch =3D dev->priv;=20 - - if (ch->HW_send_packet) { - ch->HW_send_packet(ch->dev, skb); - } -} - -static int comxlapb_exit(struct net_device *dev)=20 -{ - struct comx_channel *ch =3D dev->priv; - - dev->flags =3D 0; - dev->type =3D 0; - dev->mtu =3D 0; - dev->hard_header_len =3D 0; - - ch->LINE_rx =3D NULL; - ch->LINE_tx =3D NULL; - ch->LINE_status =3D NULL; - ch->LINE_open =3D NULL; - ch->LINE_close =3D NULL; - ch->LINE_xmit =3D NULL; - ch->LINE_header =3D NULL; - ch->LINE_statistics =3D 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 =3D dev->priv; - struct lapb_register_struct lapbreg; - - dev->mtu =3D 1500; - dev->hard_header_len =3D 4; - dev->addr_len =3D 0; - - ch->LINE_rx =3D comxlapb_rx; - ch->LINE_tx =3D comxlapb_tx; - ch->LINE_status =3D comxlapb_status; - ch->LINE_open =3D comxlapb_open; - ch->LINE_close =3D comxlapb_close; - ch->LINE_xmit =3D comxlapb_xmit; - ch->LINE_header =3D comxlapb_header; - ch->LINE_statistics =3D comxlapb_statistics; - - lapbreg.connect_confirmation =3D comxlapb_connected; - lapbreg.connect_indication =3D comxlapb_connected; - lapbreg.disconnect_confirmation =3D comxlapb_disconnected; - lapbreg.disconnect_indication =3D comxlapb_disconnected; - lapbreg.data_indication =3D comxlapb_data_indication; - lapbreg.data_transmit =3D 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)=20 -{ - dev->flags =3D IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; - dev->type =3D ARPHRD_LAPB; - - return(comxlapb_init(dev)); -} - -static int comxlapb_init_x25(struct net_device *dev) -{ - dev->flags =3D IFF_NOARP; - dev->type =3D 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 =3D create_proc_entry(name, S_IFREG | mode, dir)) !=3D NU= LL) { - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &comxlapb_read_proc; - new_file->write_proc =3D &comxlapb_write_proc; - new_file->size =3D size; - new_file->nlink =3D 1; - } - return(new_file); -} - -static struct comx_protocol comxlapb_protocol =3D { - "lapb",=20 - VERSION, - ARPHRD_LAPB,=20 - comxlapb_init_lapb,=20 - comxlapb_exit,=20 - NULL=20 -}; - -static struct comx_protocol comx25_protocol =3D { - "x25",=20 - VERSION, - ARPHRD_X25,=20 - comxlapb_init_x25,=20 - comxlapb_exit,=20 - NULL=20 -}; - -static int __init comx_proto_lapb_init(void) -{ - int ret; - - if ((ret =3D comx_register_protocol(&comxlapb_protocol)) !=3D 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"); =3D=3D=3D=3D=3D drivers/net/wan/comx-proto-ppp.c 1.6 vs edited =3D=3D=3D=3D= =3D --- 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 - * - * based on skeleton code by Tivadar Szemethy - * - * Copyright (C) 1999 ITConsult-Pro Co. - * - * 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=20 - * - 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 - *=20 - * Version 0.23 (99/12/02): - * - tbusy fixes - * - */ =20 -#define VERSION "0.23" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "comx.h" - -MODULE_AUTHOR("Author: Gergely Madarasz "); -MODULE_DESCRIPTION("Cisco-HDLC / Synchronous PPP driver for the COMX syn= c 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=3D(struct net_device *)d; - struct comx_channel *ch=3Ddev->priv; - struct syncppp_data *spch=3Dch->LINE_privdata; - struct sppp *sp =3D (struct sppp *)sppp_of(dev); - =20 - if(!(ch->line_status & PROTO_UP) &&=20 - (sp->pp_link_state=3D=3DSPPP_LINK_UP)) { - comx_status(dev, ch->line_status | PROTO_UP); - } - if((ch->line_status & PROTO_UP) && - (sp->pp_link_state=3D=3DSPPP_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)=20 -{ - struct comx_channel *ch=3Ddev->priv; -=09 - if(ch->line_status & LINE_UP) { - netif_wake_queue(dev); - } - return 0; -} - -static void syncppp_status(struct net_device *dev, unsigned short status= ) -{ - status &=3D ~(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 =3D dev->priv; - struct syncppp_data *spch =3D ch->LINE_privdata; - - if (!(ch->init_status & HW_OPEN)) return -ENODEV; - - ch->init_status |=3D LINE_OPEN; - ch->line_status &=3D ~(PROTO_UP | PROTO_LOOP); - - if(ch->line_status & LINE_UP) { - sppp_open(dev); - } - - init_timer(&spch->status_timer); - spch->status_timer.function=3Dsyncppp_status_timerfun; - spch->status_timer.data=3D(unsigned long)dev; - spch->status_timer.expires=3Djiffies + HZ*3; - add_timer(&spch->status_timer); -=09 - return 0; -} - -static int syncppp_close(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct syncppp_data *spch =3D ch->LINE_privdata; - - if (!(ch->init_status & HW_OPEN)) return -ENODEV; - del_timer(&spch->status_timer); -=09 - sppp_close(dev); - - ch->init_status &=3D ~LINE_OPEN; - ch->line_status &=3D ~(PROTO_UP | PROTO_LOOP); - - return 0; -} - -static int syncppp_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct comx_channel *ch =3D 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",=20 - dev->name, skb->len); - break; - } - return 0; -} - - -static int syncppp_statistics(struct net_device *dev, char *page)=20 -{ - int len =3D 0; - - len +=3D sprintf(page + len, " "); - return len; -} - - -static int syncppp_exit(struct net_device *dev)=20 -{ - struct comx_channel *ch =3D dev->priv; - - sppp_detach(dev); - - dev->flags =3D 0; - dev->type =3D 0; - dev->mtu =3D 0; - - ch->LINE_rx =3D NULL; - ch->LINE_tx =3D NULL; - ch->LINE_status =3D NULL; - ch->LINE_open =3D NULL; - ch->LINE_close =3D NULL; - ch->LINE_xmit =3D NULL; - ch->LINE_header =3D NULL; - ch->LINE_rebuild_header =3D NULL; - ch->LINE_statistics =3D NULL; - - kfree(ch->LINE_privdata); - ch->LINE_privdata =3D NULL; - - MOD_DEC_USE_COUNT; - return 0; -} - -static int syncppp_init(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct ppp_device *pppdev =3D (struct ppp_device *)ch->if_ptr; - - ch->LINE_privdata =3D kmalloc(sizeof(struct syncppp_data), GFP_KERNEL); - if (!ch->LINE_privdata) - return -ENOMEM; - - pppdev->dev =3D dev; - sppp_attach(pppdev); - - if(ch->protocol =3D=3D &hdlc_protocol) { - pppdev->sppp.pp_flags |=3D PP_CISCO; - dev->type =3D ARPHRD_HDLC; - } else { - pppdev->sppp.pp_flags &=3D ~PP_CISCO; - dev->type =3D ARPHRD_PPP; - } - - ch->LINE_rx =3D sppp_input; - ch->LINE_tx =3D syncppp_tx; - ch->LINE_status =3D syncppp_status; - ch->LINE_open =3D syncppp_open; - ch->LINE_close =3D syncppp_close; - ch->LINE_xmit =3D syncppp_xmit; - ch->LINE_header =3D NULL; - ch->LINE_statistics =3D syncppp_statistics; - - - MOD_INC_USE_COUNT; - return 0; -} - -static struct comx_protocol syncppp_protocol =3D { - "ppp",=20 - VERSION, - ARPHRD_PPP,=20 - syncppp_init,=20 - syncppp_exit,=20 - NULL=20 -}; - -static struct comx_protocol hdlc_protocol =3D { - "hdlc",=20 - VERSION, - ARPHRD_PPP,=20 - syncppp_init,=20 - syncppp_exit,=20 - NULL=20 -}; - -static int __init comx_proto_ppp_init(void) -{ - int ret; - - ret =3D comx_register_protocol(&hdlc_protocol); - if (!ret) { - ret =3D 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); =3D=3D=3D=3D=3D drivers/net/wan/comx.c 1.23 vs edited =3D=3D=3D=3D=3D --- 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 board= s - *=20 - * for Linux kernel 2.2.X / 2.4.X - * - * Original authors: Arpad Bakay , - * Peter Bajan , - * Previous maintainer: Tivadar Szemethy - * Current maintainer: Gergely Madarasz - * - * Copyright (C) 1995-1999 ITConsult-Pro Co. - * - * Contributors: - * Arnaldo Carvalho de Melo (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=20 - * /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. - */ =20 -#define VERSION "0.85" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_KMOD -#include -#endif - -#ifndef CONFIG_PROC_FS -#error For now, COMX really needs the /proc filesystem -#endif - -#include -#include "comx.h" - -MODULE_AUTHOR("Gergely Madarasz "); -MODULE_DESCRIPTION("Common code for the COMX synchronous serial adapters= "); -MODULE_LICENSE("GPL"); - -static struct comx_hardware *comx_channels =3D NULL; -static struct comx_protocol *comx_lines =3D 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 *, struc= t nameidata *); - -static struct inode_operations comx_root_inode_ops =3D { - .lookup =3D comx_lookup, - .mkdir =3D comx_mkdir, - .rmdir =3D comx_rmdir, -}; - -static int comx_delete_dentry(struct dentry *dentry); -static struct proc_dir_entry *create_comx_proc_entry(char *name, int mod= e, - int size, struct proc_dir_entry *dir); - -static struct dentry_operations comx_dentry_operations =3D { - .d_delete =3D comx_delete_dentry, -}; - - -static struct proc_dir_entry * comx_root_dir; - -struct comx_debugflags_struct comx_debugflags[] =3D { - { "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 }=20 -}; - - -int comx_debug(struct net_device *dev, char *fmt, ...) -{ - struct comx_channel *ch =3D dev->priv; - char *page,*str; - va_list args; - int len; - - if (!ch->debug_area) return 0; - - if (!(page =3D (char *)__get_free_page(GFP_ATOMIC))) return -ENOMEM; - - va_start(args, fmt); - len =3D vsprintf(str =3D page, fmt, args); - va_end(args); - - if (len >=3D PAGE_SIZE) { - printk(KERN_ERR "comx_debug: PANIC! len =3D %d !!!\n", len); - free_page((unsigned long)page); - return -EINVAL; - } - - while (len) { - int to_copy; - int free =3D (ch->debug_start - ch->debug_end + ch->debug_size)=20 - % ch->debug_size; - - to_copy =3D min_t(int, free ? free : ch->debug_size,=20 - min_t(int, ch->debug_size - ch->debug_end, len)); - memcpy(ch->debug_area + ch->debug_end, str, to_copy); - str +=3D to_copy; - len -=3D to_copy; - ch->debug_end =3D (ch->debug_end + to_copy) % ch->debug_size; - if (ch->debug_start =3D=3D ch->debug_end) // Full ? push start away - ch->debug_start =3D (ch->debug_start + len + 1) %=20 - ch->debug_size; - ch->debug_file->size =3D (ch->debug_end - ch->debug_start + - ch->debug_size) % ch->debug_size; - }=20 - - free_page((unsigned long)page); - return 0; -} - -int comx_debug_skb(struct net_device *dev, struct sk_buff *skb, char *ms= g) -{ - struct comx_channel *ch =3D 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 l= en,=20 - char *msg) -{ - int pos =3D 0; - struct comx_channel *ch =3D dev->priv; - - if (!ch->debug_area) return 0; - - comx_debug(dev, "%s: %s len %d\n", dev->name, msg, len); - - while (pos !=3D len) { - char line[80]; - int i =3D 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",=20 - isprint(bytes[pos]) ? bytes[pos] : '.'); - pos++; - } while (pos !=3D len && pos % 16); - - while ( i++ !=3D 78 ) if (line[i] =3D=3D 0) line[i] =3D ' '; - line[77] =3D '\n'; - line[78] =3D 0; -=09 - comx_debug(dev, "%s", line); - } - comx_debug(dev, "\n"); - return 0; -} - -static void comx_loadavg_timerfun(unsigned long d) -{ - struct net_device *dev =3D (struct net_device *)d; - struct comx_channel *ch =3D dev->priv; - - ch->avg_bytes[ch->loadavg_counter] =3D ch->current_stats->rx_bytes; - ch->avg_bytes[ch->loadavg_counter + ch->loadavg_size] =3D=20 - ch->current_stats->tx_bytes; - - ch->loadavg_counter =3D (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) -{=20 - struct net_device *dev =3D (struct net_device *)d; - struct comx_channel *ch =3D 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 =20 - -static int comx_open(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - struct proc_dir_entry *comxdir =3D ch->procdir->subdir; - int ret=3D0; - - if (!ch->protocol || !ch->hardware) return -ENODEV; - - if ((ret =3D ch->HW_open(dev))) return ret; - if ((ret =3D ch->LINE_open(dev))) {=20 - ch->HW_close(dev);=20 - return ret;=20 - }; - - for (; comxdir ; comxdir =3D comxdir->next) { - if (strcmp(comxdir->name, FILENAME_HARDWARE) =3D=3D 0 || - strcmp(comxdir->name, FILENAME_PROTOCOL) =3D=3D 0) - comxdir->mode =3D S_IFREG | 0444; - } - -#if 0 - ch->reset_pending =3D 1; - ch->reset_timeout =3D 30; - ch->reset_timer.function =3D comx_reset_timerfun; - ch->reset_timer.data =3D (unsigned long)dev; - ch->reset_timer.expires =3D 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 =3D dev->priv; - struct proc_dir_entry *comxdir =3D ch->procdir->subdir; - int ret =3D -ENODEV; - - if (test_and_clear_bit(0, &ch->lineup_pending)) { - del_timer(&ch->lineup_timer); - } - -#if 0=09 - del_timer(&ch->reset_timer); -#endif - - if (ch->init_status & LINE_OPEN && ch->protocol && ch->LINE_close) { - ret =3D ch->LINE_close(dev); - } - - if (ret) return ret; - - if (ch->init_status & HW_OPEN && ch->hardware && ch->HW_close) { - ret =3D ch->HW_close(dev); - } -=09 - ch->line_status=3D0; - - for (; comxdir ; comxdir =3D comxdir->next) { - if (strcmp(comxdir->name, FILENAME_HARDWARE) =3D=3D 0 || - strcmp(comxdir->name, FILENAME_PROTOCOL) =3D=3D 0) - comxdir->mode =3D S_IFREG | 0644; - } - - return ret; -} - -void comx_status(struct net_device *dev, int status) -{ - struct comx_channel *ch =3D 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",=20 - status & PROTO_LOOP ? "LOOP" : status & PROTO_UP ?=20 - "UP" : "DOWN"); -=09 - ch->line_status =3D status; -} - -static int comx_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct comx_channel *ch =3D 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->nam= e, - (int)skb->len, dev->mtu); - } -=09 - if (ch->debug_flags & DEBUG_COMX_TX) { - comx_debug_skb(dev, skb, "comx_xmit skb"); - } -=09 - rc=3Dch->LINE_xmit(skb, dev); -// if (!rc) dev_kfree_skb(skb); - - return rc; -} - -static int comx_header(struct sk_buff *skb, struct net_device *dev,=20 - unsigned short type, void *daddr, void *saddr, unsigned len)=20 -{ - struct comx_channel *ch =3D 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)=20 -{ - struct net_device *dev =3D skb->dev; - struct comx_channel *ch =3D 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 =3D 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 =3D jiffies; - } - return 0; -} - -static struct net_device_stats *comx_stats(struct net_device *dev) -{ - struct comx_channel *ch =3D dev->priv; - - return ch->current_stats; -} - -void comx_lineup_func(unsigned long d) -{ - struct net_device *dev =3D (struct net_device *)d; - struct comx_channel *ch =3D dev->priv; - - del_timer(&ch->lineup_timer); - clear_bit(0, &ch->lineup_pending); - - if (ch->LINE_status) { - ch->LINE_status(dev, ch->line_status |=3D 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 =3D dev->priv; - int len =3D 0; - int tmp; - int i =3D 0; - char tmpstr[20]; - int tmpstrlen =3D 0; - - len +=3D sprintf(page + len, "Interface administrative status is %s, " - "modem status is %s, protocol is %s\n",=20 - dev->flags & IFF_UP ? "UP" : "DOWN", - ch->line_status & LINE_UP ? "UP" : "DOWN", - ch->line_status & PROTO_LOOP ? "LOOP" :=20 - ch->line_status & PROTO_UP ? "UP" : "DOWN"); - len +=3D sprintf(page + len, "Modem status changes: %lu, Transmitter st= atus " - "is %s, tbusy: %d\n", ch->current_stats->tx_carrier_errors, ch->HW_txe= ?=20 - ch->HW_txe(dev) ? "IDLE" : "BUSY" : "NOT READY", netif_running(dev)); - len +=3D sprintf(page + len, "Interface load (input): %d / %d / %d bits= /s (", - LOADAVG(0,0), LOADAVG(1, 0), LOADAVG(2, 0)); - tmpstr[0] =3D 0; - for (i=3D0; i !=3D 3; i++) { - char tf; - - tf =3D ch->loadavg[i] % 60 =3D=3D 0 &&=20 - ch->loadavg[i] / 60 > 0 ? 'm' : 's'; - tmpstrlen +=3D sprintf(tmpstr + tmpstrlen, "%d%c%s",=20 - ch->loadavg[i] / (tf =3D=3D 'm' ? 60 : 1), tf,=20 - i =3D=3D 2 ? ")\n" : "/"); - } - len +=3D sprintf(page + len,=20 - "%s (output): %d / %d / %d bits/s (%s", tmpstr,=20 - LOADAVG(0,ch->loadavg_size), LOADAVG(1, ch->loadavg_size),=20 - LOADAVG(2, ch->loadavg_size), tmpstr); - - len +=3D sprintf(page + len, "Debug flags: "); - tmp =3D len; i =3D 0; - while (comx_debugflags[i].name) { - if (ch->debug_flags & comx_debugflags[i].value)=20 - len +=3D sprintf(page + len, "%s ",=20 - comx_debugflags[i].name); - i++; - } - len +=3D sprintf(page + len, "%s\n", tmp =3D=3D len ? "none" : ""); - - len +=3D 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= ,=20 - ch->current_stats->rx_crc_errors, ch->current_stats->rx_frame_errors,=20 - 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 +=3D ch->LINE_statistics(dev, page + len); - } else { - len +=3D sprintf(page+len, "Line status: driver not initialized\n"); - } - if (ch->HW_statistics && (ch->init_status & HW_OPEN)) { - len +=3D ch->HW_statistics(dev, page + len); - } else { - len +=3D 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 =3D 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 =3D comx_open; - dev->stop =3D comx_close; - dev->hard_start_xmit =3D comx_xmit; - dev->hard_header =3D comx_header; - dev->rebuild_header =3D comx_rebuild_header; - dev->get_stats =3D comx_stats; - dev->do_ioctl =3D comx_ioctl; - dev->change_mtu =3D NULL; - dev->tx_queue_len =3D 20; - dev->flags =3D IFF_NOARP; -} - -static int comx_init_dev(struct net_device *dev) -{ - struct comx_channel *ch; - - if ((ch =3D kmalloc(sizeof(struct comx_channel), GFP_KERNEL)) =3D=3D NU= LL) { - return -ENOMEM; - } - memset(ch, 0, sizeof(struct comx_channel)); - - ch->loadavg[0] =3D 5; - ch->loadavg[1] =3D 300; - ch->loadavg[2] =3D 900; - ch->loadavg_size =3D ch->loadavg[2] / ch->loadavg[0] + 1;=20 - if ((ch->avg_bytes =3D kmalloc(ch->loadavg_size *=20 - sizeof(unsigned long) * 2, GFP_KERNEL)) =3D=3D NULL) { - kfree(ch); - return -ENOMEM; - } - - memset(ch->avg_bytes, 0, ch->loadavg_size * sizeof(unsigned long) * 2); - ch->loadavg_counter =3D 0; - ch->loadavg_timer.function =3D comx_loadavg_timerfun; - ch->loadavg_timer.data =3D (unsigned long)dev; - ch->loadavg_timer.expires =3D jiffies + HZ * ch->loadavg[0]; - add_timer(&ch->loadavg_timer); - - dev->priv =3D (void *)ch; - ch->dev =3D dev; - ch->line_status &=3D ~LINE_UP; - - ch->current_stats =3D &ch->stats; - - comx_reset_dev(dev); - return 0; -} - -static int comx_read_proc(char *page, char **start, off_t off, int count= ,=20 - int *eof, void *data) -{ - struct proc_dir_entry *file =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D file->parent->data; - struct comx_channel *ch =3D dev->priv; - int len =3D 0; - - if (strcmp(file->name, FILENAME_STATUS) =3D=3D 0) { - len =3D comx_statistics(dev, page); - } else if (strcmp(file->name, FILENAME_HARDWARE) =3D=3D 0) { - len =3D sprintf(page, "%s\n", ch->hardware ?=20 - ch->hardware->name : HWNAME_NONE); - } else if (strcmp(file->name, FILENAME_PROTOCOL) =3D=3D 0) { - len =3D sprintf(page, "%s\n", ch->protocol ?=20 - ch->protocol->name : PROTONAME_NONE); - } else if (strcmp(file->name, FILENAME_LINEUPDELAY) =3D=3D 0) { - len =3D sprintf(page, "%01d\n", ch->lineup_delay); - } - - if (off >=3D len) { - *eof =3D 1; - return 0; - } - - *start =3D page + off; - if (count >=3D len - off) { - *eof =3D 1; - } - return min_t(int, count, len - off); -} - - -static int comx_root_read_proc(char *page, char **start, off_t off, int = count,=20 - int *eof, void *data) -{ - struct proc_dir_entry *file =3D (struct proc_dir_entry *)data; - struct comx_hardware *hw; - struct comx_protocol *line; - - int len =3D 0; - - if (strcmp(file->name, FILENAME_HARDWARELIST) =3D=3D 0) { - for(hw=3Dcomx_channels;hw;hw=3Dhw->next)=20 - len+=3Dsprintf(page+len, "%s\n", hw->name); - } else if (strcmp(file->name, FILENAME_PROTOCOLLIST) =3D=3D 0) { - for(line=3Dcomx_lines;line;line=3Dline->next) - len+=3Dsprintf(page+len, "%s\n", line->name); - } - - if (off >=3D len) { - *eof =3D 1; - return 0; - } - - *start =3D page + off; - if (count >=3D len - off) { - *eof =3D 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 =3D (struct proc_dir_entry *)data; - struct net_device *dev =3D (struct net_device *)entry->parent->data; - struct comx_channel *ch =3D dev->priv; - char *page; - struct comx_hardware *hw =3D comx_channels; - struct comx_protocol *line =3D comx_lines; - int ret=3D0; - - if (count > PAGE_SIZE) { - printk(KERN_ERR "count is %lu > %d!!!\n", count, (int)PAGE_SIZE); - return -ENOSPC; - } - - if (!(page =3D (char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; - - if(copy_from_user(page, buffer, count)) - { - count =3D -EFAULT; - goto out; - } - - if (page[count-1] =3D=3D '\n') - page[count-1] =3D '\0'; - else if (count < PAGE_SIZE) - page[count] =3D '\0'; - else if (page[count]) { - count =3D -EINVAL; - goto out; - } - - if (strcmp(entry->name, FILENAME_DEBUG) =3D=3D 0) { - int i; - int ret =3D 0; - - if ((i =3D simple_strtoul(page, NULL, 10)) !=3D 0) { - unsigned long flags; - - save_flags(flags); cli(); - if (ch->debug_area) kfree(ch->debug_area); - if ((ch->debug_area =3D kmalloc(ch->debug_size =3D i,=20 - GFP_KERNEL)) =3D=3D NULL) { - ret =3D -ENOMEM; - } - ch->debug_start =3D ch->debug_end =3D 0; - restore_flags(flags); - free_page((unsigned long)page); - return ret ? ret : count; - } - =09 - if (*page !=3D '+' && *page !=3D '-') { - free_page((unsigned long)page); - return -EINVAL; - } - while (comx_debugflags[i].value &&=20 - strncmp(comx_debugflags[i].name, page + 1,=20 - strlen(comx_debugflags[i].name))) { - i++; - } -=09 - if (comx_debugflags[i].value =3D=3D 0) { - printk(KERN_ERR "Invalid debug option\n"); - free_page((unsigned long)page); - return -EINVAL; - } - if (*page =3D=3D '+') { - ch->debug_flags |=3D comx_debugflags[i].value; - } else { - ch->debug_flags &=3D ~comx_debugflags[i].value; - } - } else if (strcmp(entry->name, FILENAME_HARDWARE) =3D=3D 0) { - if(strlen(page)>10) { - free_page((unsigned long)page); - return -EINVAL; - } - while (hw) {=20 - if (strcmp(hw->name, page) =3D=3D 0) { - break; - } else { - hw =3D hw->next; - } - } -#ifdef CONFIG_KMOD - if(!hw && comx_strcasecmp(HWNAME_NONE,page) !=3D 0){ - request_module("comx-hw-%s",page); - } =09 - hw=3Dcomx_channels; - while (hw) { - if (comx_strcasecmp(hw->name, page) =3D=3D 0) { - break; - } else { - hw =3D hw->next; - } - } -#endif - - if (comx_strcasecmp(HWNAME_NONE, page) !=3D 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 &&=20 - (ret=3Dch->hardware->hw_exit(dev))) { - free_page((unsigned long)page); - return ret; - } - ch->hardware =3D hw; - entry->size =3D strlen(page) + 1; - if (hw && hw->hw_init) hw->hw_init(dev); - } else if (strcmp(entry->name, FILENAME_PROTOCOL) =3D=3D 0) { - if(strlen(page)>10) { - free_page((unsigned long)page); - return -EINVAL; - } - while (line) { - if (comx_strcasecmp(line->name, page) =3D=3D 0) { - break; - } else { - line =3D line->next; - } - } -#ifdef CONFIG_KMOD - if(!line && comx_strcasecmp(PROTONAME_NONE, page) !=3D 0) { - request_module("comx-proto-%s",page); - } =09 - line=3Dcomx_lines; - while (line) { - if (comx_strcasecmp(line->name, page) =3D=3D 0) { - break; - } else { - line =3D line->next; - } - } -#endif - =09 - if (comx_strcasecmp(PROTONAME_NONE, page) !=3D 0 && !line) { - free_page((unsigned long)page); - return -ENODEV; - } - =09 - if (ch->init_status & LINE_OPEN) { - free_page((unsigned long)page); - return -EBUSY; - } - =09 - if (ch->protocol && ch->protocol->line_exit &&=20 - (ret=3Dch->protocol->line_exit(dev))) { - free_page((unsigned long)page); - return ret; - } - ch->protocol =3D line; - entry->size =3D strlen(page) + 1; - comx_reset_dev(dev); - if (line && line->line_init) line->line_init(dev); - } else if (strcmp(entry->name, FILENAME_LINEUPDELAY) =3D=3D 0) { - int i; - - if ((i =3D simple_strtoul(page, NULL, 10)) !=3D 0) { - if (i >=3D0 && i < 10) {=20 - ch->lineup_delay =3D i;=20 - } 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 =3D -EIO; - - if ((dev =3D kmalloc(sizeof(struct net_device), GFP_KERNEL)) =3D=3D NUL= L) { - return -ENOMEM; - } - memset(dev, 0, sizeof(struct net_device)); - - lock_kernel(); - if ((new_dir =3D create_proc_entry(dentry->d_name.name, mode | S_IFDIR,= =20 - comx_root_dir)) =3D=3D NULL) { - goto cleanup_dev; - } - - new_dir->nlink =3D 2; - new_dir->data =3D NULL; // ide jon majd a struct dev - - /* Ezek kellenek */ - if (!create_comx_proc_entry(FILENAME_HARDWARE, 0644,=20 - strlen(HWNAME_NONE) + 1, new_dir)) { - goto cleanup_new_dir; - } - if (!create_comx_proc_entry(FILENAME_PROTOCOL, 0644,=20 - 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 =3D create_proc_entry(FILENAME_DEBUG,=20 - S_IFREG | 0644, new_dir)) =3D=3D NULL) { - goto cleanup_filename_lineupdelay; - } - debug_file->data =3D (void *)debug_file;=20 - debug_file->read_proc =3D NULL; // see below - debug_file->write_proc =3D &comx_write_proc; - debug_file->nlink =3D 1; - - strcpy(dev->name, (char *)new_dir->name); - dev->init =3D comx_init_dev; - - if (register_netdevice(dev)) { - goto cleanup_filename_debug; - } - ch =3D dev->priv; - if((ch->if_ptr =3D (void *)kmalloc(sizeof(struct ppp_device),=20 - GFP_KERNEL)) =3D=3D NULL) { - goto cleanup_register; - } - memset(ch->if_ptr, 0, sizeof(struct ppp_device)); - ch->debug_file =3D debug_file;=20 - ch->procdir =3D new_dir; - new_dir->data =3D dev; - - ch->debug_start =3D ch->debug_end =3D 0; - if ((ch->debug_area =3D kmalloc(ch->debug_size =3D DEFAULT_DEBUG_SIZE,=20 - GFP_KERNEL)) =3D=3D NULL) { - ret =3D -ENOMEM; - goto cleanup_if_ptr; - } - - ch->lineup_delay =3D 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 =3D PDE(dentry->d_inode); - struct net_device *dev; - struct comx_channel *ch; - int ret; - - lock_kernel(); - dev =3D entry->data; - ch =3D 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 &&=20 - (ret=3Dch->protocol->line_exit(dev))) { - unlock_kernel(); - return ret; - } - if (ch->hardware && ch->hardware->hw_exit &&=20 - (ret=3Dch->hardware->hw_exit(dev))) {=20 - if(ch->protocol && ch->protocol->line_init) { - ch->protocol->line_init(dev); - } - unlock_kernel(); - return ret; - } - ch->protocol =3D NULL; - ch->hardware =3D 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 *dent= ry, struct nameidata *nd) -{ - struct proc_dir_entry *de; - struct inode *inode =3D NULL; - - lock_kernel(); - if ((de =3D PDE(dir)) !=3D NULL) { - for (de =3D de->subdir ; de ; de =3D de->next) { - if ((de->namelen =3D=3D dentry->d_name.len) && - (memcmp(dentry->d_name.name, de->name,=20 - de->namelen) =3D=3D 0)) { - if ((inode =3D proc_get_inode(dir->i_sb,=20 - de->low_ino, de)) =3D=3D NULL) {=20 - printk(KERN_ERR "COMX: lookup error\n");=20 - unlock_kernel(); - return ERR_PTR(-EINVAL);=20 - } - break; - } - } - } - unlock_kernel(); - dentry->d_op =3D &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 =3D toupper(*cs) - toupper(*ct++)) !=3D 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 mod= e, - int size, struct proc_dir_entry *dir) -{ - struct proc_dir_entry *new_file; - - if ((new_file =3D create_proc_entry(name, S_IFREG | mode, dir)) !=3D NU= LL) { - new_file->data =3D (void *)new_file; - new_file->read_proc =3D &comx_read_proc; - new_file->write_proc =3D &comx_write_proc; - new_file->size =3D size; - new_file->nlink =3D 1; - } - return(new_file); -} - -int comx_register_hardware(struct comx_hardware *comx_hw) -{ - struct comx_hardware *hw =3D comx_channels; - - if (!hw) { - comx_channels =3D comx_hw; - } else { - while (hw->next !=3D NULL && strcmp(comx_hw->name, hw->name) !=3D 0) { - hw =3D hw->next; - } - if (strcmp(comx_hw->name, hw->name) =3D=3D 0) { - return -1; - } - hw->next =3D comx_hw; - } - - printk(KERN_INFO "COMX: driver for hardware type %s, version %s\n", com= x_hw->name, comx_hw->version); - return 0; -} - -int comx_unregister_hardware(char *name) -{ - struct comx_hardware *hw =3D comx_channels; - - if (!hw) { - return -1; - } - - if (strcmp(hw->name, name) =3D=3D 0) { - comx_channels =3D comx_channels->next; - return 0; - } - - while (hw->next !=3D NULL && strcmp(hw->next->name,name) !=3D 0) { - hw =3D hw->next; - } - - if (hw->next !=3D NULL && strcmp(hw->next->name, name) =3D=3D 0) { - hw->next =3D hw->next->next; - return 0; - } - return -1; -} - -int comx_register_protocol(struct comx_protocol *comx_line) -{ - struct comx_protocol *pr =3D comx_lines; - - if (!pr) { - comx_lines =3D comx_line; - } else { - while (pr->next !=3D NULL && strcmp(comx_line->name, pr->name) !=3D0) = { - pr =3D pr->next; - } - if (strcmp(comx_line->name, pr->name) =3D=3D 0) { - return -1; - } - pr->next =3D comx_line; - } - - printk(KERN_INFO "COMX: driver for protocol type %s, version %s\n", com= x_line->name, comx_line->version); - return 0; -} - -int comx_unregister_protocol(char *name) -{ - struct comx_protocol *pr =3D comx_lines; - - if (!pr) { - return -1; - } - - if (strcmp(pr->name, name) =3D=3D 0) { - comx_lines =3D comx_lines->next; - return 0; - } - - while (pr->next !=3D NULL && strcmp(pr->next->name,name) !=3D 0) { - pr =3D pr->next; - } - - if (pr->next !=3D NULL && strcmp(pr->next->name, name) =3D=3D 0) { - pr->next =3D pr->next->next; - return 0; - } - return -1; -} - -static int __init comx_init(void) -{ - struct proc_dir_entry *new_file; - - comx_root_dir =3D create_proc_entry("comx",=20 - S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, &proc_root); - if (!comx_root_dir) - return -ENOMEM; - comx_root_dir->proc_iops =3D &comx_root_inode_ops; - - if ((new_file =3D create_proc_entry(FILENAME_HARDWARELIST,=20 - S_IFREG | 0444, comx_root_dir)) =3D=3D NULL) { - return -ENOMEM; - } -=09 - new_file->data =3D new_file; - new_file->read_proc =3D &comx_root_read_proc; - new_file->write_proc =3D NULL; - new_file->nlink =3D 1; - - if ((new_file =3D create_proc_entry(FILENAME_PROTOCOLLIST,=20 - S_IFREG | 0444, comx_root_dir)) =3D=3D NULL) { - return -ENOMEM; - } -=09 - new_file->data =3D new_file; - new_file->read_proc =3D &comx_root_read_proc; - new_file->write_proc =3D NULL; - new_file->nlink =3D 1; - - - printk(KERN_INFO "COMX: driver version %s (C) 1995-1999 ITConsult-Pro C= o. \n",=20 - 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); =3D=3D=3D=3D=3D drivers/net/wan/comx.h 1.2 vs edited =3D=3D=3D=3D=3D --- 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=20 - *=20 - * Original authors: Arpad Bakay , - * Peter Bajan , - * Previous maintainer: Tivadar Szemethy - * Currently maintained by: Gergely Madarasz - * - * Copyright (C) 1995-1999 ITConsult-Pro Co. - * - * 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 =20 -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;=20 - 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;=09 - 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=09 - 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,=20 - 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 *sav= ep); - 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, c= har *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; =3D=3D=3D=3D=3D drivers/net/wan/comxhw.h 1.1 vs edited =3D=3D=3D=3D=3D --- 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 , - * Peter Bajan , - * Previous maintainer: Tivadar Szemethy - * Current maintainer: Gergely Madarasz - * - * Copyright (C) 1995-1999 ITConsult-Pro Co. - * - * 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 =3D 1, DTE =3D 3 */ - -#define COMX_CMD_INIT 1 -#define COMX_CMD_EXIT 2 -#define COMX_CMD_OPEN 16 -#define COMX_CMD_CLOSE 17 =20