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

📄 sdla_fr.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
{	unsigned short temp; 	unsigned long sum=0;	int i;	for( i = 0; i <len; i+=2 ) {		memcpy(&temp,&data[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;	return temp;	}/*   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 enet_statistics. */static struct net_device_stats *if_stats(struct net_device *dev){	fr_channel_t* chan = dev->priv;		if(chan == NULL)		return NULL;	return &chan->ifstats;}/****** Interrupt Handlers **************************************************//*============================================================================ * fr_isr:	S508 frame relay interrupt service routine. * * Description: *	Frame relay main interrupt service route. This *      function check the interrupt type and takes *      the appropriate action. */static void fr_isr (sdla_t* card){	fr508_flags_t* flags = card->flags;	char *ptr = &flags->iflag;	int i,err;	fr_mbox_t* mbox = card->mbox;	/* This flag prevents nesting of interrupts.  See sdla_isr() routine         * in sdlamain.c.  */	card->in_isr = 1;		++card->statistics.isr_entry;	/* All peripheral (configuraiton, re-configuration) events	 * take presidence over the ISR.  Thus, retrigger */	if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {		++card->statistics.isr_already_critical;		goto fr_isr_exit;	}	        if(card->hw.type != SDLA_S514) {		if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) {                        printk(KERN_INFO "%s: Critical while in ISR: If Send Running!\n",                                card->devname);			++card->statistics.isr_already_critical;			goto fr_isr_exit;		}	}	switch (flags->iflag) {                case FR_INTR_RXRDY:  /* receive interrupt */	    		++card->statistics.isr_rx;          		rx_intr(card);            		break;                case FR_INTR_TXRDY:  /* transmit interrupt */	    		++ card->statistics.isr_tx; 			tx_intr(card);             		break;                case FR_INTR_READY:  		    		Intr_test_counter++;			++card->statistics.isr_intr_test;	    		break;	                case FR_INTR_DLC: /* Event interrupt occurred */			mbox->cmd.command = FR_READ_STATUS;			mbox->cmd.length = 0;			err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;			if (err)				fr_event(card, err, mbox);			break;                case FR_INTR_TIMER:  /* Timer interrupt */			timer_intr(card);			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;    	}fr_isr_exit:		card->in_isr = 0;	flags->iflag = 0;	return;}/*=========================================================== * rx_intr	Receive interrupt handler. * * Description * 	Upon receiveing an interrupt:  *	1. Check that the firmware is in sync with  *     	   the driver.  *      2. Find an appropriate network interface *         based on the received dlci number. *	3. Check that the netowrk interface exists *         and that it's setup properly. *	4. Copy the data into an skb buffer. *	5. Check the packet type and take *         appropriate acton: UPD, API, ARP or Data. */static void rx_intr (sdla_t* card){	fr_rx_buf_ctl_t* frbuf = card->rxmb;	fr508_flags_t* flags = card->flags;	fr_channel_t* chan;	char *ptr = &flags->iflag;	struct sk_buff* skb;	struct net_device* dev;	void* buf;	unsigned dlci, len, offs, len_incl_hdr;	int i, udp_type;		/* Check that firmware buffers are in sync */	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;		/* Bug Fix: Mar 6 2000                 * If we get a corrupted mailbox, it means that driver                  * is out of sync with the firmware. There is no recovery.                 * If we don't turn off all interrupts for this card                 * the machine will crash.                  */		printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);		printk(KERN_INFO "Please contact Sangoma Technologies !\n");		fr_set_intr_mode(card, 0, 0, 0);			return;	}	len  = frbuf->length;	dlci = frbuf->dlci;	offs = frbuf->offset;	/* Find the network interface for this packet */	dev = find_channel(card, dlci);   	/* Check that the network interface is active and         * properly setup */	if (dev == NULL) {   		if( net_ratelimit()) { 			printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n",                                                card->devname, dlci);		}		++card->statistics.rx_intr_on_orphaned_DLCI; 		++card->wandev.stats.rx_dropped;		goto rx_done;	}	if ((chan = dev->priv) == NULL){		if( net_ratelimit()) { 			printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n",                                                card->devname, dlci);		}		++card->statistics.rx_intr_on_orphaned_DLCI; 		++card->wandev.stats.rx_dropped;		goto rx_done;	}	skb = dev_alloc_skb(len); 	if (!netif_running(dev) || (skb == NULL)){		++chan->ifstats.rx_dropped;			if(skb == NULL) {			if (net_ratelimit()) { 				printk(KERN_INFO 					"%s: no socket buffers available!\n", 						card->devname);			}			chan->drvstats_rx_intr.rx_intr_no_socket ++;		} 		if (!netif_running(dev)){			chan->drvstats_rx_intr.				rx_intr_dev_not_started ++;			if (skb){				dev_kfree_skb_any(skb);			}		}		goto rx_done;	}	/* Copy data from the board into 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);	/* We got the packet from the bard.          * Check the packet type and take appropriate action */	udp_type = udp_pkt_type( skb, card );	if(udp_type != UDP_INVALID_TYPE) {		/* UDP Debug packet received, store the		 * packet and handle it in timer interrupt */		skb_pull(skb, 1); 		if (wanrouter_type_trans(skb, dev)){ 			if(store_udp_mgmt_pkt(udp_type,UDP_PKT_FRM_NETWORK,card,skb,dlci)){				flags->imask |= FR_INTR_TIMER;				if (udp_type == UDP_FPIPE_TYPE){					++chan->drvstats_rx_intr.rx_intr_PIPE_request;				}			}		}	}else if (chan->common.usedby == API) {		/* We are in API mode.                  * Add an API header to the RAW packet                 * and queue it into a circular buffer.                 * Then kick the fr_bh() bottom half handler */		api_rx_hdr_t* api_rx_hdr;		chan->drvstats_rx_intr.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;		skb_push(skb, sizeof(api_rx_hdr_t));		api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00];		api_rx_hdr->attr = frbuf->attr;		api_rx_hdr->time_stamp = frbuf->tmstamp;		skb->protocol = htons(ETH_P_IP);		skb->mac.raw  = skb->data;		skb->dev      = dev;		skb->pkt_type = WAN_PACKET_DATA;		bh_enqueue(dev, skb);		trigger_fr_bh(chan);	}else if (handle_IPXWAN(skb->data,chan->name,chan->enable_IPX, chan->network_number)){		//FIXME: Frame Relay IPX is not supported, Yet !		//if (chan->enable_IPX) {		//	fr_send(card, dlci, 0, skb->len,skb->data);		//}		dev_kfree_skb_any(skb);	} else if (is_arp(skb->data)) {		/* ARP support enabled Mar 16 2000 		 * Process incoming ARP reply/request, setup		 * dynamic routes. */ 		if (process_ARP((arphdr_1490_t *)skb->data, card, dev)) {			if (net_ratelimit()){  				printk (KERN_INFO 				   "%s: Error processing ARP Packet.\n", 					card->devname);			}		}		dev_kfree_skb_any(skb);	} else if (skb->data[0] != 0x03) {		if (net_ratelimit()) { 			printk(KERN_INFO "%s: Non IETF packet discarded.\n", 				card->devname);		}		dev_kfree_skb_any(skb);	} else {		len_incl_hdr = skb->len;		/* Decapsulate packet and pass it up the		   protocol stack */		skb->dev = dev;				if (chan->common.usedby == BRIDGE || chan->common.usedby == BRIDGE_NODE){					/* Make sure it's an Ethernet frame, otherwise drop it */			if (!memcmp(skb->data, "\x03\x00\x80\x00\x80\xC2\x00\x07", 8)) {				skb_pull(skb, 8);				skb->protocol=eth_type_trans(skb,dev);			}else{				++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack;				++chan->ifstats.rx_errors;				++card->wandev.stats.rx_errors;				goto rx_done;			}		}else{					/* remove hardware header */			buf = skb_pull(skb, 1); 						if (!wanrouter_type_trans(skb, dev)) {								/* can't decapsulate packet */				dev_kfree_skb_any(skb);				++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack;				++chan->ifstats.rx_errors;				++card->wandev.stats.rx_errors;				goto rx_done;				}			skb->mac.raw = skb->data;		} 				/* Send a packet up the IP stack */		skb->dev->last_rx = jiffies;		netif_rx(skb);		++chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack;		

⌨️ 快捷键说明

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