aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wan/wanpipe_multppp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wan/wanpipe_multppp.c')
-rw-r--r--drivers/net/wan/wanpipe_multppp.c2358
1 files changed, 0 insertions, 2358 deletions
diff --git a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c
deleted file mode 100644
index 812a1183c50..00000000000
--- a/drivers/net/wan/wanpipe_multppp.c
+++ /dev/null
@@ -1,2358 +0,0 @@
-/*****************************************************************************
-* wanpipe_multppp.c Multi-Port PPP driver module.
-*
-* Authors: Nenad Corbic <ncorbic@sangoma.com>
-*
-* Copyright: (c) 1995-2001 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.
-* ============================================================================
-* Dec 15 2000 Updated for 2.4.X kernel
-* Nov 15 2000 Fixed the SyncPPP support for kernels 2.2.16 and higher.
-* The pppstruct has changed.
-* Jul 13 2000 Using the kernel Syncppp module on top of RAW Wanpipe CHDLC
-* module.
-*****************************************************************************/
-
-#include <linux/module.h>
-#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/slab.h> /* kmalloc(), kfree() */
-#include <linux/wanrouter.h> /* WAN router definitions */
-#include <linux/wanpipe.h> /* WANPIPE common user API definitions */
-#include <linux/if_arp.h> /* ARPHRD_* defines */
-#include <linux/jiffies.h> /* time_after() macro */
-
-#include <linux/in.h> /* sockaddr_in */
-#include <linux/inet.h>
-#include <linux/if.h>
-#include <asm/byteorder.h> /* htons(), etc. */
-#include <linux/sdlapci.h>
-#include <asm/io.h>
-
-#include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
-#include <linux/sdla_asy.h> /* CHDLC (async) API definitions */
-
-#include <linux/if_wanpipe_common.h> /* Socket Driver common area */
-#include <linux/if_wanpipe.h>
-
-
-#include <linux/inetdevice.h>
-#include <asm/uaccess.h>
-
-#include <net/syncppp.h>
-
-
-/****** Defines & Macros ****************************************************/
-
-#ifdef _DEBUG_
-#define STATIC
-#else
-#define STATIC static
-#endif
-
-/* reasons for enabling the timer interrupt on the adapter */
-#define TMR_INT_ENABLED_UDP 0x01
-#define TMR_INT_ENABLED_UPDATE 0x02
-#define TMR_INT_ENABLED_CONFIG 0x04
-
-#define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
-#define CHDLC_HDR_LEN 1
-
-#define IFF_POINTTOPOINT 0x10
-
-#define CHDLC_API 0x01
-
-#define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
-#define MAX_BH_BUFF 10
-
-#define CRC_LENGTH 2
-#define PPP_HEADER_LEN 4
-
-/******Data Structures*****************************************************/
-
-/* This structure is placed in the private data area of the device structure.
- * The card structure used to occupy the private area but now the following
- * structure will incorporate the card structure along with CHDLC specific data
- */
-
-typedef struct chdlc_private_area
-{
- void *if_ptr; /* General Pointer used by SPPP */
- wanpipe_common_t common;
- sdla_t *card;
- int TracingEnabled; /* For enabling Tracing */
- unsigned long curr_trace_addr; /* Used for Tracing */
- unsigned long start_trace_addr;
- unsigned long end_trace_addr;
- unsigned long base_addr_trace_buffer;
- unsigned long end_addr_trace_buffer;
- unsigned short number_trace_elements;
- unsigned available_buffer_space;
- unsigned long router_start_time;
- unsigned char route_status;
- unsigned char route_removed;
- unsigned long tick_counter; /* For 5s timeout counter */
- unsigned long router_up_time;
- u32 IP_address; /* IP addressing */
- u32 IP_netmask;
- unsigned char mc; /* Mulitcast support on/off */
- unsigned short udp_pkt_lgth; /* udp packet processing */
- char udp_pkt_src;
- char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
- unsigned short timer_int_enabled;
- char update_comms_stats; /* updating comms stats */
-
- //FIXME: add driver stats as per frame relay!
-
-} chdlc_private_area_t;
-
-/* Route Status options */
-#define NO_ROUTE 0x00
-#define ADD_ROUTE 0x01
-#define ROUTE_ADDED 0x02
-#define REMOVE_ROUTE 0x03
-
-
-/* variable for keeping track of enabling/disabling FT1 monitor status */
-static int rCount = 0;
-
-/* variable for tracking how many interfaces to open for WANPIPE on the
- two ports */
-
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
-/****** Function Prototypes *************************************************/
-/* WAN link driver entry points. These are called by the WAN router module. */
-static int update(struct wan_device* wandev);
-static int new_if(struct wan_device* wandev, struct net_device* dev,
- wanif_conf_t* conf);
-static int del_if(struct wan_device* wandev, struct net_device* dev);
-
-/* 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_send(struct sk_buff* skb, struct net_device* dev);
-static struct net_device_stats* if_stats(struct net_device* dev);
-
-static void if_tx_timeout(struct net_device *dev);
-
-/* CHDLC Firmware interface functions */
-static int chdlc_configure (sdla_t* card, void* data);
-static int chdlc_comm_enable (sdla_t* card);
-static int chdlc_comm_disable (sdla_t* card);
-static int chdlc_read_version (sdla_t* card, char* str);
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode);
-static int chdlc_send (sdla_t* card, void* data, unsigned len);
-static int chdlc_read_comm_err_stats (sdla_t* card);
-static int chdlc_read_op_stats (sdla_t* card);
-static int config_chdlc (sdla_t *card);
-
-
-/* Miscellaneous CHDLC Functions */
-static int set_chdlc_config (sdla_t* card);
-static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev);
-static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
-static int process_chdlc_exception(sdla_t *card);
-static int process_global_exception(sdla_t *card);
-static int update_comms_stats(sdla_t* card,
- chdlc_private_area_t* chdlc_priv_area);
-static void port_set_state (sdla_t *card, int);
-
-/* Interrupt handlers */
-static void wsppp_isr (sdla_t* card);
-static void rx_intr (sdla_t* card);
-static void timer_intr(sdla_t *);
-
-/* Miscellaneous functions */
-static int reply_udp( unsigned char *data, unsigned int mbox_len );
-static int intr_test( sdla_t* card);
-static int udp_pkt_type( struct sk_buff *skb , sdla_t* card);
-static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area);
-static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,
- chdlc_private_area_t* chdlc_priv_area);
-static unsigned short calc_checksum (char *, int);
-static void s508_lock (sdla_t *card, unsigned long *smp_flags);
-static void s508_unlock (sdla_t *card, unsigned long *smp_flags);
-static void send_ppp_term_request(struct net_device *dev);
-
-
-static int Intr_test_counter;
-/****** Public Functions ****************************************************/
-
-/*============================================================================
- * Cisco HDLC protocol initialization routine.
- *
- * This routine is called by the main WANPIPE module during setup. At this
- * point adapter is completely initialized and 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 wsppp_init (sdla_t* card, wandev_conf_t* conf)
-{
- unsigned char port_num;
- int err;
- unsigned long max_permitted_baud = 0;
- SHARED_MEMORY_INFO_STRUCT *flags;
-
- union
- {
- char str[80];
- } u;
- volatile CHDLC_MAILBOX_STRUCT* mb;
- CHDLC_MAILBOX_STRUCT* mb1;
- unsigned long timeout;
-
- /* Verify configuration ID */
- if (conf->config_id != WANCONFIG_MPPP) {
- printk(KERN_INFO "%s: invalid configuration ID %u!\n",
- card->devname, conf->config_id);
- return -EINVAL;
- }
-
- /* Find out which Port to use */
- if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){
- if (card->next){
-
- if (conf->comm_port != card->next->u.c.comm_port){
- card->u.c.comm_port = conf->comm_port;
- }else{
- printk(KERN_ERR "%s: ERROR - %s port used!\n",
- card->wandev.name, PORT(conf->comm_port));
- return -EINVAL;
- }
- }else{
- card->u.c.comm_port = conf->comm_port;
- }
- }else{
- printk(KERN_ERR "%s: ERROR - Invalid Port Selected!\n",
- card->wandev.name);
- return -EINVAL;
- }
-
-
- /* Initialize protocol-specific fields */
- if(card->hw.type != SDLA_S514){
-
- if (card->u.c.comm_port == WANOPT_PRI){
- card->mbox = (void *) card->hw.dpmbase;
- }else{
- card->mbox = (void *) card->hw.dpmbase +
- SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT;
- }
- }else{
- /* for a S514 adapter, set a pointer to the actual mailbox in the */
- /* allocated virtual memory area */
- if (card->u.c.comm_port == WANOPT_PRI){
- card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
- }else{
- card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT;
- }
- }
-
- mb = mb1 = card->mbox;
-
- if (!card->configured){
-
- /* The board will place an 'I' in the return code to indicate that it is
- ready to accept commands. We expect this to be completed in less
- than 1 second. */
-
- timeout = jiffies + 1 * HZ;
- while (mb->return_code != 'I') /* Wait 1s for board to initialize */
- if (time_after(jiffies, timeout)) break;
-
- if (mb->return_code != 'I') {
- printk(KERN_INFO
- "%s: Initialization not completed by adapter\n",
- card->devname);
- printk(KERN_INFO "Please contact Sangoma representative.\n");
- return -EIO;
- }
- }
-
- /* 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 (chdlc_read_version(card, u.str))
- return -EIO;
-
- printk(KERN_INFO "%s: Running Raw CHDLC firmware v%s\n"
- "%s: for Multi-Port PPP protocol.\n",
- card->devname,u.str,card->devname);
-
- card->isr = &wsppp_isr;
- card->poll = NULL;
- card->exec = NULL;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = &del_if;
- card->wandev.udp_port = conf->udp_port;
-
- card->wandev.new_if_cnt = 0;
-
- /* reset the number of times the 'update()' proc has been called */
- card->u.c.update_call_count = 0;
-
- card->wandev.ttl = conf->ttl;
- card->wandev.interface = conf->interface;
-
- if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&&
- card->hw.type != SDLA_S514){
- printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n",
- card->devname, PORT(card->u.c.comm_port));
- return -EIO;
- }
-
-
- card->wandev.clocking = conf->clocking;
-
- port_num = card->u.c.comm_port;
-
- /* Setup Port Bps */
-
- if(card->wandev.clocking) {
- if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
- /* For Primary Port 0 */
- max_permitted_baud =
- (card->hw.type == SDLA_S514) ?
- PRI_MAX_BAUD_RATE_S514 :
- PRI_MAX_BAUD_RATE_S508;
- }
- else if(port_num == WANOPT_SEC) {
- /* For Secondary Port 1 */
- max_permitted_baud =
- (card->hw.type == SDLA_S514) ?
- SEC_MAX_BAUD_RATE_S514 :
- SEC_MAX_BAUD_RATE_S508;
- }
-
- if(conf->bps > max_permitted_baud) {
- conf->bps = max_permitted_baud;
- printk(KERN_INFO "%s: Baud too high!\n",
- card->wandev.name);
- printk(KERN_INFO "%s: Baud rate set to %lu bps\n",
- card->wandev.name, max_permitted_baud);
- }
-
- card->wandev.bps = conf->bps;
- }else{
- card->wandev.bps = 0;
- }
-
- /* Setup the Port MTU */
- if((port_num == WANOPT_PRI) || card->u.c.receive_only) {
-
- /* For Primary Port 0 */
- card->wandev.mtu =
- (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) :
- CHDLC_DFLT_DATA_LEN;
- } else if(port_num == WANOPT_SEC) {
- /* For Secondary Port 1 */
- card->wandev.mtu =
- (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ?
- min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) :
- CHDLC_DFLT_DATA_LEN;
- }
-
- /* Add on a PPP Header */
- card->wandev.mtu += PPP_HEADER_LEN;
-
- /* Set up the interrupt status area */
- /* Read the CHDLC Configuration and obtain:
- * Ptr to shared memory infor struct
- * Use this pointer to calculate the value of card->u.c.flags !
- */
- mb1->buffer_length = 0;
- mb1->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
- if(err != COMMAND_OK) {
- clear_bit(1, (void*)&card->wandev.critical);
-
- if(card->hw.type != SDLA_S514)
- enable_irq(card->hw.irq);
-
- chdlc_error(card, err, mb1);
- return -EIO;
- }
-
- if(card->hw.type == SDLA_S514){
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct));
- }else{
- card->u.c.flags = (void *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
- ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
- }
-
- flags = card->u.c.flags;
-
- /* This is for the ports link state */
- card->wandev.state = WAN_DUALPORT;
- card->u.c.state = WAN_DISCONNECTED;
-
-
- if (!card->wandev.piggyback){
- err = intr_test(card);
-
- if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) {
- printk(KERN_ERR "%s: Interrupt test failed (%i)\n",
- card->devname, Intr_test_counter);
- printk(KERN_ERR "%s: Please choose another interrupt\n",
- card->devname);
- return -EIO;
- }
-
- printk(KERN_INFO "%s: Interrupt test passed (%i)\n",
- card->devname, Intr_test_counter);
- }
-
-
- if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: Failed to set interrupt triggers!\n",
- card->devname);
- return -EIO;
- }
-
- /* Mask the Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~APP_INT_ON_TIMER;
-
- printk(KERN_INFO "\n");
-
- return 0;
-}
-
-/******* WAN Device Driver Entry Points *************************************/
-
-/*============================================================================
- * Update device status & statistics
- * This procedure is called when updating the PROC file system and returns
- * various communications statistics. These statistics are accumulated from 3
- * different locations:
- * 1) The 'if_stats' recorded for the device.
- * 2) Communication error statistics on the adapter.
- * 3) CHDLC operational statistics on the adapter.
- * The board level statistics are read during a timer interrupt. Note that we
- * read the error and operational statistics during consecitive timer ticks so
- * as to minimize the time that we are inside the interrupt handler.
- *
- */
-static int update(struct wan_device* wandev)
-{
- sdla_t* card = wandev->private;
- struct net_device* dev;
- volatile chdlc_private_area_t* chdlc_priv_area;
- SHARED_MEMORY_INFO_STRUCT *flags;
- unsigned long timeout;
-
- /* sanity checks */
- if((wandev == NULL) || (wandev->private == NULL))
- return -EFAULT;
-
- if(wandev->state == WAN_UNCONFIGURED)
- return -ENODEV;
-
- /* more sanity checks */
- if(!card->u.c.flags)
- return -ENODEV;
-
- if((dev=card->wandev.dev) == NULL)
- return -ENODEV;
-
- if((chdlc_priv_area=dev->priv) == NULL)
- return -ENODEV;
-
- flags = card->u.c.flags;
-
- if(chdlc_priv_area->update_comms_stats){
- return -EAGAIN;
- }
-
- /* we will need 2 timer interrupts to complete the */
- /* reading of the statistics */
- chdlc_priv_area->update_comms_stats = 2;
- flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
- chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE;
-
- /* wait a maximum of 1 second for the statistics to be updated */
- timeout = jiffies + 1 * HZ;
- for(;;) {
- if(chdlc_priv_area->update_comms_stats == 0)
- break;
- if (time_after(jiffies, timeout)){
- chdlc_priv_area->update_comms_stats = 0;
- chdlc_priv_area->timer_int_enabled &=
- ~TMR_INT_ENABLED_UPDATE;
- return -EAGAIN;
- }
- }
-
- 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(struct wan_device* wandev, struct net_device* pdev,
- wanif_conf_t* conf)
-{
-
- struct ppp_device *pppdev = (struct ppp_device *)pdev;
- struct net_device *dev = NULL;
- struct sppp *sp;
- sdla_t* card = wandev->private;
- chdlc_private_area_t* chdlc_priv_area;
-
- 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 */
- chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL);
-
- if(chdlc_priv_area == NULL)
- return -ENOMEM;
-
- memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t));
-
- chdlc_priv_area->card = card;
-
- /* initialize data */
- strcpy(card->u.c.if_name, conf->name);
-
- if(card->wandev.new_if_cnt > 0) {
- kfree(chdlc_priv_area);
- return -EEXIST;
- }
-
- card->wandev.new_if_cnt++;
-
- chdlc_priv_area->TracingEnabled = 0;
-
- //We don't need this any more
- chdlc_priv_area->route_status = NO_ROUTE;
- chdlc_priv_area->route_removed = 0;
-
- printk(KERN_INFO "%s: Firmware running in HDLC STREAMING Mode\n",
- wandev->name);
-
- /* Setup wanpipe as a router (WANPIPE) or as an API */
- if( strcmp(conf->usedby, "WANPIPE") == 0) {
- printk(KERN_INFO "%s: Driver running in WANPIPE mode!\n",
- wandev->name);
- card->u.c.usedby = WANPIPE;
- } else {
- printk(KERN_INFO
- "%s: API Mode is not supported for SyncPPP!\n",
- wandev->name);
- kfree(chdlc_priv_area);
- return -EINVAL;
- }
-
- /* Get Multicast Information */
- chdlc_priv_area->mc = conf->mc;
-
-
- chdlc_priv_area->if_ptr = pppdev;
-
- /* prepare network device data space for registration */
-
- strcpy(dev->name,card->u.c.if_name);
-
- /* Attach PPP protocol layer to pppdev
- * The sppp_attach() will initilize the dev structure
- * and setup ppp layer protocols.
- * All we have to do is to bind in:
- * if_open(), if_close(), if_send() and get_stats() functions.
- */
- sppp_attach(pppdev);
- dev = pppdev->dev;
- sp = &pppdev->sppp;
-
- /* Enable PPP Debugging */
- // FIXME Fix this up somehow
- //sp->pp_flags |= PP_DEBUG;
- sp->pp_flags &= ~PP_CISCO;
-
- dev->init = &if_init;
- dev->priv = chdlc_priv_area;
-
- return 0;
-}
-
-
-
-
-/*============================================================================
- * Delete logical channel.
- */
-static int del_if(struct wan_device* wandev, struct net_device* dev)
-{
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- sdla_t *card = chdlc_priv_area->card;
- unsigned long smp_lock;
-
- /* Detach the PPP layer */
- printk(KERN_INFO "%s: Detaching SyncPPP Module from %s\n",
- wandev->name,dev->name);
-
- lock_adapter_irq(&wandev->lock,&smp_lock);
-
- sppp_detach(dev);
- chdlc_priv_area->if_ptr=NULL;
-
- chdlc_set_intr_mode(card, 0);
- if (card->u.c.comm_enabled)
- chdlc_comm_disable(card);
- unlock_adapter_irq(&wandev->lock,&smp_lock);
-
- port_set_state(card, WAN_DISCONNECTED);
-
- 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)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
- struct wan_device* wandev = &card->wandev;
-
- /* NOTE: Most of the dev initialization was
- * done in sppp_attach(), called by new_if()
- * function. All we have to do here is
- * to link four major routines below.
- */
-
- /* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
- dev->tx_timeout = &if_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-
-
- /* Initialize hardware parameters */
- dev->irq = wandev->irq;
- dev->dma = wandev->dma;
- dev->base_addr = wandev->ioport;
- dev->mem_start = wandev->maddr;
- dev->mem_end = wandev->maddr + wandev->msize - 1;
-
- /* Set transmit buffer queue length
- * If we over fill this queue the packets will
- * be droped by the kernel.
- * sppp_attach() sets this to 10, but
- * 100 will give us more room at low speeds.
- */
- dev->tx_queue_len = 100;
-
- return 0;
-}
-
-
-/*============================================================================
- * Handle transmit timeout event from netif watchdog
- */
-static void if_tx_timeout(struct net_device *dev)
-{
- chdlc_private_area_t* chan = dev->priv;
- sdla_t *card = chan->card;
-
- /* If our device stays busy for at least 5 seconds then we will
- * kick start the device by making dev->tbusy = 0. We expect
- * that our device never stays busy more than 5 seconds. So this
- * is only used as a last resort.
- */
-
- ++card->wandev.stats.collisions;
-
- printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name);
- netif_wake_queue (dev);
-}
-
-
-/*============================================================================
- * Open network interface.
- * o enable communications and interrupts.
- * o prevent module from unloading by incrementing use count
- *
- * Return 0 if O.k. or errno.
- */
-static int if_open(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
- struct timeval tv;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
-
- /* Only one open per interface is allowed */
- if (netif_running(dev))
- return -EBUSY;
-
- /* Start PPP Layer */
- if (sppp_open(dev)){
- return -EIO;
- }
-
- do_gettimeofday(&tv);
- chdlc_priv_area->router_start_time = tv.tv_sec;
-
- netif_start_queue(dev);
-
- wanpipe_open(card);
-
- chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
- flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
- return 0;
-}
-
-/*============================================================================
- * Close network interface.
- * o if this is the last close, then disable communications and interrupts.
- * o reset flags.
- */
-static int if_close(struct net_device* dev)
-{
- chdlc_private_area_t* chdlc_priv_area = dev->priv;
- sdla_t* card = chdlc_priv_area->card;
-
- /* Stop the PPP Layer */
- sppp_close(dev);
- netif_stop_queue(dev);
-
- wanpipe_close(card);
-
- return 0;
-}
-
-/*============================================================================
- * Send a packet on a network interface.
- * o set tbusy flag (marks start of the transmission) to block a timer-based
- * transmit from overlapping.
- * o check link state. If link is not up, then drop the packet.
- * o execute adapter send command.
- * 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)
-{
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- sdla_t *card = chdlc_priv_area->card;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
- int udp_type = 0;
- unsigned long smp_flags;
- int err=0;
-
- netif_stop_queue(dev);
-
-
- if (skb == NULL){
- /* If we get here, some higher layer thinks we've missed an
- * tx-done interrupt.
- */
- printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n",
- card->devname, dev->name);
-
- netif_wake_queue(dev);
- return 0;
- }
-
- if (ntohs(skb->protocol) != htons(PVC_PROT)){
- /* check the udp packet type */
-
- udp_type = udp_pkt_type(skb, card);
- if (udp_type == UDP_CPIPE_TYPE){
- if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev,
- chdlc_priv_area)){
- chdlc_int->interrupt_permission |=
- APP_INT_ON_TIMER;
- }
- netif_start_queue(dev);
- return 0;
- }
- }
-
- /* Lock the 508 Card: SMP is supported */
- if(card->hw.type != SDLA_S514){
- s508_lock(card,&smp_flags);
- }
-
- if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){
-
- printk(KERN_INFO "%s: Critical in if_send: %lx\n",
- card->wandev.name,card->wandev.critical);
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_crit_exit;
- }
-
- if (card->wandev.state != WAN_CONNECTED){
- ++card->wandev.stats.tx_dropped;
- netif_start_queue(dev);
- goto if_send_crit_exit;
- }
-
- if (chdlc_send(card, skb->data, skb->len)){
- netif_stop_queue(dev);
-
- }else{
- ++card->wandev.stats.tx_packets;
- card->wandev.stats.tx_bytes += skb->len;
- dev->trans_start = jiffies;
- netif_start_queue(dev);
- }
-
-if_send_crit_exit:
- if (!(err=netif_queue_stopped(dev))){
- dev_kfree_skb_any(skb);
- }else{
- chdlc_priv_area->tick_counter = jiffies;
- chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
- }
-
- clear_bit(SEND_CRIT, (void*)&card->wandev.critical);
- if(card->hw.type != SDLA_S514){
- s508_unlock(card,&smp_flags);
- }
-
- return err;
-}
-
-
-/*============================================================================
- * Reply to UDP Management system.
- * Return length of reply.
- */
-static int reply_udp( unsigned char *data, unsigned int mbox_len )
-{
-
- unsigned short len, udp_length, temp, ip_length;
- unsigned long ip_temp;
- int even_bound = 0;
- chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data;
-
- /* Set length of packet */
- len = sizeof(ip_pkt_t)+
- sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- sizeof(trace_info_t)+
- mbox_len;
-
- /* fill in UDP reply */
- c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;
-
- /* fill in UDP length */
- udp_length = sizeof(udp_pkt_t)+
- sizeof(wp_mgmt_t)+
- sizeof(cblock_t)+
- sizeof(trace_info_t)+
- mbox_len;
-
- /* put it on an even boundary */
- if ( udp_length & 0x0001 ) {
- udp_length += 1;
- len += 1;
- even_bound = 1;
- }
-
- temp = (udp_length<<8)|(udp_length>>8);
- c_udp_pkt->udp_pkt.udp_length = temp;
-
- /* swap UDP ports */
- temp = c_udp_pkt->udp_pkt.udp_src_port;
- c_udp_pkt->udp_pkt.udp_src_port =
- c_udp_pkt->udp_pkt.udp_dst_port;
- c_udp_pkt->udp_pkt.udp_dst_port = temp;
-
- /* add UDP pseudo header */
- temp = 0x1100;
- *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp;
- temp = (udp_length<<8)|(udp_length>>8);
- *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp;
-
-
- /* calculate UDP checksum */
- c_udp_pkt->udp_pkt.udp_checksum = 0;
- c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);
-
- /* fill in IP length */
- ip_length = len;
- temp = (ip_length<<8)|(ip_length>>8);
- c_udp_pkt->ip_pkt.total_length = temp;
-
- /* swap IP addresses */
- ip_temp = c_udp_pkt->ip_pkt.ip_src_address;
- c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address;
- c_udp_pkt->ip_pkt.ip_dst_address = ip_temp;
-
- /* fill in IP checksum */
- c_udp_pkt->ip_pkt.hdr_checksum = 0;
- c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));
-
- return len;
-
-} /* reply_udp */
-
-unsigned short calc_checksum (char *data, int len)
-{
- unsigned short temp;
- unsigned long sum=0;
- int i;
-
- for( i = 0; i <len; i+=2 ) {
- memcpy(&temp,&data[i],2);
- sum += (unsigned long)temp;
- }
-
- while (sum >> 16 ) {
- sum = (sum & 0xffffUL) + (sum >> 16);
- }
-
- temp = (unsigned short)sum;
- temp = ~temp;
-
- if( temp == 0 )
- temp = 0xffff;
-
- return temp;
-}
-
-
-/*============================================================================
- * Get ethernet-style interface statistics.
- * Return a pointer to struct enet_statistics.
- */
-static struct net_device_stats* if_stats(struct net_device* dev)
-{
- sdla_t *my_card;
- chdlc_private_area_t* chdlc_priv_area;
-
- /* Shutdown bug fix. In del_if() we kill
- * dev->priv pointer. This function, gets
- * called after del_if(), thus check
- * if pointer has been deleted */
- if ((chdlc_priv_area=dev->priv) == NULL)
- return NULL;
-
- my_card = chdlc_priv_area->card;
- return &my_card->wandev.stats;
-}
-
-
-/****** Cisco HDLC Firmware Interface Functions *******************************/
-
-/*============================================================================
- * Read firmware code version.
- * Put code version as ASCII string in str.
- */
-static int chdlc_read_version (sdla_t* card, char* str)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int len;
- char err;
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- }
- else if (str) { /* is not null */
- len = mb->buffer_length;
- memcpy(str, mb->data, len);
- str[len] = '\0';
- }
- return (err);
-}
-
-/*-----------------------------------------------------------------------------
- * Configure CHDLC firmware.
- */
-static int chdlc_configure (sdla_t* card, void* data)
-{
- int err;
- CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
- int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT);
-
- mailbox->buffer_length = data_length;
- memcpy(mailbox->data, data, data_length);
- mailbox->command = SET_CHDLC_CONFIGURATION;
- err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
-
- if (err != COMMAND_OK) chdlc_error (card, err, mailbox);
-
- return err;
-}
-
-
-/*============================================================================
- * Set interrupt mode -- HDLC Version.
- */
-
-static int chdlc_set_intr_mode (sdla_t* card, unsigned mode)
-{
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_INT_TRIGGERS_STRUCT* int_data =
- (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;
- int err;
-
- int_data->CHDLC_interrupt_triggers = mode;
- int_data->IRQ = card->hw.irq;
- int_data->interrupt_timer = 1;
-
- mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);
- mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error (card, err, mb);
- return err;
-}
-
-
-/*============================================================================
- * Enable communications.
- */
-
-static int chdlc_comm_enable (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = ENABLE_CHDLC_COMMUNICATIONS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card, err, mb);
- else
- card->u.c.comm_enabled=1;
-
- return err;
-}
-
-/*============================================================================
- * Disable communications and Drop the Modem lines (DCD and RTS).
- */
-static int chdlc_comm_disable (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = DISABLE_CHDLC_COMMUNICATIONS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
-
- return err;
-}
-
-/*============================================================================
- * Read communication error statistics.
- */
-static int chdlc_read_comm_err_stats (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = READ_COMMS_ERROR_STATS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error(card,err,mb);
- return err;
-}
-
-
-/*============================================================================
- * Read CHDLC operational statistics.
- */
-static int chdlc_read_op_stats (sdla_t* card)
-{
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
-
- mb->buffer_length = 0;
- mb->command = READ_CHD