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

📄 sdla_fr.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Return:	1	physical address resolved. *		0	physical address not resolved */static int if_rebuild_hdr(struct sk_buff *skb){	struct device *dev=skb->dev;	fr_channel_t *chan = dev->priv;	sdla_t *card = chan->card;	printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",	       card->devname, dev->name);	return 1;}/*============================================================================ * Send a packet on a network interface. * o set tbusy flag (marks start of the transmission) to block a timer-based *   transmit from overlapping. * o check link state. If link is not up, then drop the packet. * o check channel status. If it's down then initiate a call. * o pass a packet to corresponding WAN device. * o free socket buffer * * Return:	0	complete (socket buffer must be freed) *		non-0	packet may be re-transmitted (tbusy must be set) * * Notes: * 1. This routine is called either by the protocol stack or by the "net *    bottom half" (with interrupts enabled). * 2. Setting tbusy flag will inhibit further transmit requests from the *    protocol stack and can be used for flow control with protocol layer. */static int if_send(struct sk_buff *skb, struct device *dev){	fr_channel_t *chan = dev->priv;	sdla_t *card = chan->card;	int retry = 0, err;	unsigned char *sendpacket;	struct device *dev2;	unsigned long check_braddr, check_mcaddr;	fr508_flags_t *adptr_flags = card->flags;	int udp_type, send_data;	fr_dlci_interface_t *dlci_interface = chan->dlci_int_interface;	unsigned long host_cpu_flags;	++chan->if_send_entry;	if (dev->tbusy) 	{		/* If our device stays busy for at least 5 seconds then we will		 * kick start the device by making dev->tbusy = 0.  We expect		 * that our device never stays busy more than 5 seconds. So this                 * is only used as a last resort.		 */		++chan->if_send_busy;		++chan->ifstats.collisions;		if ((jiffies - chan->tick_counter) < (5 * HZ))			return 1;		printk(KERN_INFO "%s: Transmit timed out\n", chan->name);		++chan->if_send_busy_timeout;		/* unbusy all the interfaces on the card */		for (dev2 = card->wandev.dev; dev2; dev2 = dev2->slave)			dev2->tbusy = 0;	}	sendpacket = skb->data;	udp_type = udp_pkt_type(skb, card);	if (udp_type == UDP_DRVSTATS_TYPE) 	{		++chan->if_send_DRVSTATS_request;		process_udp_driver_call(UDP_PKT_FRM_STACK, card, skb, dev, 0,					chan);		dev_kfree_skb(skb);		return 0;	}	else if (udp_type == UDP_FPIPE_TYPE)		++chan->if_send_FPIPE_request;	/* retreive source address in two forms: broadcast & multicast */	check_braddr = sendpacket[17];	check_mcaddr = sendpacket[14];	check_braddr = check_braddr << 8;	check_mcaddr = check_mcaddr << 8;	check_braddr |= sendpacket[16];	check_mcaddr |= sendpacket[15];	check_braddr = check_braddr << 8;	check_mcaddr = check_mcaddr << 8;	check_braddr |= sendpacket[15];	check_mcaddr |= sendpacket[16];	check_braddr = check_braddr << 8;	check_mcaddr = check_mcaddr << 8;	check_braddr |= sendpacket[14];	check_mcaddr |= sendpacket[17];	/* if the Source Address is a Multicast address */	if ((chan->mc == WANOPT_NO) && (check_mcaddr >= 0xE0000001) &&	    (check_mcaddr <= 0xFFFFFFFE)) 	{		printk(KERN_INFO "%s: Multicast Src. Addr. silently discarded\n"		       ,card->devname);		dev_kfree_skb(skb);		++chan->ifstats.tx_dropped;		++chan->if_send_multicast;		return 0;	}	disable_irq(card->hw.irq);	++card->irq_dis_if_send_count;	if (test_and_set_bit(0, (void *) &card->wandev.critical)) 	{		if (card->wandev.critical == CRITICAL_IN_ISR) 		{			++chan->if_send_critical_ISR;			if (card->intr_mode == DLCI_LIST_INTR_MODE) 			{				/* The enable_tx_int flag is set here so that if				 * the critical flag is set due to an interrupt 				 * then we want to enable transmit interrupts 				 * again.				 */				card->wandev.enable_tx_int = 1;				/* Setting this flag to WAITING_TO_BE_ENABLED 				 * specifies that interrupt bit has to be 				 * enabled for that particular interface. 				 * (delayed interrupt)				 */				chan->tx_int_status = WAITING_TO_BE_ENABLED;				/* This is used for enabling dynamic calculation				 * of CIRs relative to the packet length.				 */				chan->pkt_length = skb->len;				dev->tbusy = 1;				chan->tick_counter = jiffies;			}			else			{				card->wandev.enable_tx_int = 1;				dev->tbusy = 1;				chan->tick_counter = jiffies;			}			save_flags(host_cpu_flags);			cli();			if ((!(--card->irq_dis_if_send_count)) &&			    (!card->irq_dis_poll_count))				enable_irq(card->hw.irq);			restore_flags(host_cpu_flags);			return 1;		}		++chan->if_send_critical_non_ISR;		++chan->ifstats.tx_dropped;		dev_kfree_skb(skb);		save_flags(host_cpu_flags);		cli();		if ((!(--card->irq_dis_if_send_count)) &&		    (!card->irq_dis_poll_count))			enable_irq(card->hw.irq);		restore_flags(host_cpu_flags);		return 0;	}	card->wandev.critical = 0x21;	if (udp_type == UDP_FPIPE_TYPE) 	{		err = process_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb,					   dev, 0, chan);	}	else if (card->wandev.state != WAN_CONNECTED) 	{		++chan->if_send_wan_disconnected;		++chan->ifstats.tx_dropped;		++card->wandev.stats.tx_dropped;	}	else if (chan->state != WAN_CONNECTED) 	{		++chan->if_send_dlci_disconnected;		update_chan_state(dev);		++chan->ifstats.tx_dropped;		++card->wandev.stats.tx_dropped;	}	else if (!is_tx_ready(card, chan)) 	{		if (card->intr_mode == DLCI_LIST_INTR_MODE) 		{			dlci_interface->gen_interrupt |= 0x40;			dlci_interface->packet_length = skb->len;		}		dev->tbusy = 1;		chan->tick_counter = jiffies;		adptr_flags->imask |= 0x02;		++chan->if_send_no_bfrs;		retry = 1;	}	else	{		send_data = 1;		/* If it's an IPX packet */		if (sendpacket[1] == 0x00 &&		    sendpacket[2] == 0x80 &&		    sendpacket[6] == 0x81 &&		    sendpacket[7] == 0x37) 		{			if (card->wandev.enable_IPX) 			{				switch_net_numbers(sendpacket,					 card->wandev.network_number, 0);			} 			else 			{				/* increment some statistic here! */				send_data = 0;			}		}		if (send_data) 		{			err = (card->hw.fwid == SFID_FR508) ?			    fr508_send(card, chan->dlci, 0, skb->len, skb->data) :			    fr502_send(card, chan->dlci, 0, skb->len, skb->data);			if (err) 			{				if (card->intr_mode == DLCI_LIST_INTR_MODE) 				{					dlci_interface->gen_interrupt |= 0x40;					dlci_interface->packet_length = skb->len;				}				dev->tbusy = 1;				chan->tick_counter = jiffies;				adptr_flags->imask |= 0x02;				retry = 1;				++chan->if_send_adptr_bfrs_full;				++chan->ifstats.tx_errors;				++card->wandev.stats.tx_errors;			}			else 			{				++chan->if_send_bfrs_passed_to_adptr;				++chan->ifstats.tx_packets;				++card->wandev.stats.tx_packets;				chan->ifstats.tx_bytes += skb->len;				card->wandev.stats.tx_bytes += skb->len;			}		}	}	if (!retry)		dev_kfree_skb(skb);	card->wandev.critical = 0;	save_flags(host_cpu_flags);	cli();	if ((!(--card->irq_dis_if_send_count)) && (!card->irq_dis_poll_count))		enable_irq(card->hw.irq);	restore_flags(host_cpu_flags);	return retry;}/*============================================================================ * Reply to UDP Management system. * Return nothing. */static int reply_udp(unsigned char *data, unsigned int mbox_len){	unsigned short len, udp_length, temp, i, ip_length;	unsigned long sum;	/* Set length of packet */	len = mbox_len + 62;	/* fill in UDP reply */	data[38] = 0x02;	/* fill in UDP length */	udp_length = mbox_len + 40;	/* put it on an even boundary */	if (udp_length & 0x0001) 	{		udp_length += 1;		len += 1;	}	temp = (udp_length << 8) | (udp_length >> 8);	memcpy(&data[26], &temp, 2);	/* swap UDP ports */	memcpy(&temp, &data[22], 2);	memcpy(&data[22], &data[24], 2);	memcpy(&data[24], &temp, 2);	/* add UDP pseudo header */	temp = 0x1100;	memcpy(&data[udp_length + 22], &temp, 2);	temp = (udp_length << 8) | (udp_length >> 8);	memcpy(&data[udp_length + 24], &temp, 2);	/* calculate UDP checksum */	data[28] = data[29] = 0;	sum = 0;	for (i = 0; i < udp_length + 12; i += 2) 	{		memcpy(&temp, &data[14 + i], 2);		sum += (unsigned long) temp;	}	while (sum >> 16)		sum = (sum & 0xffffUL) + (sum >> 16);	temp = (unsigned short) sum;	temp = ~temp;	if (temp == 0)		temp = 0xffff;	memcpy(&data[28], &temp, 2);	/* fill in IP length */	ip_length = udp_length + 20;	temp = (ip_length << 8) | (ip_length >> 8);	memcpy(&data[4], &temp, 2);	/* swap IP addresses */	memcpy(&temp, &data[14], 2);	memcpy(&data[14], &data[18], 2);	memcpy(&data[18], &temp, 2);	memcpy(&temp, &data[16], 2);	memcpy(&data[16], &data[20], 2);	memcpy(&data[20], &temp, 2);	/* fill in IP checksum */	data[12] = data[13] = 0;	sum = 0;	for (i = 0; i < 20; i += 2) 	{		memcpy(&temp, &data[2 + i], 2);		sum += (unsigned long) temp;	}	while (sum >> 16)		sum = (sum & 0xffffUL) + (sum >> 16);	temp = (unsigned short) sum;	temp = ~temp;	if (temp == 0)		temp = 0xffff;	memcpy(&data[12], &temp, 2);	return len;}				/* reply_udp *//*   If incoming is 0 (outgoing)- if the net numbers is ours make it 0   if incoming is 1 - if the net number is 0 make it ours  */static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming){	unsigned long pnetwork_number;	pnetwork_number = (unsigned long) ((sendpacket[14] << 24) +			 (sendpacket[15] << 16) + (sendpacket[16] << 8) +					   sendpacket[17]);	if (!incoming) {		/* If the destination network number is ours, make it 0 */		if (pnetwork_number == network_number) {			sendpacket[14] = sendpacket[15] = sendpacket[16] =			    sendpacket[17] = 0x00;		}	} else {		/* If the incoming network is 0, make it ours */		if (pnetwork_number == 0) 		{			sendpacket[14] = (unsigned char) (network_number >> 24);			sendpacket[15] = (unsigned char) ((network_number &						      0x00FF0000) >> 16);			sendpacket[16] = (unsigned char) ((network_number &						       0x0000FF00) >> 8);			sendpacket[17] = (unsigned char) (network_number &							  0x000000FF);		}	}	pnetwork_number = (unsigned long) ((sendpacket[26] << 24) +			 (sendpacket[27] << 16) + (sendpacket[28] << 8) +					   sendpacket[29]);	if (!incoming) {		/* If the source network is ours, make it 0 */		if (pnetwork_number == network_number) 		{			sendpacket[26] = sendpacket[27] = sendpacket[28] =			    sendpacket[29] = 0x00;		}	} else {		/* If the source network is 0, make it ours */		if (pnetwork_number == 0) {			sendpacket[26] = (unsigned char) (network_number >> 24);			sendpacket[27] = (unsigned char) ((network_number &						      0x00FF0000) >> 16);			sendpacket[28] = (unsigned char) ((network_number &						       0x0000FF00) >> 8);			sendpacket[29] = (unsigned char) (network_number &							  0x000000FF);		}	}}				/* switch_net_numbers *//*============================================================================ * Get Ethernet-style interface statistics. * Return a pointer to struct net_device_stats. */static struct net_device_stats *if_stats(struct device *dev){	fr_channel_t *chan = dev->priv;	if(chan==NULL)		return NULL;			return &chan->ifstats;}/****** Interrupt Handlers **************************************************//*============================================================================ * S502 frame relay interrupt service routine. */static void fr502_isr(sdla_t * card){	fr502_flags_t *flags = card->flags;	switch (flags->iflag) 	{		case 0x01:		/* receive interrupt */			fr502_rx_intr(card);			break;		case 0x02:		/* transmit interrupt */			flags->imask &= ~0x02;			tx_intr(card);			break;		default:			spur_intr(card);	}	flags->iflag = 0;}/*============================================================================ * S508 frame relay interrupt service routine. */static void fr508_isr(sdla_t * card){	fr508_flags_t *flags = card->flags;	fr_buf_ctl_t *bctl;	char *ptr = &flags->iflag;

⌨️ 快捷键说明

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