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

📄 x25_asy.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
{	struct x25_asy *sl = dev->priv;	struct sk_buff *skb;	unsigned char *ptr;	if ((skb = dev_alloc_skb(1)) == NULL) {		printk(KERN_ERR "x25_asy: out of memory\n");		return;	}	ptr  = skb_put(skb, 1);	*ptr = 0x02;	skb->protocol = x25_type_trans(skb, sl->dev);	netif_rx(skb);	sl->dev->last_rx = jiffies;}static struct lapb_register_struct x25_asy_callbacks = {	.connect_confirmation = x25_asy_connected,	.connect_indication = x25_asy_connected,	.disconnect_confirmation = x25_asy_disconnected,	.disconnect_indication = x25_asy_disconnected,	.data_indication = x25_asy_data_indication,	.data_transmit = x25_asy_data_transmit,};/* Open the low-level part of the X.25 channel. Easy! */static int x25_asy_open(struct net_device *dev){	struct x25_asy *sl = (struct x25_asy*)(dev->priv);	unsigned long len;	int err;	if (sl->tty == NULL)		return -ENODEV;	/*	 * Allocate the X.25 frame buffers:	 *	 * rbuff	Receive buffer.	 * xbuff	Transmit buffer.	 */	len = dev->mtu * 2;	sl->rbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);	if (sl->rbuff == NULL)   {		goto norbuff;	}	sl->xbuff = (unsigned char *) kmalloc(len + 4, GFP_KERNEL);	if (sl->xbuff == NULL)   {		goto noxbuff;	}	sl->buffsize = len;	sl->rcount   = 0;	sl->xleft    = 0;	sl->flags   &= (1 << SLF_INUSE);      /* Clear ESCAPE & ERROR flags */	netif_start_queue(dev);				/*	 *	Now attach LAPB	 */	if((err=lapb_register(dev, &x25_asy_callbacks))==LAPB_OK)		return 0;	/* Cleanup */	kfree(sl->xbuff);noxbuff:	kfree(sl->rbuff);norbuff:	return -ENOMEM;}/* Close the low-level part of the X.25 channel. Easy! */static int x25_asy_close(struct net_device *dev){	struct x25_asy *sl = (struct x25_asy*)(dev->priv);	int err;	spin_lock(&sl->lock);	if (sl->tty) 		sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);	netif_stop_queue(dev);	sl->rcount = 0;	sl->xleft  = 0;	if((err=lapb_unregister(dev))!=LAPB_OK)		printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);	spin_unlock(&sl->lock);	return 0;}static int x25_asy_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 X.25 data has been received, which can now be decapsulated * and sent on to some IP layer for further processing. */ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count){	struct x25_asy *sl = (struct x25_asy *) tty->disc_data;	if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))		return;	/* Read the characters out of the buffer */	while (count--) {		if (fp && *fp++) {			if (!test_and_set_bit(SLF_ERROR, &sl->flags))  {				sl->stats.rx_errors++;			}			cp++;			continue;		}		x25_asy_unesc(sl, *cp++);	}}/* * Open the high-level part of the X.25 channel. * This function is called by the TTY module when the * X.25 line discipline is called for.  Because we are * sure the tty line exists, we only have to link it to * a free X.25 channel... */static int x25_asy_open_tty(struct tty_struct *tty){	struct x25_asy *sl = (struct x25_asy *) tty->disc_data;	int err;	/* First make sure we're not already connected. */	if (sl && sl->magic == X25_ASY_MAGIC) {		return -EEXIST;	}	/* OK.  Find a free X.25 channel to use. */	if ((sl = x25_asy_alloc()) == NULL) {		return -ENFILE;	}	sl->tty = tty;	tty->disc_data = sl;	if (tty->driver->flush_buffer)  {		tty->driver->flush_buffer(tty);	}	if (tty->ldisc.flush_buffer)  {		tty->ldisc.flush_buffer(tty);	}	/* Restore default settings */	sl->dev->type = ARPHRD_X25;		/* Perform the low-level X.25 async init */	if ((err = x25_asy_open(sl->dev)))		return err;	/* Done.  We have linked the TTY line to a channel. */	return sl->dev->base_addr;}/* * Close down an X.25 channel. * This means flushing out any pending queues, and then restoring the * TTY line discipline to what it was before it got hooked to X.25 * (which usually is TTY again). */static void x25_asy_close_tty(struct tty_struct *tty){	struct x25_asy *sl = (struct x25_asy *) tty->disc_data;	/* First make sure we're connected. */	if (!sl || sl->magic != X25_ASY_MAGIC)		return;	if (sl->dev->flags & IFF_UP)	{		(void) dev_close(sl->dev);	}	tty->disc_data = NULL;	sl->tty = NULL;	x25_asy_free(sl);}static struct net_device_stats *x25_asy_get_stats(struct net_device *dev){	struct x25_asy *sl = (struct x25_asy*)(dev->priv);	return &sl->stats;} /************************************************************************  *			STANDARD X.25 ENCAPSULATION		  	 *  ************************************************************************/int x25_asy_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++ = X25_END;	/* Send 10111110 bit seq */	/*	 * For each byte in the packet, send the appropriate	 * character sequence, according to the X.25 protocol.	 */	while (len-- > 0) 	{		switch(c = *s++) 		{			case X25_END:				*ptr++ = X25_ESC;				*ptr++ = X25_ESCAPE(X25_END);				break;			case X25_ESC:				*ptr++ = X25_ESC;				*ptr++ = X25_ESCAPE(X25_ESC);				break;			 default:				*ptr++ = c;				break;		}	}	*ptr++ = X25_END;	return (ptr - d);}static void x25_asy_unesc(struct x25_asy *sl, unsigned char s){	switch(s) 	{		case X25_END:			if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))  			{				x25_asy_bump(sl);			}			clear_bit(SLF_ESCAPE, &sl->flags);			sl->rcount = 0;			return;		case X25_ESC:			set_bit(SLF_ESCAPE, &sl->flags);			return;					case X25_ESCAPE(X25_ESC):		case X25_ESCAPE(X25_END):			if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))				s = X25_UNESCAPE(s);			break;	}	if (!test_bit(SLF_ERROR, &sl->flags))  	{		if (sl->rcount < sl->buffsize)  		{			sl->rbuff[sl->rcount++] = s;			return;		}		sl->stats.rx_over_errors++;		set_bit(SLF_ERROR, &sl->flags);	}}/* Perform I/O control on an active X.25 channel. */static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,			 unsigned int cmd,  unsigned long arg){	struct x25_asy *sl = (struct x25_asy *) tty->disc_data;	/* First make sure we're connected. */	if (!sl || sl->magic != X25_ASY_MAGIC)		return -EINVAL;	switch(cmd) {	case SIOCGIFNAME:		if (copy_to_user((void __user *)arg, sl->dev->name,					strlen(sl->dev->name) + 1))			return -EFAULT;		return 0;	case SIOCSIFHWADDR:		return -EINVAL;	/* Allow stty to read, but not set, the serial port */	case TCGETS:	case TCGETA:		return n_tty_ioctl(tty, file, cmd, arg);	default:		return -ENOIOCTLCMD;	}}static int x25_asy_open_dev(struct net_device *dev){	struct x25_asy *sl = (struct x25_asy*)(dev->priv);	if(sl->tty==NULL)		return -ENODEV;	return 0;}/* Initialise the X.25 driver.  Called by the device init code */static void x25_asy_setup(struct net_device *dev){	struct x25_asy *sl = dev->priv;	sl->magic  = X25_ASY_MAGIC;	sl->dev	   = dev;	spin_lock_init(&sl->lock);	set_bit(SLF_INUSE, &sl->flags);	/*	 *	Finish setting up the DEVICE info. 	 */	 	dev->mtu		= SL_MTU;	dev->hard_start_xmit	= x25_asy_xmit;	dev->tx_timeout		= x25_asy_timeout;	dev->watchdog_timeo	= HZ*20;	dev->open		= x25_asy_open_dev;	dev->stop		= x25_asy_close;	dev->get_stats	        = x25_asy_get_stats;	dev->change_mtu		= x25_asy_change_mtu;	dev->hard_header_len	= 0;	dev->addr_len		= 0;	dev->type		= ARPHRD_X25;	dev->tx_queue_len	= 10;	/* New-style flags. */	dev->flags		= IFF_NOARP;}static struct tty_ldisc x25_ldisc = {	.owner		= THIS_MODULE,	.magic		= TTY_LDISC_MAGIC,	.name		= "X.25",	.open		= x25_asy_open_tty,	.close		= x25_asy_close_tty,	.ioctl		= x25_asy_ioctl,	.receive_buf	= x25_asy_receive_buf,	.receive_room	= x25_asy_receive_room,	.write_wakeup	= x25_asy_write_wakeup,};static int __init init_x25_asy(void){	if (x25_asy_maxdev < 4)		x25_asy_maxdev = 4; /* Sanity */	printk(KERN_INFO "X.25 async: version 0.00 ALPHA "			"(dynamic channels, max=%d).\n", x25_asy_maxdev );	x25_asy_devs = kmalloc(sizeof(struct net_device *)*x25_asy_maxdev, 			       GFP_KERNEL);	if (!x25_asy_devs) {		printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] "				"array! Uaargh! (-> No X.25 available)\n");		return -ENOMEM;	}	memset(x25_asy_devs, 0, sizeof(struct net_device *)*x25_asy_maxdev); 	return tty_register_ldisc(N_X25, &x25_ldisc);}static void __exit exit_x25_asy(void){	struct net_device *dev;	int i;	for (i = 0; i < x25_asy_maxdev; i++) {		dev = x25_asy_devs[i];		if (dev) {			struct x25_asy *sl = dev->priv;			spin_lock_bh(&sl->lock);			if (sl->tty) 				tty_hangup(sl->tty);			spin_unlock_bh(&sl->lock);			/*			 * VSV = if dev->start==0, then device			 * unregistered while close proc.			 */			unregister_netdev(dev);			free_netdev(dev);		}	}	kfree(x25_asy_devs);	tty_unregister_ldisc(N_X25);}module_init(init_x25_asy);module_exit(exit_x25_asy);

⌨️ 快捷键说明

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