diff options
Diffstat (limited to 'drivers/net/wan/sdla_ppp.c')
-rw-r--r-- | drivers/net/wan/sdla_ppp.c | 3430 |
1 files changed, 0 insertions, 3430 deletions
diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c deleted file mode 100644 index a4b489cccbbf..000000000000 --- a/drivers/net/wan/sdla_ppp.c +++ /dev/null @@ -1,3430 +0,0 @@ -/***************************************************************************** -* sdla_ppp.c WANPIPE(tm) Multiprotocol WAN Link Driver. PPP module. -* -* Author: 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. -* ============================================================================ -* Feb 28, 2001 Nenad Corbic o Updated if_tx_timeout() routine for -* 2.4.X kernels. -* Nov 29, 2000 Nenad Corbic o Added the 2.4.x kernel support: -* get_ip_address() function has moved -* into the ppp_poll() routine. It cannot -* be called from an interrupt. -* Nov 07, 2000 Nenad Corbic o Added security features for UDP debugging: -* Deny all and specify allowed requests. -* May 02, 2000 Nenad Corbic o Added the dynamic interface shutdown -* option. When the link goes down, the -* network interface IFF_UP flag is reset. -* Mar 06, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery. -* Feb 25, 2000 Nenad Corbic o Fixed the FT1 UDP debugger problem. -* Feb 09, 2000 Nenad Coribc o Shutdown bug fix. update() was called -* with NULL dev pointer: no check. -* Jan 24, 2000 Nenad Corbic o Disabled use of CMD complete inter. -* Dev 15, 1999 Nenad Corbic o Fixed up header files for 2.0.X kernels -* Oct 25, 1999 Nenad Corbic o Support for 2.0.X kernels -* Moved dynamic route processing into -* a polling routine. -* Oct 07, 1999 Nenad Corbic o Support for S514 PCI card. -* Gideon Hack o UPD and Updates executed using timer interrupt -* Sep 10, 1999 Nenad Corbic o Fixed up the /proc statistics -* Jul 20, 1999 Nenad Corbic o Remove the polling routines and use -* interrupts instead. -* Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X Kernels. -* Aug 13, 1998 Jaspreet Singh o Improved Line Tracing. -* Jun 22, 1998 David Fong o Added remote IP address assignment -* Mar 15, 1998 Alan Cox o 2.1.8x basic port. -* Apr 16, 1998 Jaspreet Singh o using htons() for the IPX protocol. -* Dec 09, 1997 Jaspreet Singh o Added PAP and CHAP. -* o Implemented new routines like -* ppp_set_inbnd_auth(), ppp_set_outbnd_auth(), -* tokenize() and strstrip(). -* Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs -* while they have been disabled. -* Nov 24, 1997 Jaspreet Singh o Fixed another RACE condition caused by -* disabling and enabling of irqs. -* o Added new counters for stats on disable/enable -* IRQs. -* Nov 10, 1997 Jaspreet Singh o Initialized 'skb->mac.raw' to 'skb->data' -* before every netif_rx(). -* o Free up the device structure in del_if(). -* Nov 07, 1997 Jaspreet Singh o Changed the delay to zero for Line tracing -* command. -* Oct 20, 1997 Jaspreet Singh o Added hooks in for Router UP time. -* Oct 16, 1997 Jaspreet Singh o The critical flag is used to maintain flow -* control by avoiding RACE conditions. The -* cli() and restore_flags() are taken out. -* A new structure, "ppp_private_area", is added -* to provide Driver Statistics. -* Jul 21, 1997 Jaspreet Singh o Protected calls to sdla_peek() by adding -* save_flags(), cli() and restore_flags(). -* Jul 07, 1997 Jaspreet Singh o Added configurable TTL for UDP packets -* o Added ability to discard mulitcast and -* broacast source addressed packets. -* Jun 27, 1997 Jaspreet Singh o Added FT1 monitor capabilities -* New case (0x25) statement in if_send routine. -* Added a global variable rCount to keep track -* of FT1 status enabled on the board. -* May 22, 1997 Jaspreet Singh o Added change in the PPP_SET_CONFIG command for -* 508 card to reflect changes in the new -* ppp508.sfm for supporting:continous transmission -* of Configure-Request packets without receiving a -* reply -* OR-ed 0x300 to conf_flags -* o Changed connect_tmout from 900 to 0 -* May 21, 1997 Jaspreet Singh o Fixed UDP Management for multiple boards -* Apr 25, 1997 Farhan Thawar o added UDP Management stuff -* Mar 11, 1997 Farhan Thawar Version 3.1.1 -* o fixed (+1) bug in rx_intr() -* o changed if_send() to return 0 if -* wandev.critical() is true -* o free socket buffer in if_send() if -* returning 0 -* Jan 15, 1997 Gene Kozin Version 3.1.0 -* o implemented exec() entry point -* Jan 06, 1997 Gene Kozin Initial version. -*****************************************************************************/ - -#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 <asm/byteorder.h> /* htons(), etc. */ -#include <linux/in.h> /* sockaddr_in */ -#include <linux/jiffies.h> /* time_after() macro */ - - -#include <asm/uaccess.h> -#include <linux/inetdevice.h> -#include <linux/netdevice.h> - -#include <linux/if.h> -#include <linux/sdla_ppp.h> /* PPP firmware API definitions */ -#include <linux/sdlasfm.h> /* S514 Type Definition */ -/****** Defines & Macros ****************************************************/ - -#define PPP_DFLT_MTU 1500 /* default MTU */ -#define PPP_MAX_MTU 4000 /* maximum MTU */ -#define PPP_HDR_LEN 1 - -#define MAX_IP_ERRORS 100 - -#define CONNECT_TIMEOUT (90*HZ) /* link connection timeout */ -#define HOLD_DOWN_TIME (5*HZ) /* link hold down time : Changed from 30 to 5 */ - -/* For handle_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))) - -/* Macro for enabling/disabling debugging comments */ -//#define NEX_DEBUG -#ifdef NEX_DEBUG -#define NEX_PRINTK(format, a...) printk(format, ## a) -#else -#define NEX_PRINTK(format, a...) -#endif /* NEX_DEBUG */ - -#define DCD(a) ( a & 0x08 ? "HIGH" : "LOW" ) -#define CTS(a) ( a & 0x20 ? "HIGH" : "LOW" ) -#define LCP(a) ( a == 0x09 ? "OPEN" : "CLOSED" ) -#define IP(a) ( a == 0x09 ? "ENABLED" : "DISABLED" ) - -#define TMR_INT_ENABLED_UPDATE 0x01 -#define TMR_INT_ENABLED_PPP_EVENT 0x02 -#define TMR_INT_ENABLED_UDP 0x04 -#define TMR_INT_ENABLED_CONFIG 0x20 - -/* Set Configuraton Command Definitions */ -#define PERCENT_TX_BUFF 60 -#define TIME_BETWEEN_CONF_REQ 30 -#define TIME_BETWEEN_PAP_CHAP_REQ 30 -#define WAIT_PAP_CHAP_WITHOUT_REPLY 300 -#define WAIT_AFTER_DCD_CTS_LOW 5 -#define TIME_DCD_CTS_LOW_AFTER_LNK_DOWN 10 -#define WAIT_DCD_HIGH_AFTER_ENABLE_COMM 900 -#define MAX_CONF_REQ_WITHOUT_REPLY 10 -#define MAX_TERM_REQ_WITHOUT_REPLY 2 -#define NUM_CONF_NAK_WITHOUT_REPLY 5 -#define NUM_AUTH_REQ_WITHOUT_REPLY 10 - -#define END_OFFSET 0x1F0 - - -/******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 PPP specific data - */ - -typedef struct ppp_private_area -{ - struct net_device *slave; - sdla_t* card; - unsigned long router_start_time; /*router start time in sec */ - unsigned long tick_counter; /*used for 5 second counter*/ - unsigned mc; /*multicast support on or off*/ - unsigned char enable_IPX; - unsigned long network_number; - unsigned char pap; - unsigned char chap; - unsigned char sysname[31]; /* system name for in-bnd auth*/ - unsigned char userid[511]; /* list of user ids */ - unsigned char passwd[511]; /* list of passwords */ - unsigned protocol; /* SKB Protocol */ - u32 ip_local; /* Local IP Address */ - u32 ip_remote; /* remote IP Address */ - - u32 ip_local_tmp; - u32 ip_remote_tmp; - - unsigned char timer_int_enabled; /* Who enabled the timer inter*/ - unsigned char update_comms_stats; /* Used by update function */ - unsigned long curr_trace_addr; /* Trace information */ - unsigned long start_trace_addr; - unsigned long end_trace_addr; - - unsigned char interface_down; /* Brind down interface when channel - goes down */ - unsigned long config_wait_timeout; /* After if_open() if in dynamic if mode, - wait a few seconds before configuring */ - - unsigned short udp_pkt_lgth; - char udp_pkt_src; - char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; - - /* PPP specific statistics */ - - if_send_stat_t if_send_stat; - rx_intr_stat_t rx_intr_stat; - pipe_mgmt_stat_t pipe_mgmt_stat; - - unsigned long router_up_time; - - /* Polling work queue entry. Each interface - * has its own work queue entry, which is used - * to defer events from the interrupt */ - struct work_struct poll_work; - struct timer_list poll_delay_timer; - - u8 gateway; - u8 config_ppp; - u8 ip_error; - -}ppp_private_area_t; - -/* variable for keeping track of enabling/disabling FT1 monitor status */ -static int rCount = 0; - -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); - -/* WANPIPE-specific entry points */ -static int wpp_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 void if_tx_timeout(struct net_device *dev); - -static int if_rebuild_hdr(struct sk_buff *skb); -static struct net_device_stats *if_stats(struct net_device *dev); -static int if_send(struct sk_buff *skb, struct net_device *dev); - - -/* PPP firmware interface functions */ -static int ppp_read_version(sdla_t *card, char *str); -static int ppp_set_outbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area); -static int ppp_set_inbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area); -static int ppp_configure(sdla_t *card, void *data); -static int ppp_set_intr_mode(sdla_t *card, unsigned char mode); -static int ppp_comm_enable(sdla_t *card); -static int ppp_comm_disable(sdla_t *card); -static int ppp_comm_disable_shutdown(sdla_t *card); -static int ppp_get_err_stats(sdla_t *card); -static int ppp_send(sdla_t *card, void *data, unsigned len, unsigned proto); -static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb); - -static void wpp_isr(sdla_t *card); -static void rx_intr(sdla_t *card); -static void event_intr(sdla_t *card); -static void timer_intr(sdla_t *card); - -/* Background polling routines */ -static void process_route(sdla_t *card); -static void retrigger_comm(sdla_t *card); - -/* Miscellaneous functions */ -static int read_info( sdla_t *card ); -static int read_connection_info (sdla_t *card); -static void remove_route( sdla_t *card ); -static int config508(struct net_device *dev, sdla_t *card); -static void show_disc_cause(sdla_t * card, unsigned cause); -static int reply_udp( unsigned char *data, unsigned int mbox_len ); -static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev, - ppp_private_area_t *ppp_priv_area); -static void init_ppp_tx_rx_buff( sdla_t *card ); -static int intr_test( sdla_t *card ); -static int udp_pkt_type( struct sk_buff *skb , sdla_t *card); -static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area); -static void init_global_statistics( sdla_t *card ); -static int tokenize(char *str, char **tokens); -static char* strstrip(char *str, char *s); -static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev, - struct sk_buff *skb); - -static int config_ppp (sdla_t *); -static void ppp_poll(struct net_device *dev); -static void trigger_ppp_poll(struct net_device *dev); -static void ppp_poll_delay (unsigned long dev_ptr); - - -static int Read_connection_info; -static int Intr_test_counter; -static unsigned short available_buffer_space; - - -/* 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_PX, - unsigned long network_number, unsigned short proto); - -/* Lock Functions */ -static void s508_lock (sdla_t *card, unsigned long *smp_flags); -static void s508_unlock (sdla_t *card, unsigned long *smp_flags); - -static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, - struct sk_buff *skb, struct net_device* dev, - ppp_private_area_t* ppp_priv_area ); -static unsigned short calc_checksum (char *data, int len); -static void disable_comm (sdla_t *card); -static int detect_and_fix_tx_bug (sdla_t *card); - -/****** Public Functions ****************************************************/ - -/*============================================================================ - * PPP 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 wpp_init(sdla_t *card, wandev_conf_t *conf) -{ - ppp_flags_t *flags; - union - { - char str[80]; - } u; - - /* Verify configuration ID */ - if (conf->config_id != WANCONFIG_PPP) { - - printk(KERN_INFO "%s: invalid configuration ID %u!\n", - card->devname, conf->config_id); - return -EINVAL; - - } - - /* Initialize miscellaneous pointers to structures on the adapter */ - switch (card->hw.type) { - - case SDLA_S508: - card->mbox =(void*)(card->hw.dpmbase + PPP508_MB_OFFS); - card->flags=(void*)(card->hw.dpmbase + PPP508_FLG_OFFS); - break; - - case SDLA_S514: - card->mbox =(void*)(card->hw.dpmbase + PPP514_MB_OFFS); - card->flags=(void*)(card->hw.dpmbase + PPP514_FLG_OFFS); - break; - - default: - return -EINVAL; - - } - flags = card->flags; - - /* 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 (ppp_read_version(card, NULL) || ppp_read_version(card, u.str)) - return -EIO; - - printk(KERN_INFO "%s: running PPP firmware v%s\n",card->devname, u.str); - /* Adjust configuration and set defaults */ - card->wandev.mtu = (conf->mtu) ? - min_t(unsigned int, conf->mtu, PPP_MAX_MTU) : PPP_DFLT_MTU; - - card->wandev.bps = conf->bps; - card->wandev.interface = conf->interface; - card->wandev.clocking = conf->clocking; - card->wandev.station = conf->station; - card->isr = &wpp_isr; - card->poll = NULL; - card->exec = &wpp_exec; - 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.ttl = conf->ttl; - card->wandev.state = WAN_DISCONNECTED; - card->disable_comm = &disable_comm; - card->irq_dis_if_send_count = 0; - card->irq_dis_poll_count = 0; - card->u.p.authenticator = conf->u.ppp.authenticator; - card->u.p.ip_mode = conf->u.ppp.ip_mode ? - conf->u.ppp.ip_mode : WANOPT_PPP_STATIC; - card->TracingEnabled = 0; - Read_connection_info = 1; - - /* initialize global statistics */ - init_global_statistics( card ); - - - - if (!card->configured){ - int err; - - Intr_test_counter = 0; - err = intr_test(card); - - if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { - printk("%s: Interrupt Test Failed, Counter: %i\n", - card->devname, Intr_test_counter); - printk( "%s: Please choose another interrupt\n",card->devname); - return -EIO; - } - - printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n", - card->devname, Intr_test_counter); - card->configured = 1; - } - - ppp_set_intr_mode(card, PPP_INTR_TIMER); - - /* Turn off the transmit and timer interrupt */ - flags->imask &= ~PPP_INTR_TIMER; - - printk(KERN_INFO "\n"); - - return 0; -} - -/******* WAN Device Driver Entry Points *************************************/ - -/*============================================================================ - * Update device status & statistics. - */ -static int update(struct wan_device *wandev) -{ - sdla_t* card = wandev->private; - struct net_device* dev; - volatile ppp_private_area_t *ppp_priv_area; - ppp_flags_t *flags = card->flags; - unsigned long timeout; - - /* sanity checks */ - if ((wandev == NULL) || (wandev->private == NULL)) - return -EFAULT; - - if (wandev->state == WAN_UNCONFIGURED) - return -ENODEV; - - /* Shutdown bug fix. This function can be - * called with NULL dev pointer during - * shutdown - */ - if ((dev=card->wandev.dev) == NULL){ - return -ENODEV; - } - - if ((ppp_priv_area=dev->priv) == NULL){ - return -ENODEV; - } - - ppp_priv_area->update_comms_stats = 2; - ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UPDATE; - flags->imask |= PPP_INTR_TIMER; - - /* wait a maximum of 1 second for the statistics to be updated */ - timeout = jiffies; - for(;;) { - if(ppp_priv_area->update_comms_stats == 0){ - break; - } - if (time_after(jiffies, timeout + 1 * HZ)){ - ppp_priv_area->update_comms_stats = 0; - ppp_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 *dev, - wanif_conf_t *conf) -{ - sdla_t *card = wandev->private; - ppp_private_area_t *ppp_priv_area; - - if (wandev->ndev) - return -EEXIST; - - - printk(KERN_INFO "%s: Configuring Interface: %s\n", - card->devname, conf->name); - - 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 */ - ppp_priv_area = kmalloc(sizeof(ppp_private_area_t), GFP_KERNEL); - - if( ppp_priv_area == NULL ) - return -ENOMEM; - - memset(ppp_priv_area, 0, sizeof(ppp_private_area_t)); - - ppp_priv_area->card = card; - - /* initialize data */ - strcpy(card->u.p.if_name, conf->name); - - /* initialize data in ppp_private_area structure */ - - init_ppp_priv_struct( ppp_priv_area ); - - ppp_priv_area->mc = conf->mc; - ppp_priv_area->pap = conf->pap; - ppp_priv_area->chap = conf->chap; - - /* Option to bring down the interface when - * the link goes down */ - if (conf->if_down){ - set_bit(DYN_OPT_ON,&ppp_priv_area->interface_down); - printk("%s: Dynamic interface configuration enabled\n", - card->devname); - } - - /* If no user ids are specified */ - if(!strlen(conf->userid) && (ppp_priv_area->pap||ppp_priv_area->chap)){ - kfree(ppp_priv_area); - return -EINVAL; - } - - /* If no passwords are specified */ - if(!strlen(conf->passwd) && (ppp_priv_area->pap||ppp_priv_area->chap)){ - kfree(ppp_priv_area); - return -EINVAL; - } - - if(strlen(conf->sysname) > 31){ - kfree(ppp_priv_area); - return -EINVAL; - } - - /* If no system name is specified */ - if(!strlen(conf->sysname) && (card->u.p.authenticator)){ - kfree(ppp_priv_area); - return -EINVAL; - } - - /* copy the data into the ppp private structure */ - memcpy(ppp_priv_area->userid, conf->userid, strlen(conf->userid)); - memcpy(ppp_priv_area->passwd, conf->passwd, strlen(conf->passwd)); - memcpy(ppp_priv_area->sysname, conf->sysname, strlen(conf->sysname)); - - - ppp_priv_area->enable_IPX = conf->enable_IPX; - if (conf->network_number){ - ppp_priv_area->network_number = conf->network_number; - }else{ - ppp_priv_area->network_number = 0xDEADBEEF; - } - - /* Tells us that if this interface is a - * gateway or not */ - if ((ppp_priv_area->gateway = conf->gateway) == WANOPT_YES){ - printk(KERN_INFO "%s: Interface %s is set as a gateway.\n", - card->devname,card->u.p.if_name); - } - - /* prepare network device data space for registration */ - strcpy(dev->name,card->u.p.if_name); - - dev->init = &if_init; - dev->priv = ppp_priv_area; - dev->mtu = min_t(unsigned int, dev->mtu, card->wandev.mtu); - - /* Initialize the polling work routine */ - INIT_WORK(&ppp_priv_area->poll_work, (void*)(void*)ppp_poll, dev); - - /* Initialize the polling delay timer */ - init_timer(&ppp_priv_area->poll_delay_timer); - ppp_priv_area->poll_delay_timer.data = (unsigned long)dev; - ppp_priv_area->poll_delay_timer.function = ppp_poll_delay; - - - /* Since we start with dummy IP addresses we can say - * that route exists */ - printk(KERN_INFO "\n"); - - return 0; -} - -/*============================================================================ - * Delete logical channel. - */ -static int del_if(struct wan_device *wandev, struct net_device *dev) -{ - return 0; -} - -static void disable_comm (sdla_t *card) -{ - ppp_comm_disable_shutdown(card); - return; -} - -/****** WANPIPE-specific entry points ***************************************/ - -/*============================================================================ - * Execute adapter interface command. - */ - -//FIXME: Why do we need this ???? -static int wpp_exec(struct sdla *card, void *u_cmd, void *u_data) -{ - ppp_mbox_t *mbox = card->mbox; - int len; - - if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t))) - return -EFAULT; - - len = mbox->cmd.length; - - if (len) { - - if( copy_from_user((void*)&mbox->data, u_data, len)) - return -EFAULT; - - } - - /* execute command */ - if (!sdla_exec(mbox)) - return -EIO; - - /* return result */ - if( copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t))) - 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) -{ - ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t *card = ppp_priv_area->card; - struct wan_device *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; - dev->tx_timeout = &if_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; - - /* Initialize media-specific parameters */ - dev->type = ARPHRD_PPP; /* ARP h/w type */ - dev->flags |= IFF_POINTOPOINT; - dev->flags |= IFF_NOARP; - - /* Enable Mulitcasting if specified by user*/ - if (ppp_priv_area->mc == WANOPT_YES){ - dev->flags |= IFF_MULTICAST; - } - - dev->mtu = wandev->mtu; - dev->hard_header_len = PPP_HDR_LEN; /* media header length */ - - /* Initialize hardware parameters (just for reference) */ - 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 */ - dev->tx_queue_len = 100; - SET_MODULE_OWNER(dev); - - return 0; -} - -/*============================================================================ - * 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) -{ - ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t *card = ppp_priv_area->card; - struct timeval tv; - //unsigned long smp_flags; - - if (netif_running(dev)) - return -EBUSY; - - wanpipe_open(card); - - netif_start_queue(dev); - - do_gettimeofday( &tv ); - ppp_priv_area->router_start_time = tv.tv_sec; - - /* We cannot configure the card here because we don't - * have access to the interface IP addresses. - * Once the interface initilization is complete, we will be - * able to access the IP addresses. Therefore, - * configure the ppp link in the poll routine */ - set_bit(0,&ppp_priv_area->config_ppp); - ppp_priv_area->config_wait_timeout=jiffies; - - /* Start the PPP configuration after 1sec delay. - * This will give the interface initilization time - * to finish its configuration */ - mod_timer(&ppp_priv_area->poll_delay_timer, jiffies + HZ); - return 0; -} - -/*============================================================================ - * Close network interface. - * o if this is the last open, then disable communications and interrupts. - * o reset flags. - */ -static int if_close(struct net_device *dev) -{ - ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t *card = ppp_priv_area->card; - - netif_stop_queue(dev); - wanpipe_close(card); - - del_timer (&ppp_priv_area->poll_delay_timer); - return 0; -} - -/*============================================================================ - * Build media header. - * - * The trick here is to put packet type (Ethertype) into 'protocol' field of - * the socket buffer, so that we don't forget it. If packet type is not - * supported, 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) -{ - switch (type) - { - case ETH_P_IP: - case ETH_P_IPX: - skb->protocol = htons(type); - break; - - default: - skb->protocol = 0; - } - - return PPP_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; - ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t *card = ppp_priv_area->card; - - printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n", - card->devname, dev->name); - return 1; -} - -/*============================================================================ - * Handle transmit timeout event from netif watchdog - */ -static void if_tx_timeout(struct net_device *dev) -{ - ppp_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. - */ - - ++ chan->if_send_stat.if_send_tbusy; - ++card->wandev.stats.collisions; - - printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); - ++chan->if_send_stat.if_send_tbusy_timeout; - netif_wake_queue (dev); -} - - - -/*============================================================================ - * 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) -{ - ppp_private_area_t *ppp_priv_area = dev->priv; - sdla_t *card = ppp_priv_area->card; - unsigned char *sendpacket; - unsigned long smp_flags; - ppp_flags_t *flags = card->flags; - int udp_type; - int err=0; - - ++ppp_priv_area->if_send_stat.if_send_entry; - - 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: interface %s got kicked!\n", - card->devname, dev->name); - - ++ppp_priv_area->if_send_stat.if_send_skb_null; - - netif_wake_queue(dev); - return 0; - } - - sendpacket = skb->data; - - udp_type = udp_pkt_type( skb, card ); - - - if (udp_type == UDP_PTPIPE_TYPE){ - if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev, - ppp_priv_area)){ - flags->imask |= PPP_INTR_TIMER; - } - ++ppp_priv_area->if_send_stat.if_send_PIPE_request; - netif_start_queue(dev); - return 0; - } - - /* Check for broadcast and multicast addresses - * If found, drop (deallocate) a packet and return. - */ - if(chk_bcast_mcast_addr(card, dev, skb)){ - ++card->wandev.stats.tx_dropped; - dev_kfree_skb_any(skb); - netif_start_queue(dev); - return 0; - } - - - 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; - ++ppp_priv_area->if_send_stat.if_send_critical_non_ISR; - netif_start_queue(dev); - goto if_send_exit_crit; - } - - if (card->wandev.state != WAN_CONNECTED) { - - ++ppp_priv_area->if_send_stat.if_send_wan_disconnected; - ++card->wandev.stats.tx_dropped; - netif_start_queue(dev); - - } else if (!skb->protocol) { - ++ppp_priv_area->if_send_stat.if_send_protocol_error; - ++card->wandev.stats.tx_errors; - netif_start_queue(dev); - - } else { - - /*If it's IPX change the network numbers to 0 if they're ours.*/ - if( skb->protocol == htons(ETH_P_IPX) ) { - if(ppp_priv_area->enable_IPX) { - switch_net_numbers( skb->data, - ppp_priv_area->network_number, 0); - } else { - ++card->wandev.stats.tx_dropped; - netif_start_queue(dev); - goto if_send_exit_crit; - } - } - - if (ppp_send(card, skb->data, skb->len, skb->protocol)) { - netif_stop_queue(dev); - ++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full; - ++ppp_priv_area->if_send_stat.if_send_tx_int_enabled; - } else { - ++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr; - ++card->wandev.stats.tx_packets; - card->wandev.stats.tx_bytes += skb->len; - netif_start_queue(dev); - dev->trans_start = jiffies; - } - } - -if_send_exit_crit: - - if (!(err=netif_queue_stopped(dev))){ - dev_kfree_skb_any(skb); - }else{ - ppp_priv_area->tick_counter = jiffies; - flags->imask |= PPP_INTR_TXRDY; /* unmask Tx interrupts */ - } - - clear_bit(SEND_CRIT,&card->wandev.critical); - if(card->hw.type != SDLA_S514){ - s508_unlock(card,&smp_flags); - } - - return err; -} - - -/*============================================================================= - * Store a UDP management packet for later processing. - */ - -static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, - struct sk_buff *skb, struct net_device* dev, - ppp_private_area_t* ppp_priv_area ) -{ - int udp_pkt_stored = 0; - - if(!ppp_priv_area->udp_pkt_lgth && (skb->len<=MAX_LGTH_UDP_MGNT_PKT)){ - ppp_priv_area->udp_pkt_lgth = skb->len; - ppp_priv_area->udp_pkt_src = udp_pkt_src; - memcpy(ppp_priv_area->udp_pkt_data, skb->data, skb->len); - ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UDP; - ppp_priv_area->protocol = skb->protocol; - udp_pkt_stored = 1; - }else{ - if (skb->len > MAX_LGTH_UDP_MGNT_PKT){ - printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n", - card->devname, skb->len); - }else{ - printk(KERN_INFO "%s: PIPEMON UPD request already pending\n", - card->devname); - } - ppp_priv_area->udp_pkt_lgth = 0; - } - - if(udp_pkt_src == UDP_PKT_FRM_STACK){ - dev_kfree_skb_any(skb); - }else{ - dev_kfree_skb_any(skb); - } - - return(udp_pkt_stored); -} - - - -/*============================================================================ - * 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; - ppp_udp_pkt_t *p_udp_pkt = (ppp_udp_pkt_t *)data; - - /* Set length of packet */ - len = sizeof(ip_pkt_t)+ - sizeof(udp_pkt_t)+ - sizeof(wp_mgmt_t)+ - sizeof(cblock_t)+ - mbox_len; - - /* fill in UDP reply */ - p_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)+ - 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); - p_udp_pkt->udp_pkt.udp_length = temp; - - - /* swap UDP ports */ - temp = p_udp_pkt->udp_pkt.udp_src_port; - p_udp_pkt->udp_pkt.udp_src_port = - p_udp_pkt->udp_pkt.udp_dst_port; - p_udp_pkt->udp_pkt.udp_dst_port = temp; - - - /* add UDP pseudo header */ - temp = 0x1100; |