⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 baycom_epp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************//* *	baycom_epp.c  -- baycom epp radio modem driver. * *	Copyright (C) 1998-2000 *          Thomas Sailer (sailer@ife.ee.ethz.ch) * *	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. * *	This program is distributed in the hope that it will be useful, *	but WITHOUT ANY WARRANTY; without even the implied warranty of *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *	GNU General Public License for more details. * *	You should have received a copy of the GNU General Public License *	along with this program; if not, write to the Free Software *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *  Please note that the GPL allows you to use the driver, NOT the radio. *  In order to use the radio, you need a license from the communications *  authority of your country. * * *  History: *   0.1  xx.xx.1998  Initial version by Matthias Welwarsky (dg2fef) *   0.2  21.04.1998  Massive rework by Thomas Sailer *                    Integrated FPGA EPP modem configuration routines *   0.3  11.05.1998  Took FPGA config out and moved it into a separate program *   0.4  26.07.1999  Adapted to new lowlevel parport driver interface *   0.5  03.08.1999  adapt to Linus' new __setup/__initcall *                    removed some pre-2.2 kernel compatibility cruft *   0.6  10.08.1999  Check if parport can do SPP and is safe to access during interrupt contexts *   0.7  12.02.2000  adapted to softnet driver interface * *//*****************************************************************************/#include <linux/crc-ccitt.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/string.h>#include <linux/workqueue.h>#include <linux/fs.h>#include <linux/parport.h>#include <linux/if_arp.h>#include <linux/hdlcdrv.h>#include <linux/baycom.h>#include <linux/jiffies.h>#include <net/ax25.h> #include <asm/uaccess.h>/* --------------------------------------------------------------------- */#define BAYCOM_DEBUG#define BAYCOM_MAGIC 19730510/* --------------------------------------------------------------------- */static const char paranoia_str[] = KERN_ERR 	"baycom_epp: bad magic number for hdlcdrv_state struct in routine %s\n";static const char bc_drvname[] = "baycom_epp";static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n"KERN_INFO "baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n";/* --------------------------------------------------------------------- */#define NR_PORTS 4static struct net_device *baycom_device[NR_PORTS];/* --------------------------------------------------------------------- *//* EPP status register */#define EPP_DCDBIT      0x80#define EPP_PTTBIT      0x08#define EPP_NREF        0x01#define EPP_NRAEF       0x02#define EPP_NRHF        0x04#define EPP_NTHF        0x20#define EPP_NTAEF       0x10#define EPP_NTEF        EPP_PTTBIT/* EPP control register */#define EPP_TX_FIFO_ENABLE 0x10#define EPP_RX_FIFO_ENABLE 0x08#define EPP_MODEM_ENABLE   0x20#define EPP_LEDS           0xC0#define EPP_IRQ_ENABLE     0x10/* LPT registers */#define LPTREG_ECONTROL       0x402#define LPTREG_CONFIGB        0x401#define LPTREG_CONFIGA        0x400#define LPTREG_EPPDATA        0x004#define LPTREG_EPPADDR        0x003#define LPTREG_CONTROL        0x002#define LPTREG_STATUS         0x001#define LPTREG_DATA           0x000/* LPT control register */#define LPTCTRL_PROGRAM       0x04   /* 0 to reprogram */#define LPTCTRL_WRITE         0x01#define LPTCTRL_ADDRSTB       0x08#define LPTCTRL_DATASTB       0x02#define LPTCTRL_INTEN         0x10/* LPT status register */#define LPTSTAT_SHIFT_NINTR   6#define LPTSTAT_WAIT          0x80#define LPTSTAT_NINTR         (1<<LPTSTAT_SHIFT_NINTR)#define LPTSTAT_PE            0x20#define LPTSTAT_DONE          0x10#define LPTSTAT_NERROR        0x08#define LPTSTAT_EPPTIMEOUT    0x01/* LPT data register */#define LPTDATA_SHIFT_TDI     0#define LPTDATA_SHIFT_TMS     2#define LPTDATA_TDI           (1<<LPTDATA_SHIFT_TDI)#define LPTDATA_TCK           0x02#define LPTDATA_TMS           (1<<LPTDATA_SHIFT_TMS)#define LPTDATA_INITBIAS      0x80/* EPP modem config/status bits */#define EPP_DCDBIT            0x80#define EPP_PTTBIT            0x08#define EPP_RXEBIT            0x01#define EPP_RXAEBIT           0x02#define EPP_RXHFULL           0x04#define EPP_NTHF              0x20#define EPP_NTAEF             0x10#define EPP_NTEF              EPP_PTTBIT#define EPP_TX_FIFO_ENABLE    0x10#define EPP_RX_FIFO_ENABLE    0x08#define EPP_MODEM_ENABLE      0x20#define EPP_LEDS              0xC0#define EPP_IRQ_ENABLE        0x10/* Xilinx 4k JTAG instructions */#define XC4K_IRLENGTH   3#define XC4K_EXTEST     0#define XC4K_PRELOAD    1#define XC4K_CONFIGURE  5#define XC4K_BYPASS     7#define EPP_CONVENTIONAL  0#define EPP_FPGA          1#define EPP_FPGAEXTSTATUS 2#define TXBUFFER_SIZE     ((HDLCDRV_MAXFLEN*6/5)+8)/* ---------------------------------------------------------------------- *//* * Information that need to be kept for each board. */struct baycom_state {	int magic;        struct pardevice *pdev;	unsigned int work_running;	struct work_struct run_work;	unsigned int modem;	unsigned int bitrate;	unsigned char stat;	struct {		unsigned int intclk;		unsigned int fclk;		unsigned int bps;		unsigned int extmodem;		unsigned int loopback;	} cfg;        struct hdlcdrv_channel_params ch_params;        struct {		unsigned int bitbuf, bitstream, numbits, state;		unsigned char *bufptr;		int bufcnt;		unsigned char buf[TXBUFFER_SIZE];        } hdlcrx;        struct {		int calibrate;                int slotcnt;		int flags;		enum { tx_idle = 0, tx_keyup, tx_data, tx_tail } state;		unsigned char *bufptr;		int bufcnt;		unsigned char buf[TXBUFFER_SIZE];        } hdlctx;        struct net_device_stats stats;	unsigned int ptt_keyed;	struct sk_buff *skb;  /* next transmit packet  */#ifdef BAYCOM_DEBUG	struct debug_vals {		unsigned long last_jiffies;		unsigned cur_intcnt;		unsigned last_intcnt;		int cur_pllcorr;		int last_pllcorr;		unsigned int mod_cycles;		unsigned int demod_cycles;	} debug_vals;#endif /* BAYCOM_DEBUG */};/* --------------------------------------------------------------------- */#define KISS_VERBOSE/* --------------------------------------------------------------------- */#define PARAM_TXDELAY   1#define PARAM_PERSIST   2#define PARAM_SLOTTIME  3#define PARAM_TXTAIL    4#define PARAM_FULLDUP   5#define PARAM_HARDWARE  6#define PARAM_RETURN    255/* --------------------------------------------------------------------- *//* * the CRC routines are stolen from WAMPES * by Dieter Deyke *//*---------------------------------------------------------------------------*/#if 0static inline void append_crc_ccitt(unsigned char *buffer, int len){ 	unsigned int crc = 0xffff;	for (;len>0;len--)		crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buffer++) & 0xff];	crc ^= 0xffff;	*buffer++ = crc;	*buffer++ = crc >> 8;}#endif/*---------------------------------------------------------------------------*/static inline int check_crc_ccitt(const unsigned char *buf, int cnt){	return (crc_ccitt(0xffff, buf, cnt) & 0xffff) == 0xf0b8;}/*---------------------------------------------------------------------------*/static inline int calc_crc_ccitt(const unsigned char *buf, int cnt){	return (crc_ccitt(0xffff, buf, cnt) ^ 0xffff) & 0xffff;}/* ---------------------------------------------------------------------- */#define tenms_to_flags(bc,tenms) ((tenms * bc->bitrate) / 800)/* --------------------------------------------------------------------- */static inline void baycom_int_freq(struct baycom_state *bc){#ifdef BAYCOM_DEBUG	unsigned long cur_jiffies = jiffies;	/*	 * measure the interrupt frequency	 */	bc->debug_vals.cur_intcnt++;	if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {		bc->debug_vals.last_jiffies = cur_jiffies;		bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;		bc->debug_vals.cur_intcnt = 0;		bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;		bc->debug_vals.cur_pllcorr = 0;	}#endif /* BAYCOM_DEBUG */}/* ---------------------------------------------------------------------- *//* *    eppconfig_path should be setable  via /proc/sys. */static char eppconfig_path[256] = "/usr/sbin/eppfpga";static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL };/* eppconfig: called during ifconfig up to configure the modem */static int eppconfig(struct baycom_state *bc){	char modearg[256];	char portarg[16];        char *argv[] = { eppconfig_path, "-s", "-p", portarg, "-m", modearg,			 NULL };	/* set up arguments */	sprintf(modearg, "%sclk,%smodem,fclk=%d,bps=%d,divider=%d%s,extstat",		bc->cfg.intclk ? "int" : "ext",		bc->cfg.extmodem ? "ext" : "int", bc->cfg.fclk, bc->cfg.bps,		(bc->cfg.fclk + 8 * bc->cfg.bps) / (16 * bc->cfg.bps),		bc->cfg.loopback ? ",loopback" : "");	sprintf(portarg, "%ld", bc->pdev->port->base);	printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg);	return call_usermodehelper(eppconfig_path, argv, envp, 1);}/* ---------------------------------------------------------------------- */static void epp_interrupt(int irq, void *dev_id, struct pt_regs *regs){}/* ---------------------------------------------------------------------- */static inline void do_kiss_params(struct baycom_state *bc,				  unsigned char *data, unsigned long len){#ifdef KISS_VERBOSE#define PKP(a,b) printk(KERN_INFO "baycomm_epp: channel params: " a "\n", b)#else /* KISS_VERBOSE */	      #define PKP(a,b) #endif /* KISS_VERBOSE */	      	if (len < 2)		return;	switch(data[0]) {	case PARAM_TXDELAY:		bc->ch_params.tx_delay = data[1];		PKP("TX delay = %ums", 10 * bc->ch_params.tx_delay);		break;	case PARAM_PERSIST:   		bc->ch_params.ppersist = data[1];		PKP("p persistence = %u", bc->ch_params.ppersist);		break;	case PARAM_SLOTTIME:  		bc->ch_params.slottime = data[1];		PKP("slot time = %ums", bc->ch_params.slottime);		break;	case PARAM_TXTAIL:    		bc->ch_params.tx_tail = data[1];		PKP("TX tail = %ums", bc->ch_params.tx_tail);		break;	case PARAM_FULLDUP:   		bc->ch_params.fulldup = !!data[1];		PKP("%s duplex", bc->ch_params.fulldup ? "full" : "half");		break;	default:		break;	}#undef PKP}/* --------------------------------------------------------------------- */static void encode_hdlc(struct baycom_state *bc){	struct sk_buff *skb;	unsigned char *wp, *bp;	int pkt_len;        unsigned bitstream, notbitstream, bitbuf, numbit, crc;	unsigned char crcarr[2];	int j;		if (bc->hdlctx.bufcnt > 0)		return;	skb = bc->skb;	if (!skb)		return;	bc->skb = NULL;	pkt_len = skb->len-1; /* strip KISS byte */	wp = bc->hdlctx.buf;	bp = skb->data+1;	crc = calc_crc_ccitt(bp, pkt_len);	crcarr[0] = crc;	crcarr[1] = crc >> 8;	*wp++ = 0x7e;	bitstream = bitbuf = numbit = 0;	while (pkt_len > -2) {		bitstream >>= 8;		bitstream |= ((unsigned int)*bp) << 8;		bitbuf |= ((unsigned int)*bp) << numbit;		notbitstream = ~bitstream;		bp++;		pkt_len--;		if (!pkt_len)			bp = crcarr;		for (j = 0; j < 8; j++)			if (unlikely(!(notbitstream & (0x1f0 << j)))) {				bitstream &= ~(0x100 << j); 				bitbuf = (bitbuf & (((2 << j) << numbit) - 1)) |					((bitbuf & ~(((2 << j) << numbit) - 1)) << 1);				numbit++;				notbitstream = ~bitstream;			}		numbit += 8;		while (numbit >= 8) {			*wp++ = bitbuf;			bitbuf >>= 8;			numbit -= 8;		}	}	bitbuf |= 0x7e7e << numbit;	numbit += 16;	while (numbit >= 8) {		*wp++ = bitbuf;		bitbuf >>= 8;		numbit -= 8;	}	bc->hdlctx.bufptr = bc->hdlctx.buf;	bc->hdlctx.bufcnt = wp - bc->hdlctx.buf;	dev_kfree_skb(skb);	bc->stats.tx_packets++;}/* ---------------------------------------------------------------------- */static unsigned short random_seed;static inline unsigned short random_num(void){	random_seed = 28629 * random_seed + 157;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -