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

📄 baycom_epp.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	for (; cnt > 0; cnt--)		crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff];	return (crc & 0xffff) == 0xf0b8;}/*---------------------------------------------------------------------------*/extern inline int calc_crc_ccitt(const unsigned char *buf, int cnt){	unsigned int crc = 0xffff;	for (; cnt > 0; cnt--)		crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff];	crc ^= 0xffff;	return (crc & 0xffff);}/* ---------------------------------------------------------------------- */#define tenms_to_flags(bc,tenms) ((tenms * bc->bitrate) / 800)/* --------------------------------------------------------------------- */static void inline 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 ((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. */char eppconfig_path[256] = "/sbin/eppfpga";static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL };static int errno;static int exec_eppfpga(void *b){	struct baycom_state *bc = (struct baycom_state *)b;	char modearg[256];	char portarg[16];        char *argv[] = { eppconfig_path, "-s", "-p", portarg, "-m", modearg, NULL};        int i;	/* set up arguments */	sprintf(modearg, "%sclk,%smodem,divider=%d%s,extstat",		bc->cfg.intclk ? "int" : "ext",		bc->cfg.extmodem ? "ext" : "int", bc->cfg.divider,		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);        for (i = 0; i < current->files->max_fds; i++ )		if (current->files->fd[i]) 			close(i);        set_fs(KERNEL_DS);      /* Allow execve args to be in kernel space. */        current->uid = current->euid = current->fsuid = 0;        if (execve(eppconfig_path, argv, envp) < 0) {                printk(KERN_ERR "%s: failed to exec %s -s -p %s -m %s, errno = %d\n",                       bc_drvname, eppconfig_path, portarg, modearg, errno);                return -errno;        }        return 0;}/* eppconfig: called during ifconfig up to configure the modem */static int eppconfig(struct baycom_state *bc){        int i, pid, r;	mm_segment_t fs;        pid = kernel_thread(exec_eppfpga, bc, CLONE_FS);        if (pid < 0) {                printk(KERN_ERR "%s: fork failed, errno %d\n", bc_drvname, -pid);                return pid;        }	fs = get_fs();        set_fs(KERNEL_DS);      /* Allow i to be in kernel space. */	r = waitpid(pid, &i, __WCLONE);	set_fs(fs);        if (r != pid) {                printk(KERN_ERR "%s: waitpid(%d) failed, returning %d\n",		       bc_drvname, pid, r);		return -1;        }	printk(KERN_DEBUG "%s: eppfpga returned %d\n", bc_drvname, i);	return i;}/* ---------------------------------------------------------------------- */static void epp_interrupt(int irq, void *dev_id, struct pt_regs *regs){}/* ---------------------------------------------------------------------- */static void inline do_kiss_params(struct baycom_state *bc,				  unsigned char *data, unsigned long len){#ifdef KISS_VERBOSE#define PKP(a,b) printk(KERN_INFO "%s: channel params: " a "\n", bc->ifname, 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}/* --------------------------------------------------------------------- *//* * high performance HDLC encoder * yes, it's ugly, but generates pretty good code */#define ENCODEITERA(j)                         \({                                             \        if (!(notbitstream & (0x1f0 << j)))    \                goto stuff##j;                 \  encodeend##j:                                \})#define ENCODEITERB(j)                                          \({                                                              \  stuff##j:                                                     \        bitstream &= ~(0x100 << j);                             \        bitbuf = (bitbuf & (((2 << j) << numbit) - 1)) |        \                ((bitbuf & ~(((2 << j) << numbit) - 1)) << 1);  \        numbit++;                                               \        notbitstream = ~bitstream;                              \        goto encodeend##j;                                      \})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];		if (bc->hdlctx.bufcnt > 0)		return;	while ((skb = skb_dequeue(&bc->send_queue))) {		if (skb->data[0] != 0) {			do_kiss_params(bc, skb->data, skb->len);			dev_kfree_skb(skb);			continue;		}		pkt_len = skb->len-1; /* strip KISS byte */		if (pkt_len >= HDLCDRV_MAXFLEN || pkt_len < 2) {			dev_kfree_skb(skb);			continue;		}		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;                        ENCODEITERA(0);                        ENCODEITERA(1);                        ENCODEITERA(2);                        ENCODEITERA(3);                        ENCODEITERA(4);                        ENCODEITERA(5);                        ENCODEITERA(6);                        ENCODEITERA(7);                        goto enditer;                        ENCODEITERB(0);                        ENCODEITERB(1);                        ENCODEITERB(2);                        ENCODEITERB(3);                        ENCODEITERB(4);                        ENCODEITERB(5);                        ENCODEITERB(6);                        ENCODEITERB(7);                  enditer:                        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++;		return;	}}/* ---------------------------------------------------------------------- */static unsigned short random_seed;static inline unsigned short random_num(void){	random_seed = 28629 * random_seed + 157;	return random_seed;}/* ---------------------------------------------------------------------- */static void transmit(struct baycom_state *bc, int cnt, unsigned char stat){	struct parport *pp = bc->pdev->port;	int i;	if (bc->hdlctx.state == tx_tail && !(stat & EPP_PTTBIT))		bc->hdlctx.state = tx_idle;	if (bc->hdlctx.state == tx_idle && bc->hdlctx.calibrate <= 0) {		if (bc->hdlctx.bufcnt <= 0)			encode_hdlc(bc);		if (bc->hdlctx.bufcnt <= 0)			return;		if (!bc->ch_params.fulldup) {			if (!(stat & EPP_DCDBIT)) {				bc->hdlctx.slotcnt = bc->ch_params.slottime;				return;			}			if ((--bc->hdlctx.slotcnt) > 0)				return;			bc->hdlctx.slotcnt = bc->ch_params.slottime;			if ((random_num() % 256) > bc->ch_params.ppersist)				return;		}	}	if (bc->hdlctx.state == tx_idle && bc->hdlctx.bufcnt > 0) {		bc->hdlctx.state = tx_keyup;		bc->hdlctx.flags = tenms_to_flags(bc, bc->ch_params.tx_delay);		bc->ptt_keyed++;	}	while (cnt > 0) {		switch (bc->hdlctx.state) {		case tx_keyup:			i = min(cnt, bc->hdlctx.flags);			cnt -= i;			bc->hdlctx.flags -= i;			if (bc->hdlctx.flags <= 0)				bc->hdlctx.state = tx_data;			for (; i > 0; i--)				parport_epp_write_data(pp, 0x7e);			break;		case tx_data:			if (bc->hdlctx.bufcnt <= 0) {				encode_hdlc(bc);				if (bc->hdlctx.bufcnt <= 0) {					bc->hdlctx.state = tx_tail;					bc->hdlctx.flags = tenms_to_flags(bc, bc->ch_params.tx_tail);					break;				}			}			i = min(cnt, bc->hdlctx.bufcnt);			bc->hdlctx.bufcnt -= i;			cnt -= i;			for (; i > 0; i--)				parport_epp_write_data(pp, *(bc->hdlctx.bufptr)++);			break;					case tx_tail:			encode_hdlc(bc);			if (bc->hdlctx.bufcnt > 0) {				bc->hdlctx.state = tx_data;				break;			}			i = min(cnt, bc->hdlctx.flags);			if (i) {				cnt -= i;				bc->hdlctx.flags -= i;				for (; i > 0; i--)					parport_epp_write_data(pp, 0x7e);				break;			}		default:  /* fall through */			if (bc->hdlctx.calibrate <= 0)				return;			i = min(cnt, bc->hdlctx.calibrate);			cnt -= i;			bc->hdlctx.calibrate -= i;			for (; i > 0; i--)				parport_epp_write_data(pp, 0);			break;		}	}}/* ---------------------------------------------------------------------- */static void do_rxpacket(struct device *dev){	struct baycom_state *bc = (struct baycom_state *)dev->priv;	struct sk_buff *skb;	unsigned char *cp;	unsigned pktlen;	if (bc->hdlcrx.bufcnt < 4) 		return;	if (!check_crc_ccitt(bc->hdlcrx.buf, bc->hdlcrx.bufcnt)) 		return;	pktlen = bc->hdlcrx.bufcnt-2+1; /* KISS kludge */	if (!(skb = dev_alloc_skb(pktlen))) {		printk("%s: memory squeeze, dropping packet\n", bc->ifname);		bc->stats.rx_dropped++;		return;	}	skb->dev = dev;	cp = skb_put(skb, pktlen);	*cp++ = 0; /* KISS kludge */	memcpy(cp, bc->hdlcrx.buf, pktlen - 1);	skb->protocol = htons(ETH_P_AX25);	skb->mac.raw = skb->data;	netif_rx(skb);	bc->stats.rx_packets++;}#define DECODEITERA(j)                                                        \({                                                                            \        if (!(notbitstream & (0x0fc << j)))              /* flag or abort */  \                goto flgabrt##j;                                              \        if ((bitstream & (0x1f8 << j)) == (0xf8 << j))   /* stuffed bit */    \

⌨️ 快捷键说明

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