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

📄 sdla_x25.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
 */static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb){	unsigned new_lcn = mb->cmd.lcn;	struct device* dev = get_dev_by_lcn(&card->wandev, new_lcn);	printk(KERN_INFO "%s: X.25 clear request on LCN %d! Cause:0x%02X "		"Diagn:0x%02X\n",		card->devname, new_lcn, mb->cmd.cause, mb->cmd.diagn);	if (dev == NULL)		return 1;	set_chan_state(dev, WAN_DISCONNECTED);	return ((cmd == X25_WRITE) && (lcn == new_lcn)) ? 0 : 1;}/*============================================================================ * Handle X.25 restart event. */ static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb){	wan_device_t* wandev = &card->wandev;	struct device* dev;	printk(KERN_INFO		"%s: X.25 restart request! Cause:0x%02X Diagn:0x%02X\n",		card->devname, mb->cmd.cause, mb->cmd.diagn);	/* down all logical channels */	for (dev = wandev->dev; dev; dev = dev->slave)		set_chan_state(dev, WAN_DISCONNECTED);	return (cmd == X25_WRITE) ? 0 : 1;}/*============================================================================ * Handle timeout event. */static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb){	unsigned new_lcn = mb->cmd.lcn;	if (mb->cmd.pktType == 0x05)	/* call request time out */	{		struct device* dev = get_dev_by_lcn(&card->wandev, new_lcn);		printk(KERN_INFO "%s: X.25 call timed timeout on LCN %d!\n",			card->devname, new_lcn);		if (dev)			set_chan_state(dev, WAN_DISCONNECTED);	}	else printk(KERN_INFO "%s: X.25 packet 0x%02X timeout on LCN %d!\n",		card->devname, mb->cmd.pktType, new_lcn);	return 1;}/******* Miscellaneous ******************************************************//*============================================================================ * Establish physical connection. * o open HDLC and raise DTR * * Return:	0	connection established *		1	connection is in progress *		<0	error */static int connect (sdla_t* card){	if (x25_open_hdlc(card) || x25_setup_hdlc(card))		return -EIO;	wanpipe_set_state(card, WAN_CONNECTING);	return 1;}/*============================================================================ * Tear down physical connection. * o close HDLC link * o drop DTR * * Return:	0 *		<0	error */static int disconnect (sdla_t* card){	wanpipe_set_state(card, WAN_DISCONNECTED);	x25_set_intr_mode(card, 0);	/* disable interrupt generation */	x25_close_hdlc(card);		/* close HDLC link */	x25_set_dtr(card, 0);		/* drop DTR */	return 0;}/*============================================================================ * Find network device by its channel number. */static struct device* get_dev_by_lcn (wan_device_t* wandev, unsigned lcn){	struct device* dev;	for (dev = wandev->dev; dev; dev = dev->slave)		if (((x25_channel_t*)dev->priv)->lcn == lcn)			break;	return dev;}/*============================================================================ * Initiate connection on the logical channel. * o for PVC we just get channel configuration * o for SVCs place an X.25 call * * Return:	0	connected *		>0	connection in progress *		<0	failure */static int chan_connect (struct device* dev){	x25_channel_t* chan = dev->priv;	sdla_t* card = chan->card;	if (chan->svc)	{		if (!chan->addr[0])			return -EINVAL;	/* no destination address */		printk(KERN_INFO "%s: placing X.25 call to %s ...\n",			card->devname, chan->addr);		if (x25_place_call(card, chan) != CMD_OK)			return -EIO;		set_chan_state(dev, WAN_CONNECTING);		return 1;	}	else	{		if (x25_get_chan_conf(card, chan) != CMD_OK)			return -EIO;		set_chan_state(dev, WAN_CONNECTED);	}	return 0;}/*============================================================================ * Disconnect logical channel. * o if SVC then clear X.25 call */static int chan_disc (struct device* dev){	x25_channel_t* chan = dev->priv;	if (chan->svc)		x25_clear_call(chan->card, chan->lcn, 0, 0);	set_chan_state(dev, WAN_DISCONNECTED);	return 0;}/*============================================================================ * Set logical channel state. */static void set_chan_state (struct device* dev, int state){	x25_channel_t* chan = dev->priv;	sdla_t* card = chan->card;	unsigned long flags;	save_flags(flags);	cli();	if (chan->state != state)	{		switch (state)		{			case WAN_CONNECTED:				printk (KERN_INFO "%s: interface %s connected!\n",					card->devname, dev->name);				*(unsigned short*)dev->dev_addr = htons(chan->lcn);				chan->i_timeout_sofar = jiffies;				break;			case WAN_CONNECTING:				printk (KERN_INFO "%s: interface %s connecting...\n",					card->devname, dev->name);				break;			case WAN_DISCONNECTED:				printk (KERN_INFO "%s: interface %s disconnected!\n",					card->devname, dev->name);				if (chan->svc) 				{					*(unsigned short*)dev->dev_addr = 0;		                	chan->lcn = 0;				}				break;		}		chan->state = state;	}	chan->state_tick = jiffies;	restore_flags(flags);}/*============================================================================ * Send packet on a logical channel. *	When this function is called, tx_skb field of the channel data space *	points to the transmit socket buffer.  When transmission is complete, *	release socket buffer and reset 'tbusy' flag. * * Return:	0	- transmission complete *		1	- busy * * Notes: * 1. If packet length is greater than MTU for this channel, we'll fragment *    the packet into 'complete sequence' using M-bit. * 2. When transmission is complete, an event notification should be issued *    to the router. */static int chan_send (struct device* dev, struct sk_buff* skb){	x25_channel_t* chan = dev->priv;	sdla_t* card = chan->card;	TX25Status* status = card->flags;	unsigned len, qdm;	/* Check to see if channel is ready */	if (!(status->cflags[chan->ch_idx] & 0x40))		return 1;	if (skb->len > chan->tx_pkt_size)	{		len = chan->tx_pkt_size;		qdm = 0x01;		/* set M-bit (more data) */	}	else	/* final packet */	{		len = skb->len;		qdm = 0;	}	switch(x25_send(card, chan->lcn, qdm, len, skb->data))	{		case 0x00:	/* success */			chan->i_timeout_sofar = jiffies;			if (qdm)			{				skb_pull(skb, len);				return 1;			}			++chan->ifstats.tx_packets;			chan->ifstats.tx_bytes += skb->len;			break;		case 0x33:	/* Tx busy */			return 1;		default:	/* failure */			++chan->ifstats.tx_errors;/*			return 1; */	}	return 0;}/*============================================================================ * Parse X.25 call request data and fill x25_call_info_t structure. */static void parse_call_info (unsigned char* str, x25_call_info_t* info){	memset(info, 0, sizeof(x25_call_info_t));	for (; *str; ++str)	{		int i;		unsigned ch;		if (*str == '-') switch (str[1])		{			case 'd':	/* destination address */				for (i = 0; i < 16; ++i)				{					ch = str[2+i];					if (!is_digit(ch)) 						break;					info->dest[i] = ch;				}				break;				case 's':	/* source address */				for (i = 0; i < 16; ++i)				{					ch = str[2+i];					if (!is_digit(ch))						break;					info->src[i] = ch;				}				break;			case 'u':	/* user data */				for (i = 0; i < 127; ++i)				{					ch = str[2+2*i];					if (!is_hex_digit(ch)) 						break;					info->user[i] = hex_to_uint(&str[2+2*i], 2);				}				info->nuser = i;				break;			case 'f':	/* facilities */				for (i = 0; i < 64; ++i)				{					ch = str[2+4*i];					if (!is_hex_digit(ch))						break;					info->facil[i].code =						hex_to_uint(&str[2+4*i], 2);					ch = str[4+4*i];					if (!is_hex_digit(ch))						break;					info->facil[i].parm =						hex_to_uint(&str[4+4*i], 2);				}				info->nfacil = i;				break;		}	}}/*============================================================================ * Convert line speed in bps to a number used by S502 code. */static unsigned char bps_to_speed_code (unsigned long bps){	unsigned char	number;	if (bps <= 1200)        number = 0x01 ;	else if (bps <= 2400)   number = 0x02;	else if (bps <= 4800)   number = 0x03;	else if (bps <= 9600)   number = 0x04;	else if (bps <= 19200)  number = 0x05;	else if (bps <= 38400)  number = 0x06;	else if (bps <= 45000)  number = 0x07;	else if (bps <= 56000)  number = 0x08;	else if (bps <= 64000)  number = 0x09;	else if (bps <= 74000)  number = 0x0A;	else if (bps <= 112000) number = 0x0B;	else if (bps <= 128000) number = 0x0C;	else number = 0x0D;	return number;}/*============================================================================ * Convert decimal string to unsigned integer. * If len != 0 then only 'len' characters of the string are converted. */static unsigned int dec_to_uint (unsigned char* str, int len){	unsigned val;	if (!len) len = strlen(str);	for (val = 0; len && is_digit(*str); ++str, --len)		val = (val * 10) + (*str - (unsigned)'0');	return val;}/*============================================================================ * Convert hex string to unsigned integer. * If len != 0 then only 'len' characters of the string are conferted. */static unsigned int hex_to_uint (unsigned char* str, int len){	unsigned val, ch;	if (!len) len = strlen(str);	for (val = 0; len; ++str, --len)	{		ch = *str;		if (is_digit(ch))			val = (val << 4) + (ch - (unsigned)'0');		else if (is_hex_digit(ch))			val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10);		else			break;	}	return val;}static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto){	int i;	if( proto == htons(ETH_P_IPX) ) {		/* It's an IPX packet */		if(!enable_IPX) {			/* Return 1 so we don't pass it up the stack. */			return 1;		}	} else {		/* It's not IPX so pass it up the stack. */		return 0;	}	if( sendpacket[16] == 0x90 &&	    sendpacket[17] == 0x04)	{		/* It's IPXWAN */		if( sendpacket[2] == 0x02 &&		    sendpacket[34] == 0x00)		{			/* It's a timer request packet */			printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname);			/* Go through the routing options and answer no to every			 * option except Unnumbered RIP/SAP */			for(i = 41; sendpacket[i] == 0x00; i += 5)			{				/* 0x02 is the option for Unnumbered RIP/SAP */				if( sendpacket[i + 4] != 0x02)					sendpacket[i + 1] = 0;			}			/* Skip over the extended Node ID option */			if( sendpacket[i] == 0x04 )				i += 8;			/* We also want to turn off all header compression opt. */			for(; sendpacket[i] == 0x80 ;)			{				sendpacket[i + 1] = 0;				i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4;			}			/* Set the packet type to timer response */			sendpacket[34] = 0x01;			printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname);		}		else if( sendpacket[34] == 0x02 )		{			/* This is an information request packet */			printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname);			/* Set the packet type to information response */			sendpacket[34] = 0x03;			/* Set the router name */			sendpacket[51] = 'X';			sendpacket[52] = 'T';			sendpacket[53] = 'P';			sendpacket[54] = 'I';			sendpacket[55] = 'P';			sendpacket[56] = 'E';			sendpacket[57] = '-';			sendpacket[58] = CVHexToAscii(network_number >> 28);			sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24);			sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20);			sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16);			sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12);			sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8);			sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4);			sendpacket[65] = CVHexToAscii(network_number & 0x0000000F);			for(i = 66; i < 99; i+= 1)				sendpacket[i] = 0;			printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname);		}		else		{			printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname);			return 0;		}		/* Set the WNodeID to our network address */		sendpacket[35] = (unsigned char)(network_number >> 24);		sendpacket[36] = (unsigned char)((network_number & 0x00FF00

⌨️ 快捷键说明

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