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

📄 sdla_x25.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/*====================================================================== * 	Build media header. * 	o encapsulate packet according to encapsulation type. * * 	The trick here is to put packet type (Ethertype) into 'protocol'  *      field of the socket buffer, so that we don't forget it.   *      If encapsulation fails, set skb->protocol to 0 and discard  *      packet later. * * 	Return:		media header length. *======================================================================*/static int if_header(struct sk_buff* skb, struct net_device* dev,		     unsigned short type, void* daddr, void* saddr,		     unsigned len){	x25_channel_t* chan = dev->priv;	int hdr_len = dev->hard_header_len;		skb->protocol = htons(type);	if (!chan->protocol){		hdr_len = wanrouter_encapsulate(skb, dev, type);		if (hdr_len < 0){			hdr_len = 0;			skb->protocol = htons(0);		}	}	return hdr_len;}/*=============================================================== * 	Re-build media header. * * 	Return:		1	physical address resolved. *			0	physical address not resolved *==============================================================*/static int if_rebuild_hdr (struct sk_buff* skb){	struct net_device *dev = skb->dev; 	x25_channel_t* chan = dev->priv;	sdla_t* card = chan->card;	printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n",		card->devname, dev->name);	return 1;}/*============================================================================ * Handle transmit timeout event from netif watchdog */static void if_tx_timeout(struct net_device *dev){    	x25_channel_t* chan = dev->priv;	sdla_t *card = chan->card;	/* If our device stays busy for at least 5 seconds then we will	 * kick start the device by making dev->tbusy = 0.  We expect	 * that our device never stays busy more than 5 seconds. So this                 	 * is only used as a last resort.	 */	++chan->if_send_stat.if_send_tbusy_timeout;	printk (KERN_INFO "%s: Transmit timed out on %s\n", 			card->devname, dev->name);	netif_wake_queue (dev);}/*========================================================================= * 	Send a packet on a network interface. * 	o set tbusy flag (marks start of the transmission). * 	o check link state. If link is not up, then drop the packet. * 	o check channel status. If it's down then initiate a call. * 	o pass a packet to corresponding WAN device. * 	o free socket buffer * * 	Return:	0	complete (socket buffer must be freed) *		non-0	packet may be re-transmitted (tbusy must be set) * * 	Notes: * 	1. This routine is called either by the protocol stack or by the "net *    	bottom half" (with interrupts enabled). * 	2. Setting tbusy flag will inhibit further transmit requests from the *    	protocol stack and can be used for flow control with protocol layer. * *========================================================================*/static int if_send(struct sk_buff* skb, struct net_device* dev){	x25_channel_t* chan = dev->priv;	sdla_t* card = chan->card;	TX25Status* status = card->flags;	int udp_type;	unsigned long smp_flags=0;	++chan->if_send_stat.if_send_entry;	netif_stop_queue(dev);	/* No need to check frame length, since socket code         * will perform the check for us */	chan->tick_counter = jiffies;		/* Critical region starts here */	S508_S514_lock(card, &smp_flags);		if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){		printk(KERN_INFO "Hit critical in if_send()! %lx\n",card->wandev.critical);		goto if_send_crit_exit;	}		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, dev, skb,                        chan->common.lcn)) {                        status->imask |= INTR_ON_TIMER;                        if (udp_type == UDP_XPIPE_TYPE){                                chan->if_send_stat.if_send_PIPE_request++;			}               	}		netif_start_queue(dev);		clear_bit(SEND_CRIT,(void*)&card->wandev.critical);		S508_S514_unlock(card, &smp_flags);		return 0;	}	if (chan->transmit_length){		//FIXME: This check doesn't make sense any more		if (chan->common.state != WAN_CONNECTED){			chan->transmit_length=0;			atomic_set(&chan->common.driver_busy,0);		}else{			netif_stop_queue(dev);			++card->u.x.tx_interrupts_pending;		        status->imask |= INTR_ON_TX_FRAME;			clear_bit(SEND_CRIT,(void*)&card->wandev.critical);			S508_S514_unlock(card, &smp_flags);			return 1;		}	}	if (card->wandev.state != WAN_CONNECTED){		++chan->ifstats.tx_dropped;		++card->wandev.stats.tx_dropped;		++chan->if_send_stat.if_send_wan_disconnected;				}else if ( chan->protocol && (chan->protocol != skb->protocol)){		printk(KERN_INFO			"%s: unsupported Ethertype 0x%04X on interface %s!\n",			chan->name, htons(skb->protocol), dev->name);				printk(KERN_INFO "PROTO %Xn", htons(chan->protocol));		++chan->ifstats.tx_errors;		++chan->ifstats.tx_dropped;		++card->wandev.stats.tx_dropped;		++chan->if_send_stat.if_send_protocol_error;			}else switch (chan->common.state){		case WAN_DISCONNECTED:			/* Try to establish connection. If succeded, then start			 * transmission, else drop a packet.			 */			if (chan->common.usedby == API){				++chan->ifstats.tx_dropped;				++card->wandev.stats.tx_dropped;				break;			}else{				if (chan_connect(dev) != 0){					++chan->ifstats.tx_dropped;					++card->wandev.stats.tx_dropped;					break;				}			}			/* fall through */		case WAN_CONNECTED:			if( skb->protocol == htons(ETH_P_IPX)) {				if(chan->enable_IPX) {					switch_net_numbers( skb->data, 						chan->network_number, 0);				} else {					++card->wandev.stats.tx_dropped;					++chan->ifstats.tx_dropped;					++chan->if_send_stat.if_send_protocol_error;					goto if_send_crit_exit;				}			}			/* We never drop here, if cannot send than, copy	                 * a packet into a transmit buffer                          */			chan_send(dev, skb->data, skb->len, 0);			break;		default:			++chan->ifstats.tx_dropped;				++card->wandev.stats.tx_dropped;			break;	}if_send_crit_exit:	       	dev_kfree_skb_any(skb);	netif_start_queue(dev);	clear_bit(SEND_CRIT,(void*)&card->wandev.critical);	S508_S514_unlock(card, &smp_flags);	return 0;}/*============================================================================ * Setup so that a frame can be transmitted on the occurrence of a transmit * interrupt. *===========================================================================*/static void setup_for_delayed_transmit(struct net_device* dev, void* buf,				       unsigned len){        x25_channel_t* chan = dev->priv;        sdla_t* card = chan->card;	TX25Status* status = card->flags;	++chan->if_send_stat.if_send_adptr_bfrs_full;        if(chan->transmit_length) {                printk(KERN_INFO "%s: Error, transmit length set in delayed transmit!\n",				card->devname);                return;        }	if (chan->common.usedby == API){		if (len > X25_CHAN_MTU+sizeof(x25api_hdr_t)) {			++chan->ifstats.tx_dropped;				++card->wandev.stats.tx_dropped;			printk(KERN_INFO "%s: Length is too big for delayed transmit\n",				card->devname);			return;		}	}else{		if (len > X25_MAX_DATA) {			++chan->ifstats.tx_dropped;				++card->wandev.stats.tx_dropped;			printk(KERN_INFO "%s: Length is too big for delayed transmit\n",				card->devname);			return;		}	}        chan->transmit_length = len;	atomic_set(&chan->common.driver_busy,1);        memcpy(chan->transmit_buffer, buf, len);	++chan->if_send_stat.if_send_tx_int_enabled;	/* Enable Transmit Interrupt */	++card->u.x.tx_interrupts_pending;        status->imask |= INTR_ON_TX_FRAME;}/*=============================================================== * net_device_stats * * 	Get ethernet-style interface statistics. * 	Return a pointer to struct enet_statistics. * *==============================================================*/static struct net_device_stats *if_stats(struct net_device* dev){	x25_channel_t *chan = dev->priv;	if(chan == NULL)		return NULL;	return &chan->ifstats;}/* *	Interrupt Handlers  *//* * X.25 Interrupt Service Routine. */static void wpx_isr (sdla_t* card){	TX25Status* status = card->flags;	card->in_isr = 1;	++card->statistics.isr_entry;	if (test_bit(PERI_CRIT,(void*)&card->wandev.critical)){		card->in_isr=0;		status->iflags = 0;		return;	}		if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)){ 		printk(KERN_INFO "%s: wpx_isr: wandev.critical set to 0x%02lx, int type = 0x%02x\n", 			card->devname, card->wandev.critical, status->iflags);		card->in_isr = 0;		status->iflags = 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)         */	switch (status->iflags){		case RX_INTR_PENDING:		/* receive interrupt */			rx_intr(card);			break;		case TX_INTR_PENDING:		/* transmit interrupt */			tx_intr(card);			break;		case MODEM_INTR_PENDING:	/* modem status interrupt */			status_intr(card);			break;		case X25_ASY_TRANS_INTR_PENDING:	/* network event interrupt */			event_intr(card);			break;		case TIMER_INTR_PENDING:			timer_intr(card);			break;		default:		/* unwanted interrupt */			spur_intr(card);	}	card->in_isr = 0;	status->iflags = 0;	/* clear interrupt condition */}/* * 	Receive interrupt handler. * 	This routine handles fragmented IP packets using M-bit according to the * 	RFC1356. * 	o map ligical channel number to network interface. * 	o allocate socket buffer or append received packet to the existing one. * 	o if M-bit is reset (i.e. it's the last packet in a sequence) then  *   	decapsulate packet and pass socket buffer to the protocol stack. * * 	Notes: * 	1. When allocating a socket buffer, if M-bit is set then more data is *    	coming and we have to allocate buffer for the maximum IP packet size *    	expected on this channel. * 	2. If something goes wrong and X.25 packet has to be dropped (e.g. no *    	socket buffers available) the whole packet sequence must be discarded. */static void rx_intr (sdla_t* card){	TX25Mbox* rxmb = card->rxmb;	unsigned lcn = rxmb->cmd.lcn;	struct net_device* dev = find_channel(card,lcn);	x25_channel_t* chan;	struct sk_buff* skb=NULL;	if (dev == NULL){		/* Invalid channel, discard packet */		printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",			card->devname, lcn);		return;	}	chan = dev->priv;	chan->i_timeout_sofar = jiffies;	/* Copy the data from the board, into an         * skb buffer 	 */	if (wanpipe_pull_data_in_skb(card,dev,&skb)){		++chan->ifstats.rx_dropped;		++card->wandev.stats.rx_dropped;		++chan->rx_intr_stat.rx_intr_no_socket;		++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;		return;	}	dev->last_rx = jiffies;		/* timestamp */	/* ------------ API ----------------*/	if (chan->common.usedby == API){		if (bh_enqueue(dev, skb)){			++chan->ifstats.rx_dropped;			++card->wandev.stats.rx_dropped;			++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;			dev_kfree_skb_any(skb);			return;		}				++chan->ifstats.rx_packets;		chan->ifstats.rx_bytes += skb->len;				chan->rx_skb = NULL;		if (!test_and_set_bit(0, &chan->tq_working)){			wanpipe_queue_work(&chan->common.wanpipe_work);		}		return;	}	/* ------------- WANPIPE -------------------*/		/* set rx_skb to NULL so we won't access it later when kernel already owns it */	chan->rx_skb=NULL;		/* Decapsulate packet, if necessary */	if (!skb->protocol && !wanrouter_type_trans(skb, dev)){		/* can't decapsulate packet */                dev_kfree_skb_any(skb);		++chan->ifstats.rx_errors;		++chan->ifstats.rx_dropped;		++card->wandev.stats.rx_dropped;		++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;	}else{

⌨️ 快捷键说明

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