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

📄 sdla_fr.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				"%s: ERROR on DLCI %i: Not configured properly !\n",					card->devname, chan->dlci);			printk(KERN_INFO "%s: Please contact Sangoma Technologies\n",					card->devname);		}		return 1;	}			dlci_interface = chan->dlci_int_interface;        if(chan->transmit_length) {                printk(KERN_INFO "%s: Big mess in setup_for_del...\n",				card->devname);                return 1;        }	if(len > FR_MAX_NO_DATA_BYTES_IN_FRAME) {		//FIXME: increment some statistic */		return 1;	}	skb_unlink(skb);	        chan->transmit_length = len;	chan->delay_skb = skb;                dlci_interface->gen_interrupt |= FR_INTR_TXRDY;        dlci_interface->packet_length = len;	/* Turn on TX interrupt at the end of if_send */	return 0;}/*============================================================================ * Check to see if the packet to be transmitted contains a broadcast or * multicast source IP address. * Return 0 if not broadcast/multicast address, otherwise return 1. */static int chk_bcast_mcast_addr(sdla_t *card, netdevice_t* dev,                                struct sk_buff *skb){        u32 src_ip_addr;        u32 broadcast_ip_addr = 0;#if defined(LINUX_2_1) || defined(LINUX_2_4)        struct in_device *in_dev;#endif        fr_channel_t* chan = dev->priv;         /* read the IP source address from the outgoing packet */        src_ip_addr = *(u32 *)(skb->data + 14);        /* read the IP broadcast address for the device */#if defined(LINUX_2_1) || defined(LINUX_2_4)        in_dev = dev->ip_ptr;        if(in_dev != NULL) {                struct in_ifaddr *ifa= in_dev->ifa_list;                if(ifa != NULL)                        broadcast_ip_addr = ifa->ifa_broadcast;                else                        return 0;        }#else        broadcast_ip_addr = dev->pa_brdaddr;#endif        /* check if the IP Source Address is a Broadcast address */        if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) {                printk(KERN_INFO                        "%s: Broadcast Source Address silently discarded\n",                        card->devname);                return 1;        }        /* check if the IP Source Address is a Multicast address */        if((chan->mc == WANOPT_NO) && (ntohl(src_ip_addr) >= 0xE0000001) &&                (ntohl(src_ip_addr) <= 0xFFFFFFFE)) {                printk(KERN_INFO                        "%s: Multicast Source Address silently discarded\n",                        card->devname);                return 1;        }        return 0;}/*============================================================================ * Reply to UDP Management system. * Return nothing. */static int reply_udp( unsigned char *data, unsigned int mbox_len ) {	unsigned short len, udp_length, temp, ip_length;	unsigned long ip_temp;	int even_bound = 0;  	fr_udp_pkt_t *fr_udp_pkt = (fr_udp_pkt_t *)data; 	/* Set length of packet */	len = //sizeof(fr_encap_hdr_t)+	      sizeof(ip_pkt_t)+ 	      sizeof(udp_pkt_t)+	      sizeof(wp_mgmt_t)+	      sizeof(cblock_t)+	      mbox_len; 	/* fill in UDP reply */	fr_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY;  	/* fill in UDP length */	udp_length = sizeof(udp_pkt_t)+ 		     sizeof(wp_mgmt_t)+		     sizeof(cblock_t)+		     mbox_len; 	/* put it on an even boundary */	if ( udp_length & 0x0001 ) {		udp_length += 1;		len += 1;		even_bound = 1;	}	temp = (udp_length<<8)|(udp_length>>8);	fr_udp_pkt->udp_pkt.udp_length = temp;	 	/* swap UDP ports */	temp = fr_udp_pkt->udp_pkt.udp_src_port;	fr_udp_pkt->udp_pkt.udp_src_port = 			fr_udp_pkt->udp_pkt.udp_dst_port; 	fr_udp_pkt->udp_pkt.udp_dst_port = temp;	/* add UDP pseudo header */	temp = 0x1100;	*((unsigned short *)		(fr_udp_pkt->data+mbox_len+even_bound)) = temp;		temp = (udp_length<<8)|(udp_length>>8);	*((unsigned short *)		(fr_udp_pkt->data+mbox_len+even_bound+2)) = temp;		 	/* calculate UDP checksum */	fr_udp_pkt->udp_pkt.udp_checksum = 0;	fr_udp_pkt->udp_pkt.udp_checksum = 		calc_checksum(&data[UDP_OFFSET/*+sizeof(fr_encap_hdr_t)*/],			      udp_length+UDP_OFFSET);	/* fill in IP length */	ip_length = udp_length + sizeof(ip_pkt_t);	temp = (ip_length<<8)|(ip_length>>8);	fr_udp_pkt->ip_pkt.total_length = temp;  	/* swap IP addresses */	ip_temp = fr_udp_pkt->ip_pkt.ip_src_address;	fr_udp_pkt->ip_pkt.ip_src_address = 				fr_udp_pkt->ip_pkt.ip_dst_address;	fr_udp_pkt->ip_pkt.ip_dst_address = ip_temp;		 	/* fill in IP checksum */	fr_udp_pkt->ip_pkt.hdr_checksum = 0;	fr_udp_pkt->ip_pkt.hdr_checksum = 		calc_checksum(&data[/*sizeof(fr_encap_hdr_t)*/0],		      	      sizeof(ip_pkt_t));	return len;} /* reply_udp */unsigned short calc_checksum (char *data, int len){	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. */#if defined(LINUX_2_1) || defined(LINUX_2_4)static struct net_device_stats *if_stats(netdevice_t *dev)#elsestatic struct enet_statistics* if_stats (netdevice_t* dev)#endif{	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 occured */			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;	netdevice_t* 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

⌨️ 快捷键说明

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