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

📄 sdla_fr.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct device *dev = card->wandev.dev;	struct device *dev2;	int i;	unsigned long host_cpu_flags;	unsigned disable_tx_intr = 1;	fr_channel_t *chan;	fr_dlci_interface_t *dlci_interface;	/* This flag prevents nesting of interrupts.  See sdla_isr() routine	 * in sdlamain.c. 	 */	card->in_isr = 1;	++card->statistics.isr_entry;	if (test_and_set_bit(0, (void *) &card->wandev.critical)) 	{		printk(KERN_INFO "fr508_isr: %s, wandev.critical set to 0x%02X, int type = 0x%02X\n", card->devname, card->wandev.critical, flags->iflag);		++card->statistics.isr_already_critical;		card->in_isr = 0;		return;	}	/* For all interrupts set the critical flag to CRITICAL_RX_INTR.	 * If the if_send routine is called with this flag set it will set	 * the enable transmit flag to 1. (for a delayed interrupt)	 */	card->wandev.critical = CRITICAL_IN_ISR;	card->dlci_int_mode_unbusy = 0;	card->buff_int_mode_unbusy = 0;	switch (flags->iflag) 	{		case 0x01:		/* receive interrupt */			++card->statistics.isr_rx;			fr508_rx_intr(card);			break;		case 0x02:		/* transmit interrupt */			++card->statistics.isr_tx;			bctl = (void *) (flags->tse_offs - FR_MB_VECTOR +				 card->hw.dpmbase);			bctl->flag = 0xA0;			if (card->intr_mode == DLCI_LIST_INTR_MODE) 			{				/* Find the structure and make it unbusy */				dev = find_channel(card, flags->dlci);				dev->tbusy = 0;				/* This is used to perform devtint at the				 * end of the isr 				 */				card->dlci_int_mode_unbusy = 1;				/* check to see if any other interfaces are				 * busy. If so then do not disable the tx				 * interrupts 				 */				for (dev2 = card->wandev.dev; dev2;					dev2 = dev2->slave) 				{					if (dev2->tbusy == 1) 					{						disable_tx_intr = 0;						break;					}				}				if (disable_tx_intr)					flags->imask &= ~0x02;			} 			else if (card->intr_mode == BUFFER_INTR_MODE) 			{				for (dev2 = card->wandev.dev; dev2;					dev2 = dev2->slave) 				{					if (!dev2 || !dev2->start) 					{						++card->statistics.tx_intr_dev_not_started;						continue;					}					if (dev2->tbusy) 					{						card->buff_int_mode_unbusy = 1;						((fr_channel_t *) dev2->priv)->dev_pending_devtint = 1;						dev2->tbusy = 0;					} 					else						((fr_channel_t *) dev2->priv)->dev_pending_devtint = 0;				}				flags->imask &= ~0x02;			}			break;		case 0x08:			Intr_test_counter++;			++card->statistics.isr_intr_test;			break;		default:			++card->statistics.isr_spurious;			spur_intr(card);			printk(KERN_INFO "%s: Interrupt Type 0x%02X!\n",			       card->devname, flags->iflag);			printk(KERN_INFO "%s: ID Bytes = ", card->devname);			for (i = 0; i < 8; i++)				printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));			printk(KERN_INFO "\n");			break;	}	card->wandev.critical = CRITICAL_INTR_HANDLED;	if (card->wandev.enable_tx_int) 	{		if (card->intr_mode == DLCI_LIST_INTR_MODE) 		{			for (dev2 = card->wandev.dev; dev2; dev2 = dev2->slave) 			{				chan = dev2->priv;				if (chan->tx_int_status == WAITING_TO_BE_ENABLED) 				{					dlci_interface = chan->dlci_int_interface;					dlci_interface->gen_interrupt |= 0x40;					dlci_interface->packet_length = chan->pkt_length;					chan->tx_int_status = DISABLED;				}			}		}		card->wandev.enable_tx_int = 0;		flags->imask |= 0x02;		++card->statistics.isr_enable_tx_int;	}	save_flags(host_cpu_flags);	cli();	card->in_isr = 0;	card->wandev.critical = 0xD1;	flags->iflag = 0;	card->wandev.critical = 0;	restore_flags(host_cpu_flags);	/* Device is now ready to send. The instant this is executed the If_Send	   routine is called. That is why this is put at the bottom of the ISR	   to prevent a endless loop condition caused by repeated Interrupts and	   enable_tx_int flag.	 */	if (card->dlci_int_mode_unbusy)		mark_bh(NET_BH);	if (card->buff_int_mode_unbusy) 	{		for (;;) 		{			if (((fr_channel_t *) ((card->devs_struct)->dev_ptr)->priv)->dev_pending_devtint == 1) 			{				((fr_channel_t *) ((card->devs_struct)->dev_ptr)->priv)->dev_pending_devtint = 0;				mark_bh(NET_BH);			}			if ((card->devs_struct)->next == card->dev_to_devtint_next)				break;			card->devs_struct = (card->devs_struct)->next;		}		card->devs_struct = (card->dev_to_devtint_next)->next;		card->dev_to_devtint_next = card->devs_struct;	}}/*============================================================================ * Receive interrupt handler. */static void fr502_rx_intr(sdla_t * card){	fr_mbox_t *mbox = card->rxmb;	struct sk_buff *skb;	struct device *dev;	fr_channel_t *chan;	unsigned dlci, len;	void *buf;	unsigned char *sendpacket;	unsigned char buf2[3];	int udp_type;	sdla_mapmem(&card->hw, FR502_RX_VECTOR);	dlci = mbox->cmd.dlci;	len = mbox->cmd.length;	/* Find network interface for this packet */	dev = find_channel(card, dlci);	if (dev == NULL) 	{		/* Invalid channel, discard packet */		printk(KERN_INFO "%s: receiving on orphaned DLCI %d!\n",		       card->devname, dlci);		sdla_mapmem(&card->hw, FR_MB_VECTOR);	}	chan = dev->priv;	if (!dev->start) 	{		++chan->ifstats.rx_dropped;		sdla_mapmem(&card->hw, FR_MB_VECTOR);	}	/* Allocate socket buffer */	skb = dev_alloc_skb(len);	if (skb == NULL) 	{		printk(KERN_INFO "%s: no socket buffers available!\n",		       card->devname);		++chan->ifstats.rx_dropped;		sdla_mapmem(&card->hw, FR_MB_VECTOR);	}	/* Copy data to the socket buffer */	buf = skb_put(skb, len);	memcpy(buf, mbox->data, len);	sdla_mapmem(&card->hw, FR_MB_VECTOR);	/* Check if it's a UDP management packet */	sendpacket = skb->data;	memcpy(&buf2, &card->wandev.udp_port, 2);	udp_type = udp_pkt_type(skb, card);	if ((udp_type == UDP_FPIPE_TYPE) || (udp_type == UDP_DRVSTATS_TYPE)) 	{		if (udp_type == UDP_DRVSTATS_TYPE) 		{			++chan->rx_intr_DRVSTATS_request;			process_udp_driver_call(UDP_PKT_FRM_NETWORK, card, skb,						dev, dlci, chan);		}		else		{			++chan->rx_intr_FPIPE_request;			process_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, card, skb,					     dev, dlci, chan);		}	}	else	{		/* Decapsulate packet and pass it up the protocol stack */		skb->dev = dev;		buf = skb_pull(skb, 1);		/* remove hardware header */		if (!wanrouter_type_trans(skb, dev)) 		{			/* can't decapsulate packet */			dev_kfree_skb(skb);			++chan->ifstats.rx_errors;			++card->wandev.stats.rx_errors;		}		else 		{			netif_rx(skb);			++chan->ifstats.rx_packets;			++card->wandev.stats.rx_packets;			chan->ifstats.rx_bytes += skb->len;			card->wandev.stats.rx_bytes += skb->len;		}	}	sdla_mapmem(&card->hw, FR_MB_VECTOR);}/*============================================================================ * Receive interrupt handler. */static void fr508_rx_intr(sdla_t * card){	fr_buf_ctl_t *frbuf = card->rxmb;	struct sk_buff *skb;	struct device *dev;	fr_channel_t *chan;	unsigned dlci, len, offs;	void *buf;	unsigned rx_count = 0;	fr508_flags_t *flags = card->flags;	char *ptr = &flags->iflag;	int i, err, udp_type;	if (frbuf->flag != 0x01) 	{		printk(KERN_INFO		       "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n",		       card->devname, (unsigned) frbuf, frbuf->flag);		printk(KERN_INFO "%s: ID Bytes = ", card->devname);		for (i = 0; i < 8; i++)			printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i));		printk(KERN_INFO "\n");		++card->statistics.rx_intr_corrupt_rx_bfr;		return;	}		do 	{		len = frbuf->length;		dlci = frbuf->dlci;		offs = frbuf->offset;		/* Find network interface for this packet */		dev = find_channel(card, dlci);		chan = dev->priv;		if (dev == NULL) 		{			/* Invalid channel, discard packet */			printk(KERN_INFO "%s: receiving on orphaned DLCI %d!\n"			       ,card->devname, dlci);			++card->statistics.rx_intr_on_orphaned_DLCI;		}		else		{			skb = dev_alloc_skb(len);			if (!dev->start || (skb == NULL)) 			{				++chan->ifstats.rx_dropped;				if (dev->start) 				{					printk(KERN_INFO					       "%s: no socket buffers available!\n",					       card->devname);					++chan->rx_intr_no_socket;				} else					++chan->rx_intr_dev_not_started;			}			else			{				/* Copy data to the socket buffer */				if ((offs + len) > card->u.f.rx_top + 1) 				{					unsigned tmp = card->u.f.rx_top - offs + 1;					buf = skb_put(skb, tmp);					sdla_peek(&card->hw, offs, buf, tmp);					offs = card->u.f.rx_base;					len -= tmp;				}				buf = skb_put(skb, len);				sdla_peek(&card->hw, offs, buf, len);				udp_type = udp_pkt_type(skb, card);				if (udp_type == UDP_DRVSTATS_TYPE) 				{					++chan->rx_intr_DRVSTATS_request;					process_udp_driver_call(					  UDP_PKT_FRM_NETWORK, card, skb,							dev, dlci, chan);				}				else if (udp_type == UDP_FPIPE_TYPE) 				{					++chan->rx_intr_FPIPE_request;					err = process_udp_mgmt_pkt(					       UDP_PKT_FRM_NETWORK, card,						   skb, dev, dlci, chan);				}				else if (handle_IPXWAN(skb->data, card->devname, card->wandev.enable_IPX, card->wandev.network_number)) 				{					if (card->wandev.enable_IPX) 						fr508_send(card, dlci, 0, skb->len, skb->data);				} 				else				{					/* Decapsulate packet and pass it up the					   protocol stack */					skb->dev = dev;					/* remove hardware header */					buf = skb_pull(skb, 1);					if (!wanrouter_type_trans(skb, dev)) 					{						/* can't decapsulate packet */						dev_kfree_skb(skb);						++chan->						    rx_intr_bfr_not_passed_to_stack;						++chan->						    ifstats.rx_errors;						++card->						    wandev.stats.rx_errors;					}					else					{						netif_rx(skb);						++chan->rx_intr_bfr_passed_to_stack;						++chan->ifstats.rx_packets;						++card->wandev.stats.rx_packets;						chan->ifstats.rx_bytes += skb->len;						card->wandev.stats.rx_bytes += skb->len;					}				}			}		}		/* Release buffer element and calculate a pointer to the next 		   one */		frbuf->flag = 0;		card->rxmb = ++frbuf;		if ((void *) frbuf > card->u.f.rxmb_last)			card->rxmb = card->u.f.rxmb_base;		/* The loop put in is temporary, that is why the break is		 * placed here. (?????)		 */		break;		frbuf = card->rxmb;	}	while (frbuf->flag && ((++rx_count) < 4));}/*============================================================================ * Transmit interrupt handler. * o print a warning * o  * If number of spurious interrupts exceeded some limit, then ??? */static void tx_intr(sdla_t * card){	struct device *dev = card->wandev.dev;	if (card->intr_mode == BUFFER_INTR_MODE) 	{		for (; dev; dev = dev->slave) 		{			if (!dev || !dev->start) 			{				++card->statistics.tx_intr_dev_not_started;				continue;			}			dev->tbusy = 0;			mark_bh(NET_BH);		}	}	else	{		dev->tbusy = 0;		mark_bh(NET_BH);	}}/*============================================================================ * Spurious interrupt handler. * o print a warning * o  * If number of spurious interrupts exceeded some limit, then ??? */static void spur_intr(sdla_t * card){	printk(KERN_INFO "%s: spurious interrupt!\n", card->devname);}/*   Return 0 for non-IPXWAN packet   1 for IPXWAN packet or IPX is not enabled! */static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number){	int i;

⌨️ 快捷键说明

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