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

📄 mkiss.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
		actual = ax->mkiss->tty->driver.write(ax->mkiss->tty, 0, ax->mkiss->xbuff, count);		ax->tx_packets++;		ax->mkiss->dev->trans_start = jiffies;		ax->mkiss->xleft = count - actual;		ax->mkiss->xhead = ax->mkiss->xbuff + actual;	}}/* * Called by the driver when there's room for more data.  If we have * more packets to send, we send them here. */static void ax25_write_wakeup(struct tty_struct *tty){	int actual;	struct ax_disp *ax = (struct ax_disp *)tty->disc_data;	struct mkiss_channel *mkiss;	/* First make sure we're connected. */	if (ax == NULL || ax->magic != AX25_MAGIC || !ax->dev->start)		return;	if (ax->xleft <= 0)  {		/* Now serial buffer is almost free & we can start		 * transmission of another packet		 */		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);		if (ax->mkiss != NULL) {			mkiss= ax->mkiss->tty->driver_data;	        	if (mkiss->magic  == MKISS_DRIVER_MAGIC)				ax_unlock(ax->mkiss);	        }		ax_unlock(ax);		mark_bh(NET_BH);		return;	}	actual = tty->driver.write(tty, 0, ax->xhead, ax->xleft);	ax->xleft -= actual;	ax->xhead += actual;}/* Encapsulate an AX.25 packet and kick it into a TTY queue. */static int ax_xmit(struct sk_buff *skb, struct device *dev){	struct ax_disp *ax = (struct ax_disp*)dev->priv;	struct mkiss_channel *mkiss = ax->tty->driver_data;	struct ax_disp *tmp_ax;	tmp_ax = NULL;	if (mkiss->magic  == MKISS_DRIVER_MAGIC) {		if (skb->data[0] < 0x10)			skb->data[0] = skb->data[0] + 0x10;		tmp_ax = ax->mkiss;	}	if (!dev->start)  {		printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);		return 1;	}	if (tmp_ax != NULL)		if (tmp_ax->dev->tbusy)			return 1;	if (tmp_ax != NULL)		if (dev->tbusy) {			printk(KERN_ERR "mkiss: dev busy while serial dev is free\n");			ax_unlock(ax);	        }	if (dev->tbusy) {		/*		 * May be we must check transmitter timeout here ?		 *      14 Oct 1994 Dmitry Gorodchanin.		 */		if (jiffies - dev->trans_start  < 20 * HZ) {			/* 20 sec timeout not reached */			return 1;		}		printk(KERN_ERR "mkiss: %s: transmit timed out, %s?\n", dev->name,		       (ax->tty->driver.chars_in_buffer(ax->tty) || ax->xleft) ?		       "bad line quality" : "driver error");		ax->xleft = 0;		ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);		ax_unlock(ax);	}	/* We were not busy, so we are now... :-) */	if (skb != NULL) {		ax_lock(ax);		if (tmp_ax != NULL)			ax_lock(tmp_ax);		ax_encaps(ax, skb->data, skb->len);		kfree_skb(skb);	}	return 0;}#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)/* Return the frame type ID */static int ax_header(struct sk_buff *skb, struct device *dev, unsigned short type,	  void *daddr, void *saddr, unsigned len){#ifdef CONFIG_INET	if (type != htons(ETH_P_AX25))		return ax25_encapsulate(skb, dev, type, daddr, saddr, len);#endif	return 0;}static int ax_rebuild_header(struct sk_buff *skb){#ifdef CONFIG_INET	return ax25_rebuild_header(skb);#else	return 0;#endif}#endif	/* CONFIG_{AX25,AX25_MODULE} *//* Open the low-level part of the AX25 channel. Easy! */static int ax_open(struct device *dev){	struct ax_disp *ax = (struct ax_disp*)dev->priv;	unsigned long len;	if (ax->tty == NULL)		return -ENODEV;	/*	 * Allocate the frame buffers:	 *	 * rbuff	Receive buffer.	 * xbuff	Transmit buffer.	 * cbuff        Temporary compression buffer.	 */	len = dev->mtu * 2;	/*	 * allow for arrival of larger UDP packets, even if we say not to	 * also fixes a bug in which SunOS sends 512-byte packets even with	 * an MSS of 128	 */	if (len < 576 * 2)		len = 576 * 2;	if ((ax->rbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)		goto norbuff;	if ((ax->xbuff = kmalloc(len + 4, GFP_KERNEL)) == NULL)		goto noxbuff;	ax->mtu	     = dev->mtu + 73;	ax->buffsize = len;	ax->rcount   = 0;	ax->xleft    = 0;	ax->flags   &= (1 << AXF_INUSE);      /* Clear ESCAPE & ERROR flags */	dev->tbusy  = 0;	dev->start  = 1;	return 0;	/* Cleanup */	kfree(ax->xbuff);noxbuff:	kfree(ax->rbuff);norbuff:	return -ENOMEM;}/* Close the low-level part of the AX25 channel. Easy! */static int ax_close(struct device *dev){	struct ax_disp *ax = (struct ax_disp*)dev->priv;	if (ax->tty == NULL)		return -EBUSY;	ax->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);	dev->tbusy = 1;	dev->start = 0;	return 0;}static int ax25_receive_room(struct tty_struct *tty){	return 65536;  /* We can handle an infinite amount of data. :-) */}/* * Handle the 'receiver data ready' interrupt. * This function is called by the 'tty_io' module in the kernel when * a block of data has been received, which can now be decapsulated * and sent on to the AX.25 layer for further processing. */static void ax25_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count){	struct ax_disp *ax = (struct ax_disp *)tty->disc_data;	if (ax == NULL || ax->magic != AX25_MAGIC || !ax->dev->start)		return;	/*	 * Argh! mtu change time! - costs us the packet part received	 * at the change	 */	if (ax->mtu != ax->dev->mtu + 73)		ax_changedmtu(ax);	/* Read the characters out of the buffer */	while (count--) {		if (fp != NULL && *fp++) {			if (!test_and_set_bit(AXF_ERROR, &ax->flags))				ax->rx_errors++;			cp++;			continue;		}		kiss_unesc(ax, *cp++);	}}static int ax25_open(struct tty_struct *tty){	struct ax_disp *ax = (struct ax_disp *)tty->disc_data;	struct ax_disp *tmp_ax;	struct mkiss_channel *mkiss;	int err, cnt;	/* First make sure we're not already connected. */	if (ax && ax->magic == AX25_MAGIC)		return -EEXIST;	/* OK.  Find a free AX25 channel to use. */	if ((ax = ax_alloc()) == NULL)		return -ENFILE;	ax->tty = tty;	tty->disc_data = ax;	ax->mkiss = NULL;	tmp_ax    = NULL;	if (tty->driver.flush_buffer)		tty->driver.flush_buffer(tty);	if (tty->ldisc.flush_buffer)		tty->ldisc.flush_buffer(tty);	/* Restore default settings */	ax->dev->type = ARPHRD_AX25;	/* Perform the low-level AX25 initialization. */	if ((err = ax_open(ax->dev)))		return err;	mkiss= ax->tty->driver_data;	if (mkiss->magic  == MKISS_DRIVER_MAGIC) {		for (cnt = 1; cnt < ax25_maxdev; cnt++) {			if (ax25_ctrls[cnt]) {				if (ax25_ctrls[cnt]->dev.start) {					if (ax == &ax25_ctrls[cnt]->ctrl) {						cnt--;						tmp_ax = &ax25_ctrls[cnt]->ctrl;						break;					}				}			}		}	}	if (tmp_ax != NULL) {		ax->mkiss     = tmp_ax;		tmp_ax->mkiss = ax;	}	MOD_INC_USE_COUNT;	/* Done.  We have linked the TTY line to a channel. */	return ax->dev->base_addr;}static void ax25_close(struct tty_struct *tty){	struct ax_disp *ax = (struct ax_disp *)tty->disc_data;	int mkiss ;	/* First make sure we're connected. */	if (ax == NULL || ax->magic != AX25_MAGIC)		return;	mkiss = ax->mode;	dev_close(ax->dev);	tty->disc_data = 0;	ax->tty        = NULL;	/* VSV = very important to remove timers */	ax_free(ax);	unregister_netdev(ax->dev);	MOD_DEC_USE_COUNT;}static struct net_device_stats *ax_get_stats(struct device *dev){	static struct net_device_stats stats;	struct ax_disp *ax = (struct ax_disp*)dev->priv;	memset(&stats, 0, sizeof(struct net_device_stats));	stats.rx_packets     = ax->rx_packets;	stats.tx_packets     = ax->tx_packets;	stats.rx_dropped     = ax->rx_dropped;	stats.tx_dropped     = ax->tx_dropped;	stats.tx_errors      = ax->tx_errors;	stats.rx_errors      = ax->rx_errors;	stats.rx_over_errors = ax->rx_over_errors;	return &stats;}/************************************************************************ *			   STANDARD ENCAPSULATION	        	 * ************************************************************************/int kiss_esc(unsigned char *s, unsigned char *d, int len){	unsigned char *ptr = d;	unsigned char c;	/*	 * Send an initial END character to flush out any	 * data that may have accumulated in the receiver	 * due to line noise.	 */	*ptr++ = END;	while (len-- > 0) {		switch (c = *s++) {			case END:				*ptr++ = ESC;				*ptr++ = ESC_END;				break;			case ESC:				*ptr++ = ESC;				*ptr++ = ESC_ESC;				break;			default:				*ptr++ = c;				break;		}	}	*ptr++ = END;	return ptr - d;}/* * MW: * OK its ugly, but tell me a better solution without copying the * packet to a temporary buffer :-) */static int kiss_esc_crc(unsigned char *s, unsigned char *d, unsigned short crc, int len){	unsigned char *ptr = d;	unsigned char c;	*ptr++ = END;	while (len > 0) {		if (len > 2) 			c = *s++;		else if (len > 1)			c = crc >> 8;		else if (len > 0)			c = crc & 0xff;		len--;		switch (c) {                        case END:                                *ptr++ = ESC;                                *ptr++ = ESC_END;                                break;                        case ESC:                                *ptr++ = ESC;                                *ptr++ = ESC_ESC;                                break;                        default:                                *ptr++ = c;                                break;		}	}	*ptr++ = END;	return ptr - d;		}static void kiss_unesc(struct ax_disp *ax, unsigned char s)

⌨️ 快捷键说明

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