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

📄 sdla_fr.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
				switch(err) {				case FRRES_CIR_OVERFLOW:				case FRRES_BUFFER_OVERFLOW:                			setup_for_delayed_transmit(dev, data,						len);           				chan->drvstats_if_send.						if_send_adptr_bfrs_full ++;					break;					default:					chan->drvstats_if_send.						if_send_dlci_disconnected ++;        				++chan->ifstats.tx_dropped;        				++card->wandev.stats.tx_dropped;					break;				}			} else {				chan->drvstats_if_send.					if_send_bfr_passed_to_adptr++;				++chan->ifstats.tx_packets;				++card->wandev.stats.tx_packets;                                chan->ifstats.tx_bytes += len;                                card->wandev.stats.tx_bytes += len;			}		}	}        if (!netif_queue_stopped(dev))		dev_kfree_skb(skb);        clear_bit(0, (void*)&card->wandev.critical);	s508_s514_unlock(card,&smp_flags);        return (netif_queue_stopped(dev));}/*============================================================================ * Setup so that a frame can be transmitted on the occurence of a transmit * interrupt. */static void setup_for_delayed_transmit (struct net_device* dev, void* buf,	unsigned len){        fr_channel_t* chan = dev->priv;        sdla_t* card = chan->card;        fr508_flags_t* adptr_flags = card->flags;        fr_dlci_interface_t* dlci_interface = chan->dlci_int_interface;        if(chan->transmit_length) {                printk(KERN_INFO "%s: Big mess in setup_for_del...\n",				card->devname);                return;        }	if(len > FR_MAX_NO_DATA_BYTES_IN_FRAME) {		//FIXME: increment some statistic */		return;	}        chan->transmit_length = len;        memcpy(chan->transmit_buffer, buf, len);        dlci_interface->gen_interrupt |= FR_INTR_TXRDY;        dlci_interface->packet_length = len;        adptr_flags->imask |= FR_INTR_TXRDY;	card->u.f.tx_interrupts_pending ++;}/*============================================================================ * 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, struct net_device* dev,                                struct sk_buff *skb){        u32 src_ip_addr;        u32 broadcast_ip_addr = 0;        struct in_device *in_dev;        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 */        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;        }        /* 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);                dev_kfree_skb(skb);                ++ chan->ifstats.tx_dropped;                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);                dev_kfree_skb(skb);                ++ chan->ifstats.tx_dropped;                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)],		      	      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 net_device_stats. */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 **************************************************//*============================================================================ * S508 frame relay interrupt service routine. */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;	if(test_bit(1, (void*)&card->wandev.critical)) {		card->wandev.critical = 0;		flags->iflag = 0;		card->in_isr = 0;		return;	}        if(card->hw.type != SDLA_S514) {		if (test_and_set_bit(0, (void*)&card->wandev.critical)) {                        printk(KERN_INFO "%s: Critical while in ISR (0x%02X)\n",                                card->devname, card->wandev.critical);			++card->statistics.isr_already_critical;			card->in_isr = 0;			return;		}	}	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;    	}	card->in_isr = 0;	flags->iflag = 0;        if(card->hw.type != SDLA_S514)                clear_bit(0, (void*)&card->wandev.critical);}/*============================================================================ * Receive interrupt handler. * When a receive interrupt occurs do the following: *	1- Find the structure for the dlci that the interrupt occured on *      2- If it doesn't exist then print appropriate msg and goto step 8.  * 	3- If it exist then copy data to a skb. * 	4- If skb contains Sangoma UDP data then process them *	5- If skb contains IPXWAN data then send IPXWAN reply packets *	6- If skb contains Inverse Arp data then send Inv Arp replies *	7- If skb contains any other data then decapsulate the packet and *	   send it to the stack. * 	8- Release the receive element and update receive pointers on the board  */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;		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;	}	len  = frbuf->length;	dlci = frbuf->dlci;

⌨️ 快捷键说明

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