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

📄 x25_asy.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	skb->protocol = htons(ETH_P_X25);	skb->mac.raw  = skb->data;	skb->pkt_type = PACKET_HOST;	netif_rx(skb);}/* Open the low-level part of the X.25 channel. Easy! */static int x25_asy_open(struct device *dev){	struct lapb_register_struct x25_asy_callbacks;	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->mtu	     = dev->mtu;	sl->buffsize = len;	sl->rcount   = 0;	sl->xleft    = 0;	sl->flags   &= (1 << SLF_INUSE);      /* Clear ESCAPE & ERROR flags */	dev->tbusy  = 0;/*	dev->flags |= IFF_UP; */	dev->start  = 1;		/*	 *	Now attach LAPB	 */	 	x25_asy_callbacks.connect_confirmation=x25_asy_connected;	x25_asy_callbacks.connect_indication=x25_asy_connected;	x25_asy_callbacks.disconnect_confirmation=x25_asy_disconnected;	x25_asy_callbacks.disconnect_indication=x25_asy_disconnected;	x25_asy_callbacks.data_indication=x25_asy_data_indication;	x25_asy_callbacks.data_transmit=x25_asy_data_transmit;	if((err=lapb_register(sl, &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 device *dev){	struct x25_asy *sl = (struct x25_asy*)(dev->priv);	int err;	if (sl->tty == NULL)		return -EBUSY;	sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);	dev->tbusy = 1;	dev->start = 0;	if((err=lapb_unregister(sl))!=LAPB_OK)		printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);/*	dev->flags &= ~IFF_UP; */	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 || !sl->dev->start)		return;	/*	 * Argh! mtu change time! - costs us the packet part received	 * at the change	 */	if (sl->mtu != sl->dev->mtu)  {		x25_asy_changed_mtu(sl);	}	/* Read the characters out of the buffer */	while (count--) {		if (fp && *fp++) {			if (!test_and_set_bit(SLF_ERROR, &sl->flags))  {				sl->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;	MOD_INC_USE_COUNT;	/* 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)	{		dev_lock_wait();		(void) dev_close(sl->dev);		dev_unlock_list();	}	tty->disc_data = 0;	sl->tty = NULL;	x25_asy_free(sl);	unregister_netdev(sl->dev);	MOD_DEC_USE_COUNT;}static struct net_device_stats *x25_asy_get_stats(struct device *dev){	static struct net_device_stats stats;	struct x25_asy *sl = (struct x25_asy*)(dev->priv);	memset(&stats, 0, sizeof(struct net_device_stats));	stats.rx_packets     = sl->rx_packets;	stats.tx_packets     = sl->tx_packets;	stats.rx_bytes	     = sl->rx_bytes;	stats.tx_bytes	     = sl->tx_bytes;	stats.rx_dropped     = sl->rx_dropped;	stats.tx_dropped     = sl->tx_dropped;	stats.tx_errors      = sl->tx_errors;	stats.rx_errors      = sl->rx_errors;	stats.rx_over_errors = sl->rx_over_errors;	return (&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->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, void *file, int cmd, void *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(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, (struct file *) file, cmd, (unsigned long) arg);		default:			return -ENOIOCTLCMD;	}}static int x25_asy_open_dev(struct device *dev){	struct x25_asy *sl = (struct x25_asy*)(dev->priv);	if(sl->tty==NULL)		return -ENODEV;	return 0;}/* Initialize X.25 control device -- register X.25 line discipline */#ifdef MODULEstatic int x25_asy_init_ctrl_dev(void)#else	/* !MODULE */__initfunc(int x25_asy_init_ctrl_dev(struct device *dummy))#endif	/* !MODULE */{	int status;	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_ctrls = (x25_asy_ctrl_t **) kmalloc(sizeof(void*)*x25_asy_maxdev, GFP_KERNEL);	if (x25_asy_ctrls == NULL)	{		printk("X25 async: Can't allocate x25_asy_ctrls[] array!  Uaargh! (-> No X.25 available)\n");		return -ENOMEM;	}	/* Clear the pointer array, we allocate devices when we need them */	memset(x25_asy_ctrls, 0, sizeof(void*)*x25_asy_maxdev); /* Pointers */	/* Fill in our line protocol discipline, and register it */	memset(&x25_ldisc, 0, sizeof(x25_ldisc));	x25_ldisc.magic  = TTY_LDISC_MAGIC;	x25_ldisc.name   = "X.25";	x25_ldisc.flags  = 0;	x25_ldisc.open   = x25_asy_open_tty;	x25_ldisc.close  = x25_asy_close_tty;	x25_ldisc.read   = NULL;	x25_ldisc.write  = NULL;	x25_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *,				   unsigned int, unsigned long)) x25_asy_ioctl;	x25_ldisc.poll   = NULL;	x25_ldisc.receive_buf = x25_asy_receive_buf;	x25_ldisc.receive_room = x25_asy_receive_room;	x25_ldisc.write_wakeup = x25_asy_write_wakeup;	if ((status = tty_register_ldisc(N_X25, &x25_ldisc)) != 0)  {		printk("X.25 async: can't register line discipline (err = %d)\n", status);	}#ifdef MODULE	return status;#else	/* Return "not found", so that dev_init() will unlink	 * the placeholder device entry for us.	 */	return ENODEV;#endif      }/* Initialise the X.25 driver.  Called by the device init code */int x25_asy_init(struct device *dev){	struct x25_asy *sl = (struct x25_asy*)(dev->priv);	if (sl == NULL)		/* Allocation failed ?? */		return -ENODEV;	/* Set up the control block. (And clear statistics) */	memset(sl, 0, sizeof (struct x25_asy));	sl->magic  = X25_ASY_MAGIC;	sl->dev	   = dev;	/*	 *	Finish setting up the DEVICE info. 	 */	 	dev->mtu		= SL_MTU;	dev->hard_start_xmit	= x25_asy_xmit;	dev->open		= x25_asy_open_dev;	dev->stop		= x25_asy_close;	dev->get_stats	        = x25_asy_get_stats;	dev->hard_header_len	= 0;	dev->addr_len		= 0;	dev->type		= ARPHRD_X25;	dev->tx_queue_len	= 10;	dev_init_buffers(dev);		/* New-style flags. */	dev->flags		= IFF_NOARP;	return 0;}#ifdef MODULEintinit_module(void){	return x25_asy_init_ctrl_dev();}voidcleanup_module(void){	int i;	if (x25_asy_ctrls != NULL)	{		for (i = 0; i < x25_asy_maxdev; i++)		{			if (x25_asy_ctrls[i])			{				/*				 * VSV = if dev->start==0, then device				 * unregistered while close proc.				 */				if (x25_asy_ctrls[i]->dev.start)					unregister_netdev(&(x25_asy_ctrls[i]->dev));				kfree(x25_asy_ctrls[i]);				x25_asy_ctrls[i] = NULL;			}		}		kfree(x25_asy_ctrls);		x25_asy_ctrls = NULL;	}	if ((i = tty_register_ldisc(N_X25, NULL)))	{		printk("X.25 async: can't unregister line discipline (err = %d)\n", i);	}}#endif /* MODULE */

⌨️ 快捷键说明

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