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

📄 sdla_x25.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		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{                                        dev_kfree_skb_any(skb);					++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;			chan->ifstats.rx_bytes += skb->len;			++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, struct net_device *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! */                dev_kfree_skb_any(new_skb);		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){	struct net_device *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 (netif_queue_stopped(dev)){					if (chan->common.usedby == API){						netif_start_queue(dev);						wakeup_sk_bh(dev);					}else{						netif_wake_queue(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 *   * *===============================================================*/struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev){	if (card->u.x.no_dev != 1){		if (!*((struct net_device **)dev->priv))			return card->wandev.dev;		else			return *((struct net_device **)dev->priv);	}	return dev;}/*=============================================================== *  tx_intr_send *   * *===============================================================*/static int tx_intr_send(sdla_t *card, struct net_device *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 (netif_queue_stopped(dev)){		if (chan->common.usedby == API){			netif_start_queue(dev);			wakeup_sk_bh(dev);		}else{			netif_wake_queue(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) {		struct net_device *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){			struct net_device *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;	TX25ModemStatus *modem_status;	struct net_device *dev;	x25_channel_t *chan;	int err;	memset(&mbox->cmd, 0, sizeof(TX25Cmd));	mbox->cmd.command = X25_READ_MODEM_STATUS;	err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT;	if (err){ 		x25_error(card, err, X25_READ_MODEM_STATUS, 0);	}else{			modem_status = (TX25ModemStatus*)mbox->data;		           	/* Check if the last status was the same           	 * if it was, do NOT print message again */			if (last_stat.status != modem_status->status){	     		printk(KERN_INFO "%s: Modem Status Change: DCD=%s, CTS=%s\n",				card->devname,DCD(modem_status->status),CTS(modem_status->status));			last_stat.status = modem_status->status;					if (card->u.x.oob_on_modem){				mbox->cmd.pktType = mbox->cmd.command;				mbox->cmd.result = 0x08;				/* Send a OOB to all connected sockets */				for (dev = card->wandev.dev; dev;				     dev = *((struct net_device**)dev->priv)) {					chan=dev->priv;					if (chan->common.usedby == API){						send_oob_msg(card,dev,mbox);									}				}				/* The modem OOB message will probably kill the				 * the link. If we don't clear the flag here,				 * a deadlock could occur */ 				if (atomic_read(&card->u.x.command_busy)){					atomic_set(&card->u.x.command_busy,0);		

⌨️ 快捷键说明

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