chan->fr_header_len = setup_fr_header(&skb,dev,chan->common.usedby); 
chan->fr_header_len = setup_fr_header(skb,dev,chan->common.usedby); 
static int if_send(struct sk_buff* skb, struct net_device* dev){    	fr_channel_t* chan = dev->priv;    	sdla_t* card = chan->card;        int err;    	unsigned char *sendpacket;    	fr508_flags_t* adptr_flags = card->flags;	int udp_type;	long delay_tx_queued = 0;	unsigned long smp_flags=0;	unsigned char attr = 0;	chan->drvstats_if_send.if_send_entry++;	netif_stop_queue(dev);	        if (skb == NULL) {             		/* if we get here, some higher layer thinks we've missed an		 * tx-done interrupt.		 */		printk(KERN_INFO "%s: interface %s got kicked!\n", 			card->devname, dev->name);		chan->drvstats_if_send.if_send_skb_null ++;		netif_wake_queue(dev);		return 0;	}	/* If a peripheral task is running just drop packets */	if (test_bit(PERI_CRIT, &card->wandev.critical)){				printk(KERN_INFO "%s: Critical in if_send(): Peripheral running!\n",				card->devname);				dev_kfree_skb_any(skb);		netif_start_queue(dev);		return 0;	}	/* We must set the 'tbusy' flag if we already have a packet queued for	   transmission in the transmit interrupt handler. However, we must	   ensure that the transmit interrupt does not reset the 'tbusy' flag	   just before we set it, as this will result in a "transmit timeout".	*/	set_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);        if(chan->transmit_length) {		netif_stop_queue(dev);		chan->tick_counter = jiffies; 		clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical);		return 1;	}       	clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); 	/* Move the if_header() code to here. By inserting frame	 * relay header in if_header() we would break the	 * tcpdump and other packet sniffers */	chan->fr_header_len = setup_fr_header(&skb,dev,chan->common.usedby);	if (chan->fr_header_len < 0 ){		++chan->ifstats.tx_dropped;		++card->wandev.stats.tx_dropped;				dev_kfree_skb_any(skb);		netif_start_queue(dev);			return 0;	}	sendpacket = skb->data;	udp_type = udp_pkt_type(skb, card);        if(udp_type != UDP_INVALID_TYPE) {		if(store_udp_mgmt_pkt(udp_type, UDP_PKT_FRM_STACK, card, skb,                        chan->dlci)) {                        adptr_flags->imask |= FR_INTR_TIMER;                        if (udp_type == UDP_FPIPE_TYPE){                                chan->drvstats_if_send.					if_send_PIPE_request ++;			}                }		netif_start_queue(dev);		return 0;	}	//FIXME: can we do better than sendpacket[2]?  	if ((chan->common.usedby == WANPIPE) && (sendpacket[2] == 0x45)) {		               	/* check to see if the source IP address is a broadcast or */                /* multicast IP address */                if(chk_bcast_mcast_addr(card, dev, skb)){            		++chan->ifstats.tx_dropped;			++card->wandev.stats.tx_dropped;                	dev_kfree_skb_any(skb);			netif_start_queue(dev);			return 0;		}	}		/* Lock the S514/S508 card: SMP Supported */    	s508_s514_lock(card,&smp_flags);	if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) {				chan->drvstats_if_send.if_send_critical_non_ISR ++;		chan->ifstats.tx_dropped ++;		printk(KERN_INFO "%s Critical in IF_SEND: if_send() already running!\n", 				card->devname);		goto if_send_start_and_exit;	}		/* API packet check: minimum packet size must be greater than 	 * 16 byte API header */	if((chan->common.usedby == API) && (skb->len <= sizeof(api_tx_hdr_t))) {		++chan->ifstats.tx_dropped;		++card->wandev.stats.tx_dropped;	    				goto if_send_start_and_exit; 	}else{		/* During API transmission, get rid of the API header */		if (chan->common.usedby == API) {			api_tx_hdr_t* api_tx_hdr;			api_tx_hdr = (api_tx_hdr_t*)&skb->data[0x00];			attr = api_tx_hdr->attr;			skb_pull(skb,sizeof(api_tx_hdr_t));		}	}	if (card->wandev.state != WAN_CONNECTED) {		chan->drvstats_if_send.if_send_wan_disconnected ++;		++chan->ifstats.tx_dropped;        	++card->wandev.stats.tx_dropped;		} else if (chan->common.state != WAN_CONNECTED) {		chan->drvstats_if_send.if_send_dlci_disconnected ++;		/* Update the DLCI state in timer interrupt */		card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UPDATE_STATE;			adptr_flags->imask |= FR_INTR_TIMER;        	++chan->ifstats.tx_dropped;        	++card->wandev.stats.tx_dropped;			} else if (!is_tx_ready(card, chan)) {		/* No tx buffers available, store for delayed transmit */		if (!setup_for_delayed_transmit(dev, skb)){			set_bit(1,&delay_tx_queued);		}		chan->drvstats_if_send.if_send_no_bfrs++;			} else if (!skb->protocol) {		/* No protocols drop packet */		chan->drvstats_if_send.if_send_protocol_error ++;		++card->wandev.stats.tx_errors;		} else if (test_bit(ARP_CRIT,&card->wandev.critical)){		/* We are trying to send an ARP Packet, block IP data until		 * ARP is sent */		++chan->ifstats.tx_dropped;        	++card->wandev.stats.tx_dropped;			} else {		//FIXME: IPX is not implemented in this version of Frame Relay ?		if((chan->common.usedby == WANPIPE) &&		 	sendpacket[1] == 0x00 &&		    	sendpacket[2] == 0x80 &&		    	sendpacket[6] == 0x81 &&		    	sendpacket[7] == 0x37) {						if( chan->enable_IPX ) {				switch_net_numbers(sendpacket, 						chan->network_number, 0);			} else {				//FIXME: Take this out when IPX is fixed 				printk(KERN_INFO 				"%s: WARNING: Unsupported IPX data in send, packet dropped\n",					card->devname);			}					}else{        		err = fr_send_data_header(card, chan->dlci, attr, skb->len, skb->data, chan->fr_header_len);			if (err) {				switch(err) {				case FRRES_CIR_OVERFLOW:				case FRRES_BUFFER_OVERFLOW:                			if (!setup_for_delayed_transmit(dev, skb)){						set_bit(1,&delay_tx_queued);					}           				chan->drvstats_if_send.						if_send_adptr_bfrs_full ++;					break;									case FRRES_TOO_LONG:					if (net_ratelimit()){						printk(KERN_INFO 						"%s: Error: Frame too long, transmission failed %i\n",						 card->devname, (unsigned int)skb->len);					}					/* Drop down to default */				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 += skb->len;                                card->wandev.stats.tx_bytes += skb->len;				dev->trans_start = jiffies;			}		}	}if_send_start_and_exit:	netif_start_queue(dev);		/* If we queued the packet for transmission, we must not	 * deallocate it. The packet is unlinked from the IP stack	 * not copied. Therefore, we must keep the original packet */	if (!test_bit(1,&delay_tx_queued)) {                dev_kfree_skb_any(skb);	}else{		adptr_flags->imask |= FR_INTR_TXRDY;		card->u.f.tx_interrupts_pending ++;	}        clear_bit(SEND_CRIT, (void*)&card->wandev.critical);	s508_s514_unlock(card,&smp_flags);	return 0;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/8728b834b226ffcf2c94a58530090e292af2a7bf/sdla_fr.c/buggy/drivers/net/wan/sdla_fr.c