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

📄 baycom_epp.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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;		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++;}/* ---------------------------------------------------------------------- */static unsigned short random_seed;static inline unsigned short random_num(void){	random_seed = 28629 * random_seed + 157;	return random_seed;}/* ---------------------------------------------------------------------- */static int transmit(struct baycom_state *bc, int cnt, unsigned char stat){	struct parport *pp = bc->pdev->port;	unsigned char tmp[128];	int i, j;	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 0;		if (!bc->ch_params.fulldup) {			if (!(stat & EPP_DCDBIT)) {				bc->hdlctx.slotcnt = bc->ch_params.slottime;				return 0;			}			if ((--bc->hdlctx.slotcnt) > 0)				return 0;			bc->hdlctx.slotcnt = bc->ch_params.slottime;			if ((random_num() % 256) > bc->ch_params.ppersist)				return 0;		}	}	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_t(int, cnt, bc->hdlctx.flags);			cnt -= i;			bc->hdlctx.flags -= i;			if (bc->hdlctx.flags <= 0)				bc->hdlctx.state = tx_data;			memset(tmp, 0x7e, sizeof(tmp));			while (i > 0) {				j = (i > sizeof(tmp)) ? sizeof(tmp) : i;				if (j != pp->ops->epp_write_data(pp, tmp, j, 0))					return -1;				i -= j;			}			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_t(int, cnt, bc->hdlctx.bufcnt);			bc->hdlctx.bufcnt -= i;			cnt -= i;			if (i != pp->ops->epp_write_data(pp, bc->hdlctx.bufptr, i, 0))					return -1;			bc->hdlctx.bufptr += i;			break;					case tx_tail:			encode_hdlc(bc);			if (bc->hdlctx.bufcnt > 0) {				bc->hdlctx.state = tx_data;				break;			}			i = min_t(int, cnt, bc->hdlctx.flags);			if (i) {				cnt -= i;				bc->hdlctx.flags -= i;				memset(tmp, 0x7e, sizeof(tmp));				while (i > 0) {					j = (i > sizeof(tmp)) ? sizeof(tmp) : i;					if (j != pp->ops->epp_write_data(pp, tmp, j, 0))						return -1;					i -= j;				}				break;			}		default:  /* fall through */			if (bc->hdlctx.calibrate <= 0)				return 0;			i = min_t(int, cnt, bc->hdlctx.calibrate);			cnt -= i;			bc->hdlctx.calibrate -= i;			memset(tmp, 0, sizeof(tmp));			while (i > 0) {				j = (i > sizeof(tmp)) ? sizeof(tmp) : i;				if (j != pp->ops->epp_write_data(pp, tmp, j, 0))					return -1;				i -= j;			}			break;		}	}	return 0;}/* ---------------------------------------------------------------------- */static void do_rxpacket(struct net_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", dev->name);		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 */    \                goto stuff##j;                                                \  enditer##j: ;                                                               \})#define DECODEITERB(j)                                                                 \({                                                                                     \  flgabrt##j:                                                                          \        if (!(notbitstream & (0x1fc << j))) {              /* abort received */        \                state = 0;                                                             \                goto enditer##j;                                                       \        }                                                                              \        if ((bitstream & (0x1fe << j)) != (0x0fc << j))   /* flag received */          \                goto enditer##j;                                                       \        if (state)                                                                     \                do_rxpacket(dev);                                                      \        bc->hdlcrx.bufcnt = 0;                                                         \        bc->hdlcrx.bufptr = bc->hdlcrx.buf;                                            \        state = 1;                                                                     \        numbits = 7-j;                                                                 \        goto enditer##j;                                                               \  stuff##j:                                                                            \        numbits--;                                                                     \        bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1);        \        goto enditer##j;                                                               \})        static int receive(struct net_device *dev, int cnt){	struct baycom_state *bc = (struct baycom_state *)dev->priv;	struct parport *pp = bc->pdev->port;        unsigned int bitbuf, notbitstream, bitstream, numbits, state;	unsigned char tmp[128];        unsigned char *cp;	int cnt2, ret = 0;                numbits = bc->hdlcrx.numbits;	state = bc->hdlcrx.state;	bitstream = bc->hdlcrx.bitstream;	bitbuf = bc->hdlcrx.bitbuf;	while (cnt > 0) {		cnt2 = (cnt > sizeof(tmp)) ? sizeof(tmp) : cnt;		cnt -= cnt2;		if (cnt2 != pp->ops->epp_read_data(pp, tmp, cnt2, 0)) {			ret = -1;			break;		}		cp = tmp;		for (; cnt2 > 0; cnt2--, cp++) {			bitstream >>= 8;			bitstream |= (*cp) << 8;			bitbuf >>= 8;			bitbuf |= (*cp) << 8;			numbits += 8;			notbitstream = ~bitstream;			DECODEITERA(0);			DECODEITERA(1);			DECODEITERA(2);			DECODEITERA(3);			DECODEITERA(4);			DECODEITERA(5);			DECODEITERA(6);			DECODEITERA(7);			goto enddec;			DECODEITERB(0);			DECODEITERB(1);			DECODEITERB(2);			DECODEITERB(3);			DECODEITERB(4);			DECODEITERB(5);			DECODEITERB(6);			DECODEITERB(7);		enddec:			while (state && numbits >= 8) {				if (bc->hdlcrx.bufcnt >= TXBUFFER_SIZE) {					state = 0;				} else {					*(bc->hdlcrx.bufptr)++ = bitbuf >> (16-numbits);					bc->hdlcrx.bufcnt++;					numbits -= 8;				}			}		}	}        bc->hdlcrx.numbits = numbits;	bc->hdlcrx.state = state;	bc->hdlcrx.bitstream = bitstream;	bc->hdlcrx.bitbuf = bitbuf;	return ret;}/* --------------------------------------------------------------------- */#ifdef __i386__#define GETTICK(x)                                                \({                                                                \	if (cpu_has_tsc)                                          \		__asm__ __volatile__("rdtsc" : "=a" (x) : : "dx");\})#else /* __i386__ */#define GETTICK(x)#endif /* __i386__ */static void epp_bh(struct net_device *dev){	struct baycom_state *bc;	struct parport *pp;	unsigned char stat;	unsigned char tmp[2];	unsigned int time1 = 0, time2 = 0, time3 = 0;	int cnt, cnt2;		baycom_paranoia_check_void(dev, "epp_bh");	bc = (struct baycom_state *)dev->priv;	if (!bc->bh_running)		return;	baycom_int_freq(bc);	pp = bc->pdev->port;	/* update status */	if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)		goto epptimeout;	bc->stat = stat;	bc->debug_vals.last_pllcorr = stat;	GETTICK(time1);	if (bc->modem == EPP_FPGAEXTSTATUS) {		/* get input count */		tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|1;		if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1)			goto epptimeout;		if (pp->ops->epp_read_addr(pp, tmp, 2, 0) != 2)			goto epptimeout;		cnt = tmp[0] | (tmp[1] << 8);		cnt &= 0x7fff;		/* get output count */		tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|2;		if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1)			goto epptimeout;		if (pp->ops->epp_read_addr(pp, tmp, 2, 0) != 2)			goto epptimeout;		cnt2 = tmp[0] | (tmp[1] << 8);		cnt2 = 16384 - (cnt2 & 0x7fff);		/* return to normal */		tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE;		if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1)			goto epptimeout;		if (transmit(bc, cnt2, stat))			goto epptimeout;		GETTICK(time2);		if (receive(dev, cnt))			goto epptimeout;		if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)			goto epptimeout;		bc->stat = stat;	} else {		/* try to tx */		switch (stat & (EPP_NTAEF|EPP_NTHF)) {		case EPP_NTHF:			cnt = 2048 - 256;			break;				case EPP_NTAEF:			cnt = 2048 - 1793;			break;				case 0:			cnt = 0;			break;				default:			cnt = 2048 - 1025;			break;		}		if (transmit(bc, cnt, stat))			goto epptimeout;		GETTICK(time2);		/* do receiver */		while ((stat & (EPP_NRAEF|EPP_NRHF)) != EPP_NRHF) {			switch (stat & (EPP_NRAEF|EPP_NRHF)) {			case EPP_NRAEF:				cnt = 1025;				break;			case 0:				cnt = 1793;				break;			default:				cnt = 256;				break;			}			if (receive(dev, cnt))				goto epptimeout;			if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)				goto epptimeout;		}		cnt = 0;		if (bc->bitrate < 50000)			cnt = 256;		else if (bc->bitrate < 100000)			cnt = 128;		while (cnt > 0 && stat & EPP_NREF) {			if (receive(dev, 1))				goto epptimeout;			cnt--;			if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1)				goto epptimeout;		}	}	GETTICK(time3);#ifdef BAYCOM_DEBUG	bc->debug_vals.mod_cycles = time2 - time1;	bc->debug_vals.demod_cycles = time3 - time2;#endif /* BAYCOM_DEBUG */	queue_task(&bc->run_bh, &tq_timer);	if (!bc->skb)		netif_wake_queue(dev);	return; epptimeout:	printk(KERN_ERR "%s: EPP timeout!\n", bc_drvname);}/* ---------------------------------------------------------------------- *//* * ===================== network driver interface ========================= */static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev){	struct baycom_state *bc;	baycom_paranoia_check(dev, "baycom_send_packet", 0);	bc = (struct baycom_state *)dev->priv;	if (skb->data[0] != 0) {		do_kiss_params(bc, skb->data, skb->len);		dev_kfree_skb(skb);		return 0;	}	if (bc->skb)		return -1;	/* strip KISS byte */	if (skb->len >= HDLCDRV_MAXFLEN+1 || skb->len < 3) {		dev_kfree_skb(skb);		return 0;	}	netif_stop_queue(dev);	bc->skb = skb;	return 0;}/* --------------------------------------------------------------------- */static int baycom_set_mac_address(struct net_device *dev, void *addr){	struct sockaddr *sa = (struct sockaddr *)addr;	/* addr is an AX.25 shifted ASCII mac address */	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); 	return 0;                                         }/* --------------------------------------------------------------------- */static struct net_device_stats *baycom_get_stats(struct net_device *dev){	struct baycom_state *bc;	baycom_paranoia_check(dev, "baycom_get_stats", NULL);	bc = (struct baycom_state *)dev->priv;	/* 	 * Get the current statistics.  This may be called with the	 * card open or closed. 	 */	return &bc->stats;}/* --------------------------------------------------------------------- */static void epp_wakeup(void *handle){        struct net_device *dev = (struct net_device *)handle;        struct baycom_state *bc;	baycom_paranoia_check_void(dev, "epp_wakeup");        bc = (struct baycom_state *)dev->priv;        printk(KERN_DEBUG "baycom_epp: %s: why am I being woken up?\n", dev->name);        if (!parport_claim(bc->pdev))                printk(KERN_DEBUG "baycom_epp: %s: I'm broken.\n", dev->name);}/* --------------------------------------------------------------------- *//* * Open/initialize the board. This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. * * This routine should set everything up anew at each open, even * registers that "should" only need to be set once at boot, so that * there is non-reboot way to recover if something goes wrong. */static int epp_open(struct net_device *dev)

⌨️ 快捷键说明

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