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

📄 sdla_x25.c

📁 MIZI Research, Inc.发布的嵌入式Linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	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;			wan_dev_kfree_skb(skb, FREE_READ);			return;		}				++chan->ifstats.rx_packets;#if defined(LINUX_2_1) || defined(LINUX_2_4)		chan->ifstats.rx_bytes += skb->len;#endif				chan->rx_skb = NULL;		if (!test_and_set_bit(0, &chan->tq_working)){			wanpipe_queue_tq(&chan->common.wanpipe_task);			wanpipe_mark_bh();		}		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 */                wan_dev_kfree_skb(skb, FREE_READ);		++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{		if( handle_IPXWAN(skb->data, chan->name, 				  chan->enable_IPX, chan->network_number, 				  skb->protocol)){			if( chan->enable_IPX ){				if(chan_send(dev, skb->data, skb->len,0)){					chan->tx_skb = skb;				}else{                                        wan_dev_kfree_skb(skb, FREE_WRITE);					++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;				}			}else{				/* increment IPX packet dropped statistic */				++chan->ifstats.rx_dropped;				++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack;			}		}else{			skb->mac.raw = skb->data;#if defined(LINUX_2_1) || defined(LINUX_2_4)			chan->ifstats.rx_bytes += skb->len;#endif			++chan->ifstats.rx_packets;			++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack;			netif_rx(skb);		}	}		return;}static int wanpipe_pull_data_in_skb (sdla_t *card, netdevice_t *dev, struct sk_buff **skb){	void *bufptr;	TX25Mbox* rxmb = card->rxmb;	unsigned len = rxmb->cmd.length;	/* packet length */	unsigned qdm = rxmb->cmd.qdm;		/* Q,D and M bits */	x25_channel_t *chan = dev->priv;	struct sk_buff *new_skb = *skb;	if (chan->common.usedby == WANPIPE){		if (chan->drop_sequence){			if (!(qdm & 0x01)){ 				chan->drop_sequence = 0;			}			return 1;		}		new_skb = chan->rx_skb;	}else{		/* Add on the API header to the received                 * data 		 */		len += sizeof(x25api_hdr_t);	}	if (new_skb == NULL){		int bufsize;		if (chan->common.usedby == WANPIPE){			bufsize = (qdm & 0x01) ? dev->mtu : len;		}else{			bufsize = len;		}		/* Allocate new socket buffer */		new_skb = dev_alloc_skb(bufsize + dev->hard_header_len);		if (new_skb == NULL){			printk(KERN_INFO "%s: no socket buffers available!\n",				card->devname);			chan->drop_sequence = 1;	/* set flag */			++chan->ifstats.rx_dropped;			return 1;		}	}	if (skb_tailroom(new_skb) < len){		/* No room for the packet. Call off the whole thing! */                wan_dev_kfree_skb(new_skb, FREE_READ);		if (chan->common.usedby == WANPIPE){			chan->rx_skb = NULL;			if (qdm & 0x01){ 				chan->drop_sequence = 1;			}		}		printk(KERN_INFO "%s: unexpectedly long packet sequence "			"on interface %s!\n", card->devname, dev->name);		++chan->ifstats.rx_length_errors;		return 1;	}	bufptr = skb_put(new_skb,len);	if (chan->common.usedby == API){		/* Fill in the x25api header 		 */		x25api_t * api_data = (x25api_t*)bufptr;		api_data->hdr.qdm = rxmb->cmd.qdm;		api_data->hdr.cause = rxmb->cmd.cause;		api_data->hdr.diagn = rxmb->cmd.diagn;		api_data->hdr.length = rxmb->cmd.length;		memcpy(api_data->data, rxmb->data, rxmb->cmd.length);	}else{		memcpy(bufptr, rxmb->data, len);	}	new_skb->dev = dev;	if (chan->common.usedby == API){		new_skb->mac.raw = new_skb->data;		new_skb->protocol = htons(X25_PROT);		new_skb->pkt_type = WAN_PACKET_DATA;	}else{		new_skb->protocol = chan->protocol;		chan->rx_skb = new_skb;	}	/* If qdm bit is set, more data is coming          * thus, exit and wait for more data before         * sending the packet up. (Used by router only) 	 */	if ((qdm & 0x01) && (chan->common.usedby == WANPIPE)) 		return 1;		*skb = new_skb; 	return 0;}/*=============================================================== * tx_intr *   * 	Transmit interrupt handler. *	For each dev, check that there is something to send. *	If data available, transmit. 	 * *===============================================================*/static void tx_intr (sdla_t* card){	netdevice_t *dev;	TX25Status* status = card->flags;	unsigned char more_to_tx=0;	x25_channel_t *chan=NULL;	int i=0;		if (card->u.x.tx_dev == NULL){		card->u.x.tx_dev = card->wandev.dev;	}	dev = card->u.x.tx_dev;	for (;;){		chan = dev->priv;		if (chan->transmit_length){			/* Device was set to transmit, check if the TX                         * buffers are available 			 */					if (chan->common.state != WAN_CONNECTED){				chan->transmit_length = 0;				atomic_set(&chan->common.driver_busy,0);				chan->tx_offset=0;				if (is_queue_stopped(dev)){					if (chan->common.usedby == API){						start_net_queue(dev);						wakeup_sk_bh(dev);					}else{						wake_net_dev(dev);					}				}				dev = move_dev_to_next(card,dev);				break;			}							if ((status->cflags[chan->ch_idx] & 0x40 || card->u.x.LAPB_hdlc) && 			     (*card->u.x.hdlc_buf_status & 0x40) ){				/* Tx buffer available, we can send */								if (tx_intr_send(card, dev)){					more_to_tx=1;				}				/* If more than one interface present, move the                                 * device pointer to the next interface, so on the                                  * next TX interrupt we will try sending from it.                                  */				dev = move_dev_to_next(card,dev);				break;			}else{				/* Tx buffers not available, but device set                                 * the TX interrupt.  Set more_to_tx and try                                   * to transmit for other devices.				 */				more_to_tx=1;				dev = move_dev_to_next(card,dev);			}		}else{			/* This device was not set to transmit,                         * go to next 			 */			dev = move_dev_to_next(card,dev);		}			if (++i == card->u.x.no_dev){			if (!more_to_tx){				DBG_PRINTK(KERN_INFO "%s: Nothing to Send in TX INTR\n",					card->devname);			}			break;		}	} //End of FOR	card->u.x.tx_dev = dev;		if (!more_to_tx){		/* if any other interfaces have transmit interrupts pending, */		/* do not disable the global transmit interrupt */		if (!(--card->u.x.tx_interrupts_pending)){			status->imask &= ~INTR_ON_TX_FRAME;		}	}	return;}/*=============================================================== * move_dev_to_next *   * *===============================================================*/netdevice_t * move_dev_to_next (sdla_t *card, netdevice_t *dev){	if (card->u.x.no_dev != 1){		if (*((netdevice_t**)dev->priv) == NULL){			return card->wandev.dev;		}else{			return *((netdevice_t**)dev->priv);		}	}	return dev;}/*=============================================================== *  tx_intr_send *   * *===============================================================*/static int tx_intr_send(sdla_t *card, netdevice_t *dev){	x25_channel_t* chan = dev->priv; 	if (chan_send (dev,chan->transmit_buffer,chan->transmit_length,1)){		                 /* Packet was split up due to its size, do not disable                 * tx_intr                  */		return 1;	}	chan->transmit_length=0;	atomic_set(&chan->common.driver_busy,0);	chan->tx_offset=0;	/* If we are in API mode, wakeup the          * sock BH handler, not the NET_BH */	if (is_queue_stopped(dev)){		if (chan->common.usedby == API){			start_net_queue(dev);			wakeup_sk_bh(dev);		}else{			wake_net_dev(dev);		}	}	return 0;}/*=============================================================== * timer_intr *   * 	Timer interrupt handler. *	Check who called the timer interrupt and perform *      action accordingly. * *===============================================================*/static void timer_intr (sdla_t *card){	TX25Status* status = card->flags;	if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC){		if (timer_intr_cmd_exec(card) == 0){			card->u.x.timer_int_enabled &=				~TMR_INT_ENABLED_CMD_EXEC;		}	}else  if(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UDP_PKT) {		if ((*card->u.x.hdlc_buf_status & 0x40) && 		    card->u.x.udp_type == UDP_XPIPE_TYPE){                    	if(process_udp_mgmt_pkt(card)) {		                card->u.x.timer_int_enabled &= 					~TMR_INT_ENABLED_UDP_PKT;			}		}	}else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_ACTIVE) {		netdevice_t *dev = card->u.x.poll_device;		x25_channel_t *chan = NULL;		if (!dev){			card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE;			return;		}		chan = dev->priv;		printk(KERN_INFO 			"%s: Closing down Idle link %s on LCN %d\n",					card->devname,chan->name,chan->common.lcn); 		chan->i_timeout_sofar = jiffies;		chan_disc(dev);	         	card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE;		card->u.x.poll_device=NULL;	}else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_ON) {		wanpipe_set_state(card, WAN_CONNECTED);		if (card->u.x.LAPB_hdlc){			netdevice_t *dev = card->wandev.dev;			set_chan_state(dev,WAN_CONNECTED);			send_delayed_cmd_result(card,dev,card->mbox);			}		/* 0x8F enable all interrupts */		x25_set_intr_mode(card, INTR_ON_RX_FRAME|						INTR_ON_TX_FRAME|					INTR_ON_MODEM_STATUS_CHANGE|					//INTR_ON_COMMAND_COMPLETE|					X25_ASY_TRANS_INTR_PENDING |					INTR_ON_TIMER |					DIRECT_RX_INTR_USAGE				); 		status->imask &= ~INTR_ON_TX_FRAME;	/* mask Tx interrupts */		card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_ON;	}else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_OFF) {		//printk(KERN_INFO "Poll connect, Turning OFF\n");		disconnect(card);		card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_OFF;	}else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_DISCONNECT) {		//printk(KERN_INFO "POll disconnect, trying to connect\n");		connect(card);		card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_DISCONNECT;	}else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE){		if (*card->u.x.hdlc_buf_status & 0x40){			x25_get_err_stats(card);			x25_get_stats(card);			card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE;		}	}	if(!card->u.x.timer_int_enabled){		//printk(KERN_INFO "Turning Timer Off \n");                status->imask &= ~INTR_ON_TIMER;		}}/*==================================================================== * 	Modem status interrupt handler. *===================================================================*/static void status_intr (sdla_t* card){	/* Added to avoid Modem status message flooding */	static TX25ModemStatus last_stat;	TX25Mbox* mbox = card->mbox;	

⌨️ 快捷键说明

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