patch-2.3.21 linux/drivers/net/sdla_x25.c
Next file: linux/drivers/net/sdladrv.c
Previous file: linux/drivers/net/sdla_ppp.c
Back to the patch index
Back to the overall index
- Lines: 2436
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.3.20/linux/drivers/net/sdla_x25.c
- Orig date:
Wed Aug 18 11:36:42 1999
diff -u --recursive --new-file v2.3.20/linux/drivers/net/sdla_x25.c linux/drivers/net/sdla_x25.c
@@ -1,2435 +0,0 @@
-/*****************************************************************************
-* sdla_x25.c WANPIPE(tm) Multiprotocol WAN Link Driver. X.25 module.
-*
-* Author: Gene Kozin <genek@compuserve.com>
-*
-* Copyright: (c) 1995-1997 Sangoma Technologies Inc.
-*
-* 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.
-* ============================================================================
-* Mar 15, 1998 Alan Cox o 2.1.x porting
-* Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs
-* when they are disabled.
-* Nov 17, 1997 Farhan Thawar o Added IPX support
-* o Changed if_send() to now buffer packets when
-* the board is busy
-* o Removed queueing of packets via the polling
-* routing
-* o Changed if_send() critical flags to properly
-* handle race conditions
-* Nov 06, 1997 Farhan Thawar o Added support for SVC timeouts
-* o Changed PVC encapsulation to ETH_P_IP
-* Jul 21, 1997 Jaspreet Singh o Fixed freeing up of buffers using kfree()
-* when packets are received.
-* Mar 11, 1997 Farhan Thawar Version 3.1.1
-* o added support for V35
-* o changed if_send() to return 0 if
-* wandev.critical() is true
-* o free socket buffer in if_send() if
-* returning 0
-* o added support for single '@' address to
-* accept all incoming calls
-* o fixed bug in set_chan_state() to disconnect
-* Jan 15, 1997 Gene Kozin Version 3.1.0
-* o implemented exec() entry point
-* Jan 07, 1997 Gene Kozin Initial version.
-*****************************************************************************/
-
-
-#include <linux/kernel.h> /* printk(), and other useful stuff */
-#include <linux/stddef.h> /* offsetof(), etc. */
-#include <linux/errno.h> /* return codes */
-#include <linux/string.h> /* inline memset(), etc. */
-#include <linux/malloc.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <asm/uaccess.h>
-
-#define _GNUC_
-#include <linux/sdla_x25.h> /* X.25 firmware API definitions */
-
-/****** Defines & Macros ****************************************************/
-
-#define CMD_OK 0 /* normal firmware return code */
-#define CMD_TIMEOUT 0xFF /* firmware command timed out */
-#define MAX_CMD_RETRY 10 /* max number of firmware retries */
-
-#define X25_CHAN_MTU 4096 /* unfragmented logical channel MTU */
-#define X25_HRDHDR_SZ 7 /* max encapsulation header size */
-#define X25_CONCT_TMOUT (90*HZ) /* link connection timeout */
-#define X25_RECON_TMOUT (10*HZ) /* link connection timeout */
-#define CONNECT_TIMEOUT (90*HZ) /* link connection timeout */
-#define HOLD_DOWN_TIME (30*HZ) /* link hold down time */
-
-/* For IPXWAN */
-#define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b)))
-
-/****** Data Structures *****************************************************/
-
-/* This is an extention of the 'struct net_device' we create for each network
- * interface to keep the rest of X.25 channel-specific data.
- */
-typedef struct x25_channel
-{
- char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
- char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */
- unsigned lcn; /* logical channel number */
- unsigned tx_pkt_size;
- unsigned short protocol; /* ethertype, 0 - multiplexed */
- char svc; /* 0 - permanent, 1 - switched */
- char state; /* channel state */
- char drop_sequence; /* mark sequence for dropping */
- unsigned long state_tick; /* time of the last state change */
- unsigned idle_timeout; /* sec, before disconnecting */
- unsigned long i_timeout_sofar; /* # of sec's we've been idle */
- unsigned hold_timeout; /* sec, before re-connecting */
- unsigned long tick_counter; /* counter for transmit time out */
- char devtint; /* Weather we should dev_tint() */
- struct sk_buff* rx_skb; /* receive socket buffer */
- struct sk_buff* tx_skb; /* transmit socket buffer */
- sdla_t* card; /* -> owner */
- int ch_idx;
- struct net_device_stats ifstats; /* interface statistics */
-} x25_channel_t;
-
-typedef struct x25_call_info
-{
- char dest[17]; /* ASCIIZ destination address */
- char src[17]; /* ASCIIZ source address */
- char nuser; /* number of user data bytes */
- unsigned char user[127]; /* user data */
- char nfacil; /* number of facilities */
- struct
- {
- unsigned char code;
- unsigned char parm;
- } facil[64]; /* facilities */
-} x25_call_info_t;
-
-/****** Function Prototypes *************************************************/
-
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update (wan_device_t* wandev);
-static int new_if (wan_device_t* wandev, struct net_device* dev,
- wanif_conf_t* conf);
-static int del_if (wan_device_t* wandev, struct net_device* dev);
-
-/* WANPIPE-specific entry points */
-static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data);
-
-/* Network device interface */
-static int if_init (struct net_device* dev);
-static int if_open (struct net_device* dev);
-static int if_close (struct net_device* dev);
-static int if_header (struct sk_buff* skb, struct net_device* dev,
- unsigned short type, void* daddr, void* saddr, unsigned len);
-static int if_rebuild_hdr (struct sk_buff* skb);
-static int if_send (struct sk_buff* skb, struct net_device* dev);
-static struct net_device_stats * if_stats (struct net_device* dev);
-
-/* Interrupt handlers */
-static void wpx_isr (sdla_t* card);
-static void rx_intr (sdla_t* card);
-static void tx_intr (sdla_t* card);
-static void status_intr (sdla_t* card);
-static void event_intr (sdla_t* card);
-static void spur_intr (sdla_t* card);
-
-/* Background polling routines */
-static void wpx_poll (sdla_t* card);
-static void poll_disconnected (sdla_t* card);
-static void poll_connecting (sdla_t* card);
-static void poll_active (sdla_t* card);
-
-/* X.25 firmware interface functions */
-static int x25_get_version (sdla_t* card, char* str);
-static int x25_configure (sdla_t* card, TX25Config* conf);
-static int x25_get_err_stats (sdla_t* card);
-static int x25_get_stats (sdla_t* card);
-static int x25_set_intr_mode (sdla_t* card, int mode);
-static int x25_close_hdlc (sdla_t* card);
-static int x25_open_hdlc (sdla_t* card);
-static int x25_setup_hdlc (sdla_t* card);
-static int x25_set_dtr (sdla_t* card, int dtr);
-static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan);
-static int x25_place_call (sdla_t* card, x25_channel_t* chan);
-static int x25_accept_call (sdla_t* card, int lcn, int qdm);
-static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn);
-static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf);
-static int x25_fetch_events (sdla_t* card);
-static int x25_error (sdla_t* card, int err, int cmd, int lcn);
-
-/* X.25 asynchronous event handlers */
-static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb);
-
-/* Miscellaneous functions */
-static int connect (sdla_t* card);
-static int disconnect (sdla_t* card);
-static struct net_device* get_dev_by_lcn(wan_device_t* wandev, unsigned lcn);
-static int chan_connect (struct net_device* dev);
-static int chan_disc (struct net_device* dev);
-static void set_chan_state (struct net_device* dev, int state);
-static int chan_send (struct net_device* dev, struct sk_buff* skb);
-static unsigned char bps_to_speed_code (unsigned long bps);
-static unsigned int dec_to_uint (unsigned char* str, int len);
-static unsigned int hex_to_uint (unsigned char* str, int len);
-static void parse_call_info (unsigned char* str, x25_call_info_t* info);
-
-/* IPX functions */
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming);
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto);
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/****** Global Data **********************************************************
- * Note: All data must be explicitly initialized!!!
- */
-
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * X.25 Protocol Initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and X.25 firmware is running.
- * o read firmware version (to make sure it's alive)
- * o configure adapter
- * o initialize protocol-specific fields of the adapter data space.
- *
- * Return: 0 o.k.
- * < 0 failure.
- */
-int wpx_init (sdla_t* card, wandev_conf_t* conf)
-{
- union
- {
- char str[80];
- TX25Config cfg;
- } u;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_X25)
- {
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id)
- ;
- return -EINVAL;
- }
-
- /* Initialize protocol-specific fields */
- card->mbox = (void*)(card->hw.dpmbase + X25_MBOX_OFFS);
- card->rxmb = (void*)(card->hw.dpmbase + X25_RXMBOX_OFFS);
- card->flags = (void*)(card->hw.dpmbase + X25_STATUS_OFFS);
-
- /* Read firmware version. Note that when adapter initializes, it
- * clears the mailbox, so it may appear that the first command was
- * executed successfully when in fact it was merely erased. To work
- * around this, we execute the first command twice.
- */
- if (x25_get_version(card, NULL) || x25_get_version(card, u.str))
- return -EIO
- ;
- printk(KERN_INFO "%s: running X.25 firmware v%s\n",
- card->devname, u.str)
- ;
-
- /* Configure adapter. Here we set resonable defaults, then parse
- * device configuration structure and set configuration options.
- * Most configuration options are verified and corrected (if
- * necessary) since we can't rely on the adapter to do so and don't
- * want it to fail either.
- */
- memset(&u.cfg, 0, sizeof(u.cfg));
- u.cfg.t1 = 3;
- u.cfg.n2 = 10;
- u.cfg.autoHdlc = 1; /* automatic HDLC connection */
- u.cfg.hdlcWindow = 7;
- u.cfg.pktWindow = 2;
- u.cfg.station = 1; /* DTE */
- u.cfg.options = 0x00B0; /* disable D-bit pragmatics */
- u.cfg.ccittCompat = 1988;
- u.cfg.t10t20 = 30;
- u.cfg.t11t21 = 30;
- u.cfg.t12t22 = 30;
- u.cfg.t13t23 = 30;
- u.cfg.t16t26 = 30;
- u.cfg.t28 = 30;
- u.cfg.r10r20 = 5;
- u.cfg.r12r22 = 5;
- u.cfg.r13r23 = 5;
- u.cfg.responseOpt = 1; /* RR's after every packet */
-
- if (conf->clocking != WANOPT_EXTERNAL)
- u.cfg.baudRate = bps_to_speed_code(conf->bps)
- ;
- if (conf->station != WANOPT_DTE)
- {
- u.cfg.station = 0; /* DCE mode */
- }
- if (conf->interface != WANOPT_RS232 ) {
- u.cfg.hdlcOptions |= 0x80; /* V35 mode */
- }
- /* adjust MTU */
- if (!conf->mtu || (conf->mtu >= 1024))
- card->wandev.mtu = 1024
- ;
- else if (conf->mtu >= 512)
- card->wandev.mtu = 512
- ;
- else if (conf->mtu >= 256)
- card->wandev.mtu = 256
- ;
- else if (conf->mtu >= 128)
- card->wandev.mtu = 128
- ;
- else card->wandev.mtu = 64;
- u.cfg.defPktSize = u.cfg.pktMTU = card->wandev.mtu;
-
- if (conf->u.x25.hi_pvc)
- {
- card->u.x.hi_pvc = min(conf->u.x25.hi_pvc, 4095);
- card->u.x.lo_pvc = min(conf->u.x25.lo_pvc, card->u.x.hi_pvc);
- }
- if (conf->u.x25.hi_svc)
- {
- card->u.x.hi_svc = min(conf->u.x25.hi_svc, 4095);
- card->u.x.lo_svc = min(conf->u.x25.lo_svc, card->u.x.hi_svc);
- }
- u.cfg.loPVC = card->u.x.lo_pvc;
- u.cfg.hiPVC = card->u.x.hi_pvc;
- u.cfg.loTwoWaySVC = card->u.x.lo_svc;
- u.cfg.hiTwoWaySVC = card->u.x.hi_svc;
-
- if (conf->u.x25.hdlc_window)
- u.cfg.hdlcWindow = min(conf->u.x25.hdlc_window, 7)
- ;
- if (conf->u.x25.pkt_window)
- u.cfg.pktWindow = min(conf->u.x25.pkt_window, 7)
- ;
- if (conf->u.x25.t1)
- u.cfg.t1 = min(conf->u.x25.t1, 30)
- ;
- u.cfg.t2 = min(conf->u.x25.t2, 29);
- u.cfg.t4 = min(conf->u.x25.t4, 240);
- if (conf->u.x25.n2)
- u.cfg.n2 = min(conf->u.x25.n2, 30)
- ;
- if (conf->u.x25.ccitt_compat)
- u.cfg.ccittCompat = conf->u.x25.ccitt_compat
- ;
-
- /* initialize adapter */
- if ((x25_configure(card, &u.cfg) != CMD_OK) ||
- (x25_close_hdlc(card) != CMD_OK) || /* close HDLC link */
- (x25_set_dtr(card, 0) != CMD_OK)) /* drop DTR */
- return -EIO
- ;
-
- /* Initialize protocol-specific fields of adapter data space */
- card->wandev.bps = conf->bps;
- card->wandev.interface = conf->interface;
- card->wandev.clocking = conf->clocking;
- card->wandev.station = conf->station;
- card->isr = &wpx_isr;
- card->poll = &wpx_poll;
- card->exec = &wpx_exec;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = &del_if;
- card->wandev.state = WAN_DISCONNECTED;
- card->wandev.enable_tx_int = 0;
- card->irq_dis_if_send_count = 0;
- card->irq_dis_poll_count = 0;
- card->wandev.enable_IPX = conf->enable_IPX;
-
- if (conf->network_number)
- card->wandev.network_number = conf->network_number;
- else
- card->wandev.network_number = 0xDEADBEEF;
- return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics.
- */
-static int update (wan_device_t* wandev)
-{
- sdla_t* card;
-
- /* sanity checks */
- if ((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
- if (wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
- if (test_and_set_bit(0, (void*)&wandev->critical))
- return -EAGAIN;
- card = wandev->private;
-
- x25_get_err_stats(card);
- x25_get_stats(card);
- wandev->critical = 0;
- return 0;
-}
-
-/*============================================================================
- * Create new logical channel.
- * This routine is called by the router when ROUTER_IFNEW IOCTL is being
- * handled.
- * o parse media- and hardware-specific configuration
- * o make sure that a new channel can be created
- * o allocate resources, if necessary
- * o prepare network device structure for registaration.
- *
- * Return: 0 o.k.
- * < 0 failure (channel will not be created)
- */
-static int new_if (wan_device_t* wandev, struct net_device* dev, wanif_conf_t* conf)
-{
- sdla_t* card = wandev->private;
- x25_channel_t* chan;
- int err = 0;
-
- if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ))
- {
- printk(KERN_INFO "%s: invalid interface name!\n",
- card->devname)
- ;
- return -EINVAL;
- }
-
- /* allocate and initialize private data */
- chan = kmalloc(sizeof(x25_channel_t), GFP_KERNEL);
- if (chan == NULL)
- return -ENOMEM
- ;
- memset(chan, 0, sizeof(x25_channel_t));
- strcpy(chan->name, conf->name);
- chan->card = card;
- chan->protocol = ETH_P_IP;
- chan->tx_skb = chan->rx_skb = NULL;
-
- /* verify media address */
- if (conf->addr[0] == '@') /* SVC */
- {
- chan->svc = 1;
- strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ);
-
- /* Set channel timeouts (default if not specified) */
- chan->idle_timeout = (conf->idle_timeout) ? conf->idle_timeout : 90;
- chan->hold_timeout = (conf->hold_timeout) ? conf->hold_timeout : 10;
- }
- else if (is_digit(conf->addr[0])) /* PVC */
- {
- int lcn = dec_to_uint(conf->addr, 0);
-
- if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc))
- {
- chan->lcn = lcn;
- }
- else
- {
- printk(KERN_ERR
- "%s: PVC %u is out of range on interface %s!\n",
- wandev->name, lcn, chan->name)
- ;
- err = -EINVAL;
- }
- }
- else
- {
- printk(KERN_ERR
- "%s: invalid media address on interface %s!\n",
- wandev->name, chan->name)
- ;
- err = -EINVAL;
- }
- if (err)
- {
- kfree(chan);
- return err;
- }
-
- /* prepare network device data space for registration */
- dev->name = chan->name;
- dev->init = &if_init;
- dev->priv = chan;
- return 0;
-}
-
-/*============================================================================
- * Delete logical channel.
- */
-static int del_if (wan_device_t* wandev, struct net_device* dev)
-{
- if (dev->priv)
- {
- kfree(dev->priv);
- dev->priv = NULL;
- }
- return 0;
-}
-
-/****** WANPIPE-specific entry points ***************************************/
-
-/*============================================================================
- * Execute adapter interface command.
- */
-
-static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err, len;
- TX25Cmd cmd;
-
- if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd)))
- return -EFAULT;
-
- /* execute command */
-
- do
- {
- memcpy(&mbox->cmd, &cmd, sizeof(cmd));
- if (cmd.length)
- {
- if(copy_from_user((void*)&mbox->data, u_data, cmd.length))
- return-EFAULT;
- }
- if (sdla_exec(mbox))
- err = mbox->cmd.result
- ;
- else return -EIO;
- }
- while (err && retry-- && x25_error(card, err, cmd.command, cmd.lcn));
-
- /* return result */
- if(copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(TX25Cmd)))
- return -EFAULT;
- len = mbox->cmd.length;
- if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len))
- return -EFAULT;
- return 0;
-}
-
-/****** Network Device Interface ********************************************/
-
-/*============================================================================
- * Initialize Linux network interface.
- *
- * This routine is called only once for each interface, during Linux network
- * interface registration. Returning anything but zero will fail interface
- * registration.
- */
-static int if_init (struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- wan_device_t* wandev = &card->wandev;
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_header = &if_header;
- dev->rebuild_header = &if_rebuild_hdr;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
-
- /* Initialize media-specific parameters */
- dev->type = 30; /* ARP h/w type */
- dev->mtu = X25_CHAN_MTU;
- dev->hard_header_len = X25_HRDHDR_SZ; /* media header length */
- dev->addr_len = 2; /* hardware address length */
- if (!chan->svc)
- *(unsigned short*)dev->dev_addr = htons(chan->lcn);
-
- /* Initialize hardware parameters (just for reference) */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = (unsigned long)wandev->maddr;
- dev->mem_end = dev->mem_end + wandev->msize - 1;
-
- /* Set transmit buffer queue length */
- dev->tx_queue_len = 10;
-
- /* Initialize socket buffers */
-
- dev_init_buffers(dev);
- set_chan_state(dev, WAN_DISCONNECTED);
- return 0;
-}
-
-/*============================================================================
- * Open network interface.
- * o prevent module from unloading by incrementing use count
- * o if link is disconnected then initiate connection
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open (struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- if (dev->start)
- return -EBUSY; /* only one open is allowed */
-
- if (test_and_set_bit(0, (void*)&card->wandev.critical))
- return -EAGAIN;
-
- dev->interrupt = 0;
- dev->tbusy = 0;
- dev->start = 1;
- wanpipe_open(card);
-
- /* If this is the first open, initiate physical connection */
- if (card->open_cnt == 1)
- connect(card);
- card->wandev.critical = 0;
- return 0;
-}
-
-/*============================================================================
- * Close network interface.
- * o reset flags.
- * o if there's no more open channels then disconnect physical link.
- */
-static int if_close (struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- if (test_and_set_bit(0, (void*)&card->wandev.critical))
- return -EAGAIN;
-
- dev->start = 0;
- if ((chan->state == WAN_CONNECTED) || (chan->state == WAN_CONNECTING))
- chan_disc(dev);
-
- wanpipe_close(card);
-
- /* If this is the last close, disconnect physical link */
- if (!card->open_cnt)
- disconnect(card);
-
- card->wandev.critical = 0;
- return 0;
-}
-
-/*============================================================================
- * Build media header.
- * o encapsulate packet according to encapsulation type.
- *
- * The trick here is to put packet type (Ethertype) into 'protocol' field of
- * the socket buffer, so that we don't forget it. If encapsulation fails,
- * set skb->protocol to 0 and discard packet later.
- *
- * Return: media header length.
- */
-static int if_header (struct sk_buff* skb, struct net_device* dev,
- unsigned short type, void* daddr, void* saddr, unsigned len)
-{
- x25_channel_t* chan = dev->priv;
- int hdr_len = dev->hard_header_len;
-
- skb->protocol = type;
- if (!chan->protocol)
- {
- hdr_len = wanrouter_encapsulate(skb, dev);
- if (hdr_len < 0)
- {
- hdr_len = 0;
- skb->protocol = 0;
- }
- }
- return hdr_len;
-}
-
-/*============================================================================
- * Re-build media header.
- *
- * Return: 1 physical address resolved.
- * 0 physical address not resolved
- */
-
-static int if_rebuild_hdr (struct sk_buff* skb)
-{
- struct net_device *dev=skb->dev;
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",
- card->devname, dev->name);
- return 1;
-}
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission).
- * o check link state. If link is not up, then drop the packet.
- * o check channel status. If it's down then initiate a call.
- * o pass a packet to corresponding WAN device.
- * o free socket buffer
- *
- * Return: 0 complete (socket buffer must be freed)
- * non-0 packet may be re-transmitted (tbusy must be set)
- *
- * Notes:
- * 1. This routine is called either by the protocol stack or by the "net
- * bottom half" (with interrupts enabled).
- * 2. Setting tbusy flag will inhibit further transmit requests from the
- * protocol stack and can be used for flow control with protocol layer.
- */
-
-static int if_send (struct sk_buff* skb, struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- struct net_device *dev2;
- TX25Status* status = card->flags;
- unsigned long host_cpu_flags;
-
- if (dev->tbusy)
- {
- ++chan->ifstats.rx_dropped;
- if ((jiffies - chan->tick_counter) < (5*HZ))
- {
- return dev->tbusy;
- }
- printk(KERN_INFO "%s: Transmit time out %s!\n",
- card->devname, dev->name)
- ;
- for( dev2 = card->wandev.dev; dev2; dev2 = dev2->slave)
- {
- dev2->tbusy = 0;
- }
- }
- chan->tick_counter = jiffies;
-
- disable_irq(card->hw.irq);
- ++card->irq_dis_if_send_count;
-
- if (test_and_set_bit(0, (void*)&card->wandev.critical))
- {
- printk(KERN_INFO "Hit critical in if_send()!\n");
- if (card->wandev.critical == CRITICAL_IN_ISR)
- {
- card->wandev.enable_tx_int = 1;
- dev->tbusy = 1;
-
- save_flags(host_cpu_flags);
- cli();
- if ((!(--card->irq_dis_if_send_count)) &&
- (!card->irq_dis_poll_count))
- enable_irq(card->hw.irq);
- restore_flags(host_cpu_flags);
-
- return dev->tbusy;
- }
- dev_kfree_skb(skb);
-
- save_flags(host_cpu_flags);
- cli();
- if ((!(--card->irq_dis_if_send_count)) &&
- (!card->irq_dis_poll_count))
- enable_irq(card->hw.irq);
- restore_flags(host_cpu_flags);
-
- return dev->tbusy;
- }
-
- /* Below is only until we have per-channel IPX going.... */
- if(!(chan->svc))
- chan->protocol = skb->protocol;
-
- if (card->wandev.state != WAN_CONNECTED)
- ++chan->ifstats.tx_dropped;
-
- /* Below is only until we have per-channel IPX going.... */
- else if ( (chan->svc) && (chan->protocol && (chan->protocol != skb->protocol)))
- {
- printk(KERN_INFO
- "%s: unsupported Ethertype 0x%04X on interface %s!\n",
- card->devname, skb->protocol, dev->name);
- ++chan->ifstats.tx_errors;
- }
- else switch (chan->state)
- {
- case WAN_DISCONNECTED:
- /* Try to establish connection. If succeded, then start
- * transmission, else drop a packet.
- */
- if (chan_connect(dev) != 0)
- {
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- break;
- }
- /* fall through */
-
- case WAN_CONNECTED:
- if( skb->protocol == ETH_P_IPX )
- {
- if(card->wandev.enable_IPX)
- {
- switch_net_numbers( skb->data,
- card->wandev.network_number, 0);
- }
- else
- {
- ++card->wandev.stats.tx_dropped;
- ++chan->ifstats.tx_dropped;
- goto tx_done;
- }
- }
- dev->trans_start = jiffies;
- if(chan_send(dev, skb))
- {
- dev->tbusy = 1;
- status->imask |= 0x2;
- }
- break;
-
- default:
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
- }
-tx_done:
- if (!dev->tbusy)
- dev_kfree_skb(skb);
-
- card->wandev.critical = 0;
- save_flags(host_cpu_flags);
- cli();
- if ((!(--card->irq_dis_if_send_count)) && (!card->irq_dis_poll_count))
- enable_irq(card->hw.irq);
- restore_flags(host_cpu_flags);
- return dev->tbusy;
-}
-
-/*============================================================================
- * Get Ethernet-style interface statistics.
- * Return a pointer to struct net_device_stats
- */
-
-static struct net_device_stats* if_stats (struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- if(chan==NULL)
- return NULL;
- return &chan->ifstats;
-}
-
-/****** Interrupt Handlers **************************************************/
-
-/*============================================================================
- * X.25 Interrupt Service Routine.
- */
-
-static void wpx_isr (sdla_t* card)
-{
- TX25Status* status = card->flags;
- struct net_device *dev;
- unsigned long host_cpu_flags;
-
- card->in_isr = 1;
- card->buff_int_mode_unbusy = 0;
-
- if (test_and_set_bit(0, (void*)&card->wandev.critical))
- {
-
- printk(KERN_INFO "wpx_isr: %s, wandev.critical set to 0x%02X, int type = 0x%02X\n", card->devname, card->wandev.critical, status->iflags);
- card->in_isr = 0;
- return;
- }
-
- /* For all interrupts set the critical flag to CRITICAL_RX_INTR.
- * If the if_send routine is called with this flag set it will set
- * the enable transmit flag to 1. (for a delayed interrupt)
- */
- card->wandev.critical = CRITICAL_IN_ISR;
-
- switch (status->iflags)
- {
- case 0x01: /* receive interrupt */
- rx_intr(card);
- break;
-
- case 0x02: /* transmit interrupt */
- tx_intr(card);
- card->buff_int_mode_unbusy = 1;
- status->imask &= ~0x2;
- break;
-
- case 0x04: /* modem status interrupt */
- status_intr(card);
- break;
-
- case 0x10: /* network event interrupt */
- event_intr(card);
- break;
-
- default: /* unwanted interrupt */
- spur_intr(card);
- }
- card->wandev.critical = CRITICAL_INTR_HANDLED;
- if( card->wandev.enable_tx_int)
- {
- card->wandev.enable_tx_int = 0;
- status->imask |= 0x2;
- }
- save_flags(host_cpu_flags);
- cli();
- card->in_isr = 0;
- status->iflags = 0; /* clear interrupt condition */
- card->wandev.critical = 0;
- restore_flags(host_cpu_flags);
-
- if(card->buff_int_mode_unbusy)
- {
- for(dev = card->wandev.dev; dev; dev = dev->slave)
- {
- if(((x25_channel_t*)dev->priv)->devtint)
- {
- mark_bh(NET_BH);
- return;
- }
- }
- }
-}
-
-/*============================================================================
- * Receive interrupt handler.
- * This routine handles fragmented IP packets using M-bit according to the
- * RFC1356.
- * o map ligical channel number to network interface.
- * o allocate socket buffer or append received packet to the existing one.
- * o if M-bit is reset (i.e. it's the last packet in a sequence) then
- * decapsulate packet and pass socket buffer to the protocol stack.
- *
- * Notes:
- * 1. When allocating a socket buffer, if M-bit is set then more data is
- * comming and we have to allocate buffer for the maximum IP packet size
- * expected on this channel.
- * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no
- * socket buffers available) the whole packet sequence must be discarded.
- */
-
-static void rx_intr (sdla_t* card)
-{
- TX25Mbox* rxmb = card->rxmb;
- unsigned lcn = rxmb->cmd.lcn; /* logical channel number */
- unsigned len = rxmb->cmd.length; /* packet length */
- unsigned qdm = rxmb->cmd.qdm; /* Q,D and M bits */
- wan_device_t* wandev = &card->wandev;
- struct net_device* dev = get_dev_by_lcn(wandev, lcn);
- x25_channel_t* chan;
- struct sk_buff* skb;
- void* bufptr;
-
- if (dev == NULL)
- {
- /* Invalid channel, discard packet */
- printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
- card->devname, lcn);
- return;
- }
-
- chan = dev->priv;
- chan->i_timeout_sofar = jiffies;
- if (chan->drop_sequence)
- {
- if (!(qdm & 0x01)) chan->drop_sequence = 0;
- return;
- }
-
- skb = chan->rx_skb;
- if (skb == NULL)
- {
- /* Allocate new socket buffer */
- int bufsize = (qdm & 0x01) ? dev->mtu : len;
-
- skb = dev_alloc_skb(bufsize + dev->hard_header_len);
- if (skb == NULL)
- {
- printk(KERN_INFO "%s: no socket buffers available!\n",
- card->devname);
- chan->drop_sequence = 1; /* set flag */
- ++chan->ifstats.rx_dropped;
- return;
- }
- skb->dev = dev;
- skb->protocol = htons(chan->protocol);
- chan->rx_skb = skb;
- }
-
- if (skb_tailroom(skb) < len)
- {
- /* No room for the packet. Call off the whole thing! */
- dev_kfree_skb(skb);
- chan->rx_skb = NULL;
- if (qdm & 0x01) chan->drop_sequence = 1;
-
- printk(KERN_INFO "%s: unexpectedly long packet sequence "
- "on interface %s!\n", card->devname, dev->name);
- ++chan->ifstats.rx_length_errors;
- return;
- }
-
- /* Append packet to the socket buffer */
- bufptr = skb_put(skb, len);
- memcpy(bufptr, rxmb->data, len);
-
- if (qdm & 0x01)
- return; /* more data is comming */
-
- dev->last_rx = jiffies; /* timestamp */
- chan->rx_skb = NULL; /* dequeue packet */
-
- /* Decapsulate packet, if necessary */
- if (!skb->protocol && !wanrouter_type_trans(skb, dev))
- {
- /* can't decapsulate packet */
- dev_kfree_skb(skb);
- ++chan->ifstats.rx_errors;
- }
- else
- {
- if( handle_IPXWAN(skb->data, card->devname, card->wandev.enable_IPX, card->wandev.network_number, skb->protocol))
- {
- if( card->wandev.enable_IPX )
- {
- if(chan_send(dev, skb))
- {
- chan->tx_skb = skb;
- }
- else
- {
- dev_kfree_skb(skb);
- }
- }
- else
- {
- /* FIXME: increment IPX packet dropped statistic */
- }
- }
- else
- {
- netif_rx(skb);
- ++chan->ifstats.rx_packets;
- chan->ifstats.rx_bytes += skb->len;
- }
- }
-}
-
-/*============================================================================
- * Transmit interrupt handler.
- * o Release socket buffer
- * o Clear 'tbusy' flag
- */
-
-static void tx_intr (sdla_t* card)
-{
- struct net_device *dev;
-
- /* unbusy all devices and then dev_tint(); */
- for(dev = card->wandev.dev; dev; dev = dev->slave)
- {
- ((x25_channel_t*)dev->priv)->devtint = dev->tbusy;
- dev->tbusy = 0;
- }
-
-}
-
-/*============================================================================
- * Modem status interrupt handler.
- */
-static void status_intr (sdla_t* card)
-{
-}
-
-/*============================================================================
- * Network event interrupt handler.
- */
-static void event_intr (sdla_t* card)
-{
-}
-
-/*============================================================================
- * Spurious interrupt handler.
- * o print a warning
- * o
- * If number of spurious interrupts exceeded some limit, then ???
- */
-static void spur_intr (sdla_t* card)
-{
- printk(KERN_INFO "%s: spurious interrupt!\n", card->devname);
-}
-
-/****** Background Polling Routines ****************************************/
-
-/*============================================================================
- * Main polling routine.
- * This routine is repeatedly called by the WANPIPE 'thread' to allow for
- * time-dependent housekeeping work.
- *
- * Notes:
- * 1. This routine may be called on interrupt context with all interrupts
- * enabled. Beware!
- */
-
-static void wpx_poll (sdla_t* card)
-{
- unsigned long host_cpu_flags;
-
- disable_irq(card->hw.irq);
- ++card->irq_dis_poll_count;
-
- if (test_and_set_bit(0, (void*)&card->wandev.critical))
- {
- printk(KERN_INFO "%s: critical in polling!\n",card->devname);
- save_flags(host_cpu_flags);
- cli();
- if ((!card->irq_dis_if_send_count) &&
- (!(--card->irq_dis_poll_count)))
- enable_irq(card->hw.irq);
- restore_flags(host_cpu_flags);
- return;
- }
-
- switch(card->wandev.state)
- {
- case WAN_CONNECTED:
- poll_active(card);
- break;
-
- case WAN_CONNECTING:
- poll_connecting(card);
- break;
-
- case WAN_DISCONNECTED:
- poll_disconnected(card);
- }
- card->wandev.critical = 0;
- save_flags(host_cpu_flags);
- cli();
- if ((!card->irq_dis_if_send_count) && (!(--card->irq_dis_poll_count)))
- enable_irq(card->hw.irq);
- restore_flags(host_cpu_flags);
-}
-
-/*============================================================================
- * Handle physical link establishment phase.
- * o if connection timed out, disconnect the link.
- */
-static void poll_connecting (sdla_t* card)
-{
- TX25Status* status = card->flags;
-
- if (status->gflags & X25_HDLC_ABM)
- {
- wanpipe_set_state(card, WAN_CONNECTED);
- x25_set_intr_mode(card, 0x83); /* enable Rx interrupts */
- status->imask &= ~0x2; /* mask Tx interupts */
- }
- else if ((jiffies - card->state_tick) > CONNECT_TIMEOUT)
- disconnect(card);
-}
-
-/*============================================================================
- * Handle physical link disconnected phase.
- * o if hold-down timeout has expired and there are open interfaces, connect
- * link.
- */
-static void poll_disconnected (sdla_t* card)
-{
- if (card->open_cnt && ((jiffies - card->state_tick) > HOLD_DOWN_TIME))
- connect(card);
-}
-
-/*============================================================================
- * Handle active link phase.
- * o fetch X.25 asynchronous events.
- * o kick off transmission on all interfaces.
- */
-static void poll_active (sdla_t* card)
-{
- struct net_device* dev;
-
- /* Fetch X.25 asynchronous events */
- x25_fetch_events(card);
-
- for (dev = card->wandev.dev; dev; dev = dev->slave)
- {
- x25_channel_t* chan = dev->priv;
- struct sk_buff* skb = chan->tx_skb;
-
- /* If there is a packet queued for transmission then kick
- * the channel's send routine. When transmission is complete
- * or if error has occurred, release socket buffer and reset
- * 'tbusy' flag.
- */
- if (skb && (chan_send(dev, skb) == 0))
- {
- chan->tx_skb = NULL;
- dev->tbusy = 0;
- dev_kfree_skb(skb);
- }
-
- /* If SVC has been idle long enough, close virtual circuit */
-
- if(( chan->svc )&&( chan->state == WAN_CONNECTED ))
- {
- if( (jiffies - chan->i_timeout_sofar) / HZ > chan->idle_timeout )
- {
- /* Close svc */
- printk(KERN_INFO "%s: Closing down Idle link %s on LCN %d\n",card->devname,chan->name,chan->lcn);
- chan->i_timeout_sofar = jiffies;
- chan_disc(dev);
- }
- }
- }
-}
-
-/****** SDLA Firmware-Specific Functions *************************************
- * Almost all X.25 commands can unexpetedly fail due to so called 'X.25
- * asynchronous events' such as restart, interrupt, incoming call request,
- * call clear request, etc. They can't be ignored and have to be dealt with
- * immediately. To tackle with this problem we execute each interface command
- * in a loop until good return code is received or maximum number of retries
- * is reached. Each interface command returns non-zero return code, an
- * asynchronous event/error handler x25_error() is called.
- */
-
-/*============================================================================
- * Read X.25 firmware version.
- * Put code version as ASCII string in str.
- */
-static int x25_get_version (sdla_t* card, char* str)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_READ_CODE_VERSION;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- &&
- x25_error(card, err, X25_READ_CODE_VERSION, 0));
-
- if (!err && str)
- {
- int len = mbox->cmd.length;
- memcpy(str, mbox->data, len);
- str[len] = '\0';
- }
- return err;
-}
-
-/*============================================================================
- * Configure adapter.
- */
-
-static int x25_configure (sdla_t* card, TX25Config* conf)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- memcpy(mbox->data, (void*)conf, sizeof(TX25Config));
- mbox->cmd.length = sizeof(TX25Config);
- mbox->cmd.command = X25_SET_CONFIGURATION;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0));
- return err;
-}
-
-/*============================================================================
- * Get communications error statistics.
- */
-static int x25_get_err_stats (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_READ_COMM_ERR;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_READ_COMM_ERR, 0));
-
- if (!err)
- {
- THdlcCommErr* stats = (void*)mbox->data;
-
- card->wandev.stats.rx_over_errors = stats->rxOverrun;
- card->wandev.stats.rx_crc_errors = stats->rxBadCrc;
- card->wandev.stats.rx_missed_errors = stats->rxAborted;
- card->wandev.stats.tx_aborted_errors = stats->txAborted;
- }
- return err;
-}
-
-/*============================================================================
- * Get protocol statistics.
- */
-static int x25_get_stats (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_READ_STATISTICS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_READ_STATISTICS, 0));
-
- if (!err)
- {
- TX25Stats* stats = (void*)mbox->data;
-
- card->wandev.stats.rx_packets = stats->rxData;
- card->wandev.stats.tx_packets = stats->rxData;
- }
- return err;
-}
-
-/*============================================================================
- * Close HDLC link.
- */
-static int x25_close_hdlc (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_LINK_CLOSE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_CLOSE, 0));
-
- return err;
-}
-
-/*============================================================================
- * Open HDLC link.
- */
-static int x25_open_hdlc (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_LINK_OPEN;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_OPEN, 0));
-
- return err;
-}
-
-/*============================================================================
- * Setup HDLC link.
- */
-static int x25_setup_hdlc (sdla_t* card)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_HDLC_LINK_SETUP;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_SETUP, 0));
-
- return err;
-}
-
-/*============================================================================
- * Set (raise/drop) DTR.
- */
-static int x25_set_dtr (sdla_t* card, int dtr)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->data[0] = 0;
- mbox->data[2] = 0;
- mbox->data[1] = dtr ? 0x02 : 0x01;
- mbox->cmd.length = 3;
- mbox->cmd.command = X25_SET_GLOBAL_VARS;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_SET_GLOBAL_VARS, 0));
-
- return err;
-}
-
-/*============================================================================
- * Set interrupt mode.
- */
-static int x25_set_intr_mode (sdla_t* card, int mode)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->data[0] = mode;
- if (card->hw.fwid == SFID_X25_508)
- {
- mbox->data[1] = card->hw.irq;
- mbox->cmd.length = 2;
- }
- else mbox->cmd.length = 1;
- mbox->cmd.command = X25_SET_INTERRUPT_MODE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_SET_INTERRUPT_MODE, 0)) ;
- return err;
-}
-
-/*============================================================================
- * Read X.25 channel configuration.
- */
-static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int lcn = chan->lcn;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.lcn = lcn;
- mbox->cmd.command = X25_READ_CHANNEL_CONFIG;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_READ_CHANNEL_CONFIG, lcn));
-
- if (!err)
- {
- TX25Status* status = card->flags;
-
- /* calculate an offset into the array of status bytes */
- if (card->u.x.hi_svc <= 255)
- chan->ch_idx = lcn - 1;
- else
- {
- int offset;
-
- switch (mbox->data[0] && 0x1F)
- {
- case 0x01:
- offset = status->pvc_map; break;
- case 0x03:
- offset = status->icc_map; break;
- case 0x07:
- offset = status->twc_map; break;
- case 0x0B:
- offset = status->ogc_map; break;
- default:
- offset = 0;
- }
- chan->ch_idx = lcn - 1 - offset;
- }
-
- /* get actual transmit packet size on this channel */
- switch(mbox->data[1] & 0x38)
- {
- case 0x00:
- chan->tx_pkt_size = 16;
- break;
- case 0x08:
- chan->tx_pkt_size = 32;
- break;
- case 0x10:
- chan->tx_pkt_size = 64;
- break;
- case 0x18:
- chan->tx_pkt_size = 128;
- break;
- case 0x20:
- chan->tx_pkt_size = 256;
- break;
- case 0x28:
- chan->tx_pkt_size = 512;
- break;
- case 0x30:
- chan->tx_pkt_size = 1024;
- break;
- }
- printk(KERN_INFO "%s: X.25 packet size on LCN %d is %d.\n",
- card->devname, lcn, chan->tx_pkt_size);
- }
- return err;
-}
-
-/*============================================================================
- * Place X.25 call.
- */
-
-static int x25_place_call (sdla_t* card, x25_channel_t* chan)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
- char str[64];
-
- sprintf(str, "-d%s -uCC", chan->addr);
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- strcpy(mbox->data, str);
- mbox->cmd.length = strlen(str);
- mbox->cmd.command = X25_PLACE_CALL;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_PLACE_CALL, 0));
-
- if (!err)
- {
- chan->lcn = mbox->cmd.lcn;
- chan->protocol = ETH_P_IP;
- }
- return err;
-}
-
-/*============================================================================
- * Accept X.25 call.
- */
-
-static int x25_accept_call (sdla_t* card, int lcn, int qdm)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.lcn = lcn;
- mbox->cmd.qdm = qdm;
- mbox->cmd.command = X25_ACCEPT_CALL;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_ACCEPT_CALL, lcn));
-
- return err;
-}
-
-/*============================================================================
- * Clear X.25 call.
- */
-static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.lcn = lcn;
- mbox->cmd.cause = cause;
- mbox->cmd.diagn = diagn;
- mbox->cmd.command = X25_CLEAR_CALL;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_CLEAR_CALL, lcn));
-
- return err;
-}
-
-/*============================================================================
- * Send X.25 data packet.
- */
-static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf)
-{
- TX25Mbox* mbox = card->mbox;
- int retry = MAX_CMD_RETRY;
- int err;
-
- do
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- memcpy(mbox->data, buf, len);
- mbox->cmd.length = len;
- mbox->cmd.lcn = lcn;
- mbox->cmd.qdm = qdm;
- mbox->cmd.command = X25_WRITE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- } while (err && retry-- && x25_error(card, err, X25_WRITE, lcn));
- return err;
-}
-
-/*============================================================================
- * Fetch X.25 asynchronous events.
- */
-static int x25_fetch_events (sdla_t* card)
-{
- TX25Status* status = card->flags;
- TX25Mbox* mbox = card->mbox;
- int err = 0;
-
- if (status->gflags & 0x20)
- {
- memset(&mbox->cmd, 0, sizeof(TX25Cmd));
- mbox->cmd.command = X25_IS_DATA_AVAILABLE;
- err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;
- if (err)
- x25_error(card, err, X25_IS_DATA_AVAILABLE, 0);
- }
- return err;
-}
-
-/*============================================================================
- * X.25 asynchronous event/error handler.
- * This routine is called each time interface command returns non-zero
- * return code to handle X.25 asynchronous events and common errors.
- * Return non-zero to repeat command or zero to cancel it.
- *
- * Notes:
- * 1. This function may be called recursively, as handling some of the
- * asynchronous events (e.g. call request) requires execution of the
- * interface command(s) that, in turn, may also return asynchronous
- * events. To avoid re-entrancy problems we copy mailbox to dynamically
- * allocated memory before processing events.
- */
-static int x25_error (sdla_t* card, int err, int cmd, int lcn)
-{
- int retry = 1;
- unsigned dlen = ((TX25Mbox*)card->mbox)->cmd.length;
- TX25Mbox* mb;
-
- mb = kmalloc(sizeof(TX25Mbox) + dlen, GFP_ATOMIC);
- if (mb == NULL)
- {
- printk(KERN_ERR "%s: x25_error() out of memory!\n",
- card->devname);
- return 0;
- }
- memcpy(mb, card->mbox, sizeof(TX25Mbox) + dlen);
- switch (err)
- {
- case 0x40: /* X.25 asynchronous packet was received */
- mb->data[dlen] = '\0';
- switch (mb->cmd.pktType & 0x7F)
- {
- case 0x30: /* incoming call */
- retry = incoming_call(card, cmd, lcn, mb);
- break;
-
- case 0x31: /* connected */
- retry = call_accepted(card, cmd, lcn, mb);
- break;
-
- case 0x02: /* call clear request */
- retry = call_cleared(card, cmd, lcn, mb);
- break;
-
- case 0x04: /* reset request */
- printk(KERN_INFO "%s: X.25 reset request on LCN %d! "
- "Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.lcn, mb->cmd.cause,
- mb->cmd.diagn);
- break;
-
- case 0x08: /* restart request */
- retry = restart_event(card, cmd, lcn, mb);
- break;
-
- default:
- printk(KERN_INFO "%s: X.25 event 0x%02X on LCN %d! "
- "Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.pktType,
- mb->cmd.lcn, mb->cmd.cause, mb->cmd.diagn);
- }
- break;
-
- case 0x41: /* X.25 protocol violation indication */
- printk(KERN_INFO
- "%s: X.25 protocol violation on LCN %d! "
- "Packet:0x%02X Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.lcn,
- mb->cmd.pktType & 0x7F, mb->cmd.cause, mb->cmd.diagn);
- break;
-
- case 0x42: /* X.25 timeout */
- retry = timeout_event(card, cmd, lcn, mb);
- break;
-
- case 0x43: /* X.25 retry limit exceeded */
- printk(KERN_INFO
- "%s: exceeded X.25 retry limit on LCN %d! "
- "Packet:0x%02X Diagn:0x%02X\n", card->devname,
- mb->cmd.lcn, mb->cmd.pktType, mb->cmd.diagn);
- break;
-
- case 0x08: /* modem failure */
- printk(KERN_INFO "%s: modem failure!\n", card->devname);
- break;
-
- case 0x09: /* N2 retry limit */
- printk(KERN_INFO "%s: exceeded HDLC retry limit!\n",
- card->devname);
- break;
-
- case 0x06: /* unnumbered frame was received while in ABM */
- printk(KERN_INFO "%s: received Unnumbered frame 0x%02X!\n",
- card->devname, mb->data[0]);
- break;
-
- case CMD_TIMEOUT:
- printk(KERN_ERR "%s: command 0x%02X timed out!\n",
- card->devname, cmd);
- retry = 0; /* abort command */
- break;
-
- default:
- printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
- card->devname, cmd, err);
- retry = 0; /* abort command */
- }
- kfree(mb);
- return retry;
-}
-
-/****** X.25 Asynchronous Event Handlers *************************************
- * These functions are called by the x25_error() and should return 0, if
- * the command resulting in the asynchronous event must be aborted.
- */
-
-/*============================================================================
- * Handle X.25 incoming call request.
- * RFC 1356 establishes the following rules:
- * 1. The first octet in the Call User Data (CUD) field of the call
- * request packet contains NLPID identifying protocol encapsulation.
- * 2. Calls MUST NOT be accepted unless router supports requested
- * protocol encapsulation.
- * 3. A diagnostic code 249 defined by ISO/IEC 8208 may be used when
- * clearing a call because protocol encapsulation is not supported.
- * 4. If an incoming call is received while a call request is pending
- * (i.e. call collision has occurred), the incoming call shall be
- * rejected and call request shall be retried.
- */
-
-static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- wan_device_t* wandev = &card->wandev;
- int new_lcn = mb->cmd.lcn;
- struct net_device* dev = get_dev_by_lcn(wandev, new_lcn);
- x25_channel_t* chan = NULL;
- int accept = 0; /* set to '1' if o.k. to accept call */
- x25_call_info_t* info;
-
- /* Make sure there is no call collision */
- if (dev != NULL)
- {
- printk(KERN_INFO
- "%s: X.25 incoming call collision on LCN %d!\n",
- card->devname, new_lcn);
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
-
- /* Make sure D bit is not set in call request */
- if (mb->cmd.qdm & 0x02)
- {
- printk(KERN_INFO
- "%s: X.25 incoming call on LCN %d with D-bit set!\n",
- card->devname, new_lcn);
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
-
- /* Parse call request data */
- info = kmalloc(sizeof(x25_call_info_t), GFP_ATOMIC);
- if (info == NULL)
- {
- printk(KERN_ERR
- "%s: not enough memory to parse X.25 incoming call "
- "on LCN %d!\n", card->devname, new_lcn);
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
- parse_call_info(mb->data, info);
- printk(KERN_INFO "%s: X.25 incoming call on LCN %d! Call data: %s\n",
- card->devname, new_lcn, mb->data);
-
- /* Find available channel */
- for (dev = wandev->dev; dev; dev = dev->slave)
- {
- chan = dev->priv;
-
- if (!chan->svc || (chan->state != WAN_DISCONNECTED))
- continue;
- if (strcmp(info->src, chan->addr) == 0)
- break;
- /* If just an '@' is specified, accept all incoming calls */
- if (strcmp(chan->addr, "") == 0)
- break;
- }
-
- if (dev == NULL)
- {
- printk(KERN_INFO "%s: no channels available!\n",
- card->devname);
- x25_clear_call(card, new_lcn, 0, 0);
- }
-
- /* Check requested protocol encapsulation */
- else if (info->nuser == 0)
- {
- printk(KERN_INFO
- "%s: no user data in incoming call on LCN %d!\n",
- card->devname, new_lcn);
- x25_clear_call(card, new_lcn, 0, 0);
- }
- else switch (info->user[0])
- {
- case 0: /* multiplexed */
- chan->protocol = 0;
- accept = 1;
- break;
-
- case NLPID_IP: /* IP datagrams */
- chan->protocol = ETH_P_IP;
- accept = 1;
- break;
-
- case NLPID_SNAP: /* IPX datagrams */
- chan->protocol = ETH_P_IPX;
- accept = 1;
- break;
- default:
- printk(KERN_INFO
- "%s: unsupported NLPID 0x%02X in incoming call "
- "on LCN %d!\n", card->devname, info->user[0], new_lcn);
- x25_clear_call(card, new_lcn, 0, 249);
- }
-
- if (accept && (x25_accept_call(card, new_lcn, 0) == CMD_OK))
- {
- chan->lcn = new_lcn;
- if (x25_get_chan_conf(card, chan) == CMD_OK)
- set_chan_state(dev, WAN_CONNECTED);
- else
- x25_clear_call(card, new_lcn, 0, 0);
- }
- kfree(info);
- return 1;
-}
-
-/*============================================================================
- * Handle accepted call.
- */
-
-static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- unsigned new_lcn = mb->cmd.lcn;
- struct net_device* dev = get_dev_by_lcn(&card->wandev, new_lcn);
- x25_channel_t* chan;
-
- printk(KERN_INFO "%s: X.25 call accepted on LCN %d!\n",
- card->devname, new_lcn);
- if (dev == NULL)
- {
- printk(KERN_INFO
- "%s: clearing orphaned connection on LCN %d!\n",
- card->devname, new_lcn);
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
-
- /* Get channel configuration and notify router */
- chan = dev->priv;
- if (x25_get_chan_conf(card, chan) != CMD_OK)
- {
- x25_clear_call(card, new_lcn, 0, 0);
- return 1;
- }
- set_chan_state(dev, WAN_CONNECTED);
- return 1;
-}
-
-/*============================================================================
- * Handle cleared call.
- */
-
-static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- unsigned new_lcn = mb->cmd.lcn;
- struct net_device* dev = get_dev_by_lcn(&card->wandev, new_lcn);
-
- printk(KERN_INFO "%s: X.25 clear request on LCN %d! Cause:0x%02X "
- "Diagn:0x%02X\n",
- card->devname, new_lcn, mb->cmd.cause, mb->cmd.diagn);
- if (dev == NULL)
- return 1;
- set_chan_state(dev, WAN_DISCONNECTED);
- return ((cmd == X25_WRITE) && (lcn == new_lcn)) ? 0 : 1;
-}
-
-/*============================================================================
- * Handle X.25 restart event.
- */
-
-static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- wan_device_t* wandev = &card->wandev;
- struct net_device* dev;
-
- printk(KERN_INFO
- "%s: X.25 restart request! Cause:0x%02X Diagn:0x%02X\n",
- card->devname, mb->cmd.cause, mb->cmd.diagn);
-
- /* down all logical channels */
- for (dev = wandev->dev; dev; dev = dev->slave)
- set_chan_state(dev, WAN_DISCONNECTED);
- return (cmd == X25_WRITE) ? 0 : 1;
-}
-
-/*============================================================================
- * Handle timeout event.
- */
-static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
-{
- unsigned new_lcn = mb->cmd.lcn;
-
- if (mb->cmd.pktType == 0x05) /* call request time out */
- {
- struct net_device* dev = get_dev_by_lcn(&card->wandev, new_lcn);
-
- printk(KERN_INFO "%s: X.25 call timed timeout on LCN %d!\n",
- card->devname, new_lcn);
- if (dev)
- set_chan_state(dev, WAN_DISCONNECTED);
- }
- else printk(KERN_INFO "%s: X.25 packet 0x%02X timeout on LCN %d!\n",
- card->devname, mb->cmd.pktType, new_lcn);
- return 1;
-}
-
-/******* Miscellaneous ******************************************************/
-
-/*============================================================================
- * Establish physical connection.
- * o open HDLC and raise DTR
- *
- * Return: 0 connection established
- * 1 connection is in progress
- * <0 error
- */
-static int connect (sdla_t* card)
-{
- if (x25_open_hdlc(card) || x25_setup_hdlc(card))
- return -EIO;
- wanpipe_set_state(card, WAN_CONNECTING);
- return 1;
-}
-
-/*============================================================================
- * Tear down physical connection.
- * o close HDLC link
- * o drop DTR
- *
- * Return: 0
- * <0 error
- */
-static int disconnect (sdla_t* card)
-{
- wanpipe_set_state(card, WAN_DISCONNECTED);
- x25_set_intr_mode(card, 0); /* disable interrupt generation */
- x25_close_hdlc(card); /* close HDLC link */
- x25_set_dtr(card, 0); /* drop DTR */
- return 0;
-}
-
-/*============================================================================
- * Find network device by its channel number.
- */
-static struct net_device* get_dev_by_lcn (wan_device_t* wandev, unsigned lcn)
-{
- struct net_device* dev;
-
- for (dev = wandev->dev; dev; dev = dev->slave)
- if (((x25_channel_t*)dev->priv)->lcn == lcn)
- break;
- return dev;
-}
-
-/*============================================================================
- * Initiate connection on the logical channel.
- * o for PVC we just get channel configuration
- * o for SVCs place an X.25 call
- *
- * Return: 0 connected
- * >0 connection in progress
- * <0 failure
- */
-static int chan_connect (struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
-
- if (chan->svc)
- {
- if (!chan->addr[0])
- return -EINVAL; /* no destination address */
- printk(KERN_INFO "%s: placing X.25 call to %s ...\n",
- card->devname, chan->addr);
- if (x25_place_call(card, chan) != CMD_OK)
- return -EIO;
- set_chan_state(dev, WAN_CONNECTING);
- return 1;
- }
- else
- {
- if (x25_get_chan_conf(card, chan) != CMD_OK)
- return -EIO;
- set_chan_state(dev, WAN_CONNECTED);
- }
- return 0;
-}
-
-/*============================================================================
- * Disconnect logical channel.
- * o if SVC then clear X.25 call
- */
-static int chan_disc (struct net_device* dev)
-{
- x25_channel_t* chan = dev->priv;
-
- if (chan->svc)
- x25_clear_call(chan->card, chan->lcn, 0, 0);
- set_chan_state(dev, WAN_DISCONNECTED);
- return 0;
-}
-
-/*============================================================================
- * Set logical channel state.
- */
-static void set_chan_state (struct net_device* dev, int state)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- unsigned long flags;
-
- save_flags(flags);
- cli();
- if (chan->state != state)
- {
- switch (state)
- {
- case WAN_CONNECTED:
- printk (KERN_INFO "%s: interface %s connected!\n",
- card->devname, dev->name);
- *(unsigned short*)dev->dev_addr = htons(chan->lcn);
- chan->i_timeout_sofar = jiffies;
- break;
-
- case WAN_CONNECTING:
- printk (KERN_INFO "%s: interface %s connecting...\n",
- card->devname, dev->name);
- break;
-
- case WAN_DISCONNECTED:
- printk (KERN_INFO "%s: interface %s disconnected!\n",
- card->devname, dev->name);
- if (chan->svc)
- {
- *(unsigned short*)dev->dev_addr = 0;
- chan->lcn = 0;
- }
- break;
- }
- chan->state = state;
- }
- chan->state_tick = jiffies;
- restore_flags(flags);
-}
-
-/*============================================================================
- * Send packet on a logical channel.
- * When this function is called, tx_skb field of the channel data space
- * points to the transmit socket buffer. When transmission is complete,
- * release socket buffer and reset 'tbusy' flag.
- *
- * Return: 0 - transmission complete
- * 1 - busy
- *
- * Notes:
- * 1. If packet length is greater than MTU for this channel, we'll fragment
- * the packet into 'complete sequence' using M-bit.
- * 2. When transmission is complete, an event notification should be issued
- * to the router.
- */
-static int chan_send (struct net_device* dev, struct sk_buff* skb)
-{
- x25_channel_t* chan = dev->priv;
- sdla_t* card = chan->card;
- TX25Status* status = card->flags;
- unsigned len, qdm;
-
- /* Check to see if channel is ready */
- if (!(status->cflags[chan->ch_idx] & 0x40))
- return 1;
-
- if (skb->len > chan->tx_pkt_size)
- {
- len = chan->tx_pkt_size;
- qdm = 0x01; /* set M-bit (more data) */
- }
- else /* final packet */
- {
- len = skb->len;
- qdm = 0;
- }
- switch(x25_send(card, chan->lcn, qdm, len, skb->data))
- {
- case 0x00: /* success */
- chan->i_timeout_sofar = jiffies;
- if (qdm)
- {
- skb_pull(skb, len);
- return 1;
- }
- ++chan->ifstats.tx_packets;
- chan->ifstats.tx_bytes += skb->len;
- break;
-
- case 0x33: /* Tx busy */
- return 1;
-
- default: /* failure */
- ++chan->ifstats.tx_errors;
-/* return 1; */
- }
- return 0;
-}
-
-/*============================================================================
- * Parse X.25 call request data and fill x25_call_info_t structure.
- */
-
-static void parse_call_info (unsigned char* str, x25_call_info_t* info)
-{
- memset(info, 0, sizeof(x25_call_info_t));
- for (; *str; ++str)
- {
- int i;
- unsigned ch;
-
- if (*str == '-') switch (str[1])
- {
- case 'd': /* destination address */
- for (i = 0; i < 16; ++i)
- {
- ch = str[2+i];
- if (!is_digit(ch))
- break;
- info->dest[i] = ch;
- }
- break;
-
- case 's': /* source address */
- for (i = 0; i < 16; ++i)
- {
- ch = str[2+i];
- if (!is_digit(ch))
- break;
- info->src[i] = ch;
- }
- break;
-
- case 'u': /* user data */
- for (i = 0; i < 127; ++i)
- {
- ch = str[2+2*i];
- if (!is_hex_digit(ch))
- break;
- info->user[i] = hex_to_uint(&str[2+2*i], 2);
- }
- info->nuser = i;
- break;
-
- case 'f': /* facilities */
- for (i = 0; i < 64; ++i)
- {
- ch = str[2+4*i];
- if (!is_hex_digit(ch))
- break;
- info->facil[i].code =
- hex_to_uint(&str[2+4*i], 2);
- ch = str[4+4*i];
- if (!is_hex_digit(ch))
- break;
- info->facil[i].parm =
- hex_to_uint(&str[4+4*i], 2);
- }
- info->nfacil = i;
- break;
- }
- }
-}
-
-/*============================================================================
- * Convert line speed in bps to a number used by S502 code.
- */
-static unsigned char bps_to_speed_code (unsigned long bps)
-{
- unsigned char number;
-
- if (bps <= 1200) number = 0x01 ;
- else if (bps <= 2400) number = 0x02;
- else if (bps <= 4800) number = 0x03;
- else if (bps <= 9600) number = 0x04;
- else if (bps <= 19200) number = 0x05;
- else if (bps <= 38400) number = 0x06;
- else if (bps <= 45000) number = 0x07;
- else if (bps <= 56000) number = 0x08;
- else if (bps <= 64000) number = 0x09;
- else if (bps <= 74000) number = 0x0A;
- else if (bps <= 112000) number = 0x0B;
- else if (bps <= 128000) number = 0x0C;
- else number = 0x0D;
-
- return number;
-}
-
-/*============================================================================
- * Convert decimal string to unsigned integer.
- * If len != 0 then only 'len' characters of the string are converted.
- */
-static unsigned int dec_to_uint (unsigned char* str, int len)
-{
- unsigned val;
-
- if (!len) len = strlen(str);
- for (val = 0; len && is_digit(*str); ++str, --len)
- val = (val * 10) + (*str - (unsigned)'0');
- return val;
-}
-
-/*============================================================================
- * Convert hex string to unsigned integer.
- * If len != 0 then only 'len' characters of the string are conferted.
- */
-static unsigned int hex_to_uint (unsigned char* str, int len)
-{
- unsigned val, ch;
-
- if (!len) len = strlen(str);
- for (val = 0; len; ++str, --len)
- {
- ch = *str;
- if (is_digit(ch))
- val = (val << 4) + (ch - (unsigned)'0');
- else if (is_hex_digit(ch))
- val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10);
- else
- break;
- }
- return val;
-}
-
-
-static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto)
-{
- int i;
-
- if( proto == htons(ETH_P_IPX) ) {
- /* It's an IPX packet */
- if(!enable_IPX) {
- /* Return 1 so we don't pass it up the stack. */
- return 1;
- }
- } else {
- /* It's not IPX so pass it up the stack. */
- return 0;
- }
-
- if( sendpacket[16] == 0x90 &&
- sendpacket[17] == 0x04)
- {
- /* It's IPXWAN */
-
- if( sendpacket[2] == 0x02 &&
- sendpacket[34] == 0x00)
- {
- /* It's a timer request packet */
- printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname);
-
- /* Go through the routing options and answer no to every
- * option except Unnumbered RIP/SAP */
- for(i = 41; sendpacket[i] == 0x00; i += 5)
- {
- /* 0x02 is the option for Unnumbered RIP/SAP */
- if( sendpacket[i + 4] != 0x02)
- sendpacket[i + 1] = 0;
- }
-
- /* Skip over the extended Node ID option */
- if( sendpacket[i] == 0x04 )
- i += 8;
-
- /* We also want to turn off all header compression opt. */
- for(; sendpacket[i] == 0x80 ;)
- {
- sendpacket[i + 1] = 0;
- i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4;
- }
-
- /* Set the packet type to timer response */
- sendpacket[34] = 0x01;
-
- printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname);
- }
- else if( sendpacket[34] == 0x02 )
- {
- /* This is an information request packet */
- printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname);
-
- /* Set the packet type to information response */
- sendpacket[34] = 0x03;
-
- /* Set the router name */
- sendpacket[51] = 'X';
- sendpacket[52] = 'T';
- sendpacket[53] = 'P';
- sendpacket[54] = 'I';
- sendpacket[55] = 'P';
- sendpacket[56] = 'E';
- sendpacket[57] = '-';
- sendpacket[58] = CVHexToAscii(network_number >> 28);
- sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24);
- sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20);
- sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16);
- sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12);
- sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8);
- sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4);
- sendpacket[65] = CVHexToAscii(network_number & 0x0000000F);
- for(i = 66; i < 99; i+= 1)
- sendpacket[i] = 0;
-
- printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname);
- }
- else
- {
- printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname);
- return 0;
- }
-
- /* Set the WNodeID to our network address */
- sendpacket[35] = (unsigned char)(network_number >> 24);
- sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16);
- sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8);
- sendpacket[38] = (unsigned char)(network_number & 0x000000FF);
-
- return 1;
- } else {
- /* If we get here its an IPX-data packet, so it'll get passed up the stack.
- switch the network numbers */
- switch_net_numbers(sendpacket, network_number, 1);
- return 0;
- }
-}
-
-/*
- If incoming is 0 (outgoing)- if the net numbers is ours make it 0
- if incoming is 1 - if the net number is 0 make it ours
-
-*/
-
-static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming)
-{
- unsigned long pnetwork_number;
-
- pnetwork_number = (unsigned long)((sendpacket[6] << 24) +
- (sendpacket[7] << 16) + (sendpacket[8] << 8) +
- sendpacket[9]);
-
- if (!incoming)
- {
- /* If the destination network number is ours, make it 0 */
- if( pnetwork_number == network_number)
- {
- sendpacket[6] = sendpacket[7] = sendpacket[8] =
- sendpacket[9] = 0x00;
- }
- }
- else
- {
- /* If the incoming network is 0, make it ours */
- if( pnetwork_number == 0)
- {
- sendpacket[6] = (unsigned char)(network_number >> 24);
- sendpacket[7] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[8] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[9] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-
-
- pnetwork_number = (unsigned long)((sendpacket[18] << 24) +
- (sendpacket[19] << 16) + (sendpacket[20] << 8) +
- sendpacket[21]);
-
- if( !incoming )
- {
- /* If the source network is ours, make it 0 */
- if( pnetwork_number == network_number)
- {
- sendpacket[18] = sendpacket[19] = sendpacket[20] =
- sendpacket[21] = 0x00;
- }
- }
- else
- {
- /* If the source network is 0, make it ours */
- if( pnetwork_number == 0 )
- {
- sendpacket[18] = (unsigned char)(network_number >> 24);
- sendpacket[19] = (unsigned char)((network_number &
- 0x00FF0000) >> 16);
- sendpacket[20] = (unsigned char)((network_number &
- 0x0000FF00) >> 8);
- sendpacket[21] = (unsigned char)(network_number &
- 0x000000FF);
- }
- }
-} /* switch_net_numbers */
-
-
-/****** End *****************************************************************/
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)