📄 sdla_x25.c
字号:
/****************************************************************************** sdla_x25.c WANPIPE(tm) Multiprotocol WAN Link Driver. X.25 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.* ============================================================================* Apr 03, 2001 Nenad Corbic o Fixed the rx_skb=NULL bug in x25 in rx_intr().* Dec 26, 2000 Nenad Corbic o Added a new polling routine, that uses* a kernel timer (more efficient).* Dec 25, 2000 Nenad Corbic o Updated for 2.4.X kernel* Jul 26, 2000 Nenad Corbic o Increased the local packet buffering* for API to 4096+header_size. * Jul 17, 2000 Nenad Corbic o Fixed the x25 startup bug. Enable * communications only after all interfaces* come up. HIGH SVC/PVC is used to calculate* the number of channels.* Enable protocol only after all interfaces* are enabled.* Jul 10, 2000 Nenad Corbic o Fixed the M_BIT bug. * Apr 25, 2000 Nenad Corbic o Pass Modem messages to the API.* Disable idle timeout in X25 API.* Apr 14, 2000 Nenad Corbic o Fixed: Large LCN number support.* Maximum LCN number is 4095.* Maximum number of X25 channels is 255.* Apr 06, 2000 Nenad Corbic o Added SMP Support.* Mar 29, 2000 Nenad Corbic o Added support for S514 PCI Card* Mar 23, 2000 Nenad Corbic o Improved task queue, BH handling.* Mar 14, 2000 Nenad Corbic o Updated Protocol Violation handling* routines. Bug Fix.* Mar 10, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery.* Mar 09, 2000 Nenad Corbic o Fixed the auto HDLC bug.* Mar 08, 2000 Nenad Corbic o Fixed LAPB HDLC startup problems.* Application must bring the link up * before tx/rx, and bring the * link down on close().* Mar 06, 2000 Nenad Corbic o Added an option for logging call setup * information. * Feb 29, 2000 Nenad Corbic o Added support for LAPB HDLC API* Feb 25, 2000 Nenad Corbic o Fixed the modem failure handling.* No Modem OOB message will be passed * to the user.* Feb 21, 2000 Nenad Corbic o Added Xpipemon Debug Support* Dec 30, 1999 Nenad Corbic o Socket based X25API * Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X kernel* Mar 15, 1998 Alan Cox o 2.1.x porting* Dec 19, 1997 Jaspreet Singh o Added multi-channel IPX support* 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.*****************************************************************************//*====================================================== * Includes *=====================================================*/#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/ctype.h>#include <linux/slab.h> /* kmalloc(), kfree() */#include <linux/wanrouter.h> /* WAN router definitions */#include <linux/wanpipe.h> /* WANPIPE common user API definitions */#include <linux/workqueue.h>#include <linux/jiffies.h> /* time_after() macro */#include <asm/byteorder.h> /* htons(), etc. */#include <asm/atomic.h>#include <linux/delay.h> /* Experimental delay */#include <asm/uaccess.h>#include <linux/if.h>#include <linux/if_arp.h>#include <linux/sdla_x25.h> /* X.25 firmware API definitions */#include <linux/if_wanpipe_common.h>#include <linux/if_wanpipe.h>/*====================================================== * 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 */#define MAX_BH_BUFF 10#define M_BIT 0x01 //#define PRINT_DEBUG 1#ifdef PRINT_DEBUG#define DBG_PRINTK(format, a...) printk(format, ## a)#else#define DBG_PRINTK(format, a...)#endif #define TMR_INT_ENABLED_POLL_ACTIVE 0x01#define TMR_INT_ENABLED_POLL_CONNECT_ON 0x02#define TMR_INT_ENABLED_POLL_CONNECT_OFF 0x04#define TMR_INT_ENABLED_POLL_DISCONNECT 0x08#define TMR_INT_ENABLED_CMD_EXEC 0x10#define TMR_INT_ENABLED_UPDATE 0x20#define TMR_INT_ENABLED_UDP_PKT 0x40#define MAX_X25_ADDR_SIZE 16#define MAX_X25_DATA_SIZE 129#define MAX_X25_FACL_SIZE 110#define TRY_CMD_AGAIN 2#define DELAY_RESULT 1#define RETURN_RESULT 0#define DCD(x) (x & 0x03 ? "HIGH" : "LOW")#define CTS(x) (x & 0x05 ? "HIGH" : "LOW")/* Driver will not write log messages about * modem status if defined.*/#define MODEM_NOT_LOG 1/*==================================================== * 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)))/*==================================================== * MEMORY DEBUGGING FUNCTION *====================================================#define KMEM_SAFETYZONE 8static void * dbg_kmalloc(unsigned int size, int prio, int line) { int i = 0; void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio); char * c1 = v; c1 += sizeof(unsigned int); *((unsigned int *)v) = size; for (i = 0; i < KMEM_SAFETYZONE; i++) { c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D'; c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F'; c1 += 8; } c1 += size; for (i = 0; i < KMEM_SAFETYZONE; i++) { c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G'; c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L'; c1 += 8; } v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8; printk(KERN_INFO "line %d kmalloc(%d,%d) = %p\n",line,size,prio,v); return v;}static void dbg_kfree(void * v, int line) { unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8)); unsigned int size = *sp; char * c1 = ((char *)v) - KMEM_SAFETYZONE*8; int i = 0; for (i = 0; i < KMEM_SAFETYZONE; i++) { if ( c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D' || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') { printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v); printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8, c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] ); } c1 += 8; } c1 += size; for (i = 0; i < KMEM_SAFETYZONE; i++) { if ( c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G' || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L' ) { printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v); printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8, c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] ); } c1 += 8; } printk(KERN_INFO "line %d kfree(%p)\n",line,v); v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8); kfree(v);}#define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__)#define kfree(x) dbg_kfree(x,__LINE__)==============================================================*//*=============================================== * Data Structures *===============================================*//*======================================================== * Name: x25_channel * * Purpose: To hold private informaton for each * logical channel. * * Rationale: Per-channel debugging is possible if each * channel has its own private area. * * Assumptions: * * Description: 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. * * Construct: Typedef */typedef struct x25_channel{ wanpipe_common_t common; /* common area for x25api and socket */ char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */ char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */ unsigned tx_pkt_size; unsigned short protocol; /* ethertype, 0 - multiplexed */ 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 */ bh_data_t *bh_head; /* Circular buffer for x25api_bh */ unsigned long tq_working; volatile int bh_write; volatile int bh_read; atomic_t bh_buff_used; sdla_t* card; /* -> owner */ struct net_device *dev; /* -> bound devce */ int ch_idx; unsigned char enable_IPX; unsigned long network_number; struct net_device_stats ifstats; /* interface statistics */ unsigned short transmit_length; unsigned short tx_offset; char transmit_buffer[X25_CHAN_MTU+sizeof(x25api_hdr_t)]; if_send_stat_t if_send_stat; rx_intr_stat_t rx_intr_stat; pipe_mgmt_stat_t pipe_mgmt_stat; unsigned long router_start_time; /* Router start time in seconds */ unsigned long router_up_time; } x25_channel_t;/* FIXME Take this out */#ifdef NEX_OLD_CALL_INFOtypedef struct x25_call_info{ char dest[17]; PACKED;/* ASCIIZ destination address */ char src[17]; PACKED;/* ASCIIZ source address */ char nuser; PACKED;/* number of user data bytes */ unsigned char user[127]; PACKED;/* user data */ char nfacil; PACKED;/* number of facilities */ struct { unsigned char code; PACKED; unsigned char parm; PACKED; } facil[64]; /* facilities */} x25_call_info_t;#elsetypedef struct x25_call_info{ char dest[MAX_X25_ADDR_SIZE] PACKED;/* ASCIIZ destination address */ char src[MAX_X25_ADDR_SIZE] PACKED;/* ASCIIZ source address */ unsigned char nuser PACKED; unsigned char user[MAX_X25_DATA_SIZE] PACKED;/* user data */ unsigned char nfacil PACKED; unsigned char facil[MAX_X25_FACL_SIZE] PACKED; unsigned short lcn PACKED;} x25_call_info_t;#endif /*=============================================== * Private 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);static void disable_comm (sdla_t* card);static void disable_comm_shutdown(sdla_t *card);/*================================================= * WANPIPE-specific entry points */static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data);static void x25api_bh(struct net_device *dev);static int x25api_bh_cleanup(struct net_device *dev);static int bh_enqueue(struct net_device *dev, struct sk_buff *skb);/*================================================= * 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);static void if_tx_timeout(struct net_device *dev);/*================================================= * Interrupt handlers */static void wpx_isr (sdla_t *);static void rx_intr (sdla_t *);static void tx_intr (sdla_t *);static void status_intr (sdla_t *);static void event_intr (sdla_t *);static void spur_intr (sdla_t *);static void timer_intr (sdla_t *);static int tx_intr_send(sdla_t *card, struct net_device *dev);static struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev);/*================================================= * 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);static void trigger_x25_poll(sdla_t *card);static void x25_timer_routine(unsigned long data);/*================================================= * 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 hdlc_configure (sdla_t* card, TX25Config* conf);static int set_hdlc_level (sdla_t* card);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(struct wan_device* 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, void* buff, unsigned data_len, unsigned char tx_intr);static unsigned char bps_to_speed_code (unsigned long bps);static unsigned int dec_to_uint (unsigned char* str, int len);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -