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

📄 baycom_epp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 = netdev_priv(dev);	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;	}	cp = skb_put(skb, pktlen);	*cp++ = 0; /* KISS kludge */	memcpy(cp, bc->hdlcrx.buf, pktlen - 1);	skb->protocol = ax25_type_trans(skb, dev);	netif_rx(skb);	dev->last_rx = jiffies;	bc->stats.rx_packets++;}static int receive(struct net_device *dev, int cnt){	struct baycom_state *bc = netdev_priv(dev);	struct parport *pp = bc->pdev->port;        unsigned int bitbuf, notbitstream, bitstream, numbits, state;	unsigned char tmp[128];        unsigned char *cp;	int cnt2, ret = 0;	int j;                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;			for (j = 0; j < 8; j++) {				/* flag or abort */			        if (unlikely(!(notbitstream & (0x0fc << j)))) {					/* abort received */					if (!(notbitstream & (0x1fc << j)))						state = 0;					/* not flag received */					else if (!(bitstream & (0x1fe << j)) != (0x0fc << j)) {						if (state)							do_rxpacket(dev);						bc->hdlcrx.bufcnt = 0;						bc->hdlcrx.bufptr = bc->hdlcrx.buf;						state = 1;						numbits = 7-j;						}					}				/* stuffed bit */				else if (unlikely((bitstream & (0x1f8 << j)) == (0xf8 << j))) {					numbits--;					bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1);					}				}			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__#include <asm/msr.h>#define GETTICK(x)                                                \({                                                                \	if (cpu_has_tsc)                                          \		rdtscl(x);                                        \})#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;		bc = netdev_priv(dev);	if (!bc->work_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 */	schedule_delayed_work(&bc->run_work, 1);	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 = netdev_priv(dev);	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 = netdev_priv(dev);	/* 	 * 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 = netdev_priv(dev);        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){	struct baycom_state *bc = netdev_priv(dev);        struct parport *pp = parport_find_base(dev->base_addr);	unsigned int i, j;	unsigned char tmp[128];	unsigned char stat;	unsigned long tstart;	        if (!pp) {                printk(KERN_ERR "%s: parport at 0x%lx unknown\n", bc_drvname, dev->base_addr);                return -ENXIO;        }#if 0        if (pp->irq < 0) {                printk(KERN_ERR "%s: parport at 0x%lx has no irq\n", bc_drvname, pp->base);		parport_put_port(pp);                return -ENXIO;        }#endif	if ((~pp->modes) & (PARPORT_MODE_TRISTATE | PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) {                printk(KERN_ERR "%s: parport at 0x%lx cannot be used\n",		       bc_drvname, pp->base);		parport_put_port(pp);                return -EIO;	}	memset(&bc->modem, 0, sizeof(bc->modem));

⌨️ 快捷键说明

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