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

📄 wanpipe_multppp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
static void rx_intr (sdla_t* card){	struct net_device *dev;	chdlc_private_area_t *chdlc_priv_area;	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;	CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb;	struct sk_buff *skb;	unsigned len;	unsigned addr = rxbuf->ptr_data_bfr;	void *buf;	int i,udp_type;		if (rxbuf->opp_flag != 0x01) {		printk(KERN_INFO 			"%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", 			card->devname, (unsigned)rxbuf, rxbuf->opp_flag);                printk(KERN_INFO "Code name: ");                for(i = 0; i < 4; i ++)                        printk(KERN_INFO "%c",                                flags->global_info_struct.codename[i]);                printk(KERN_INFO "\nCode version: ");                for(i = 0; i < 4; i ++)                        printk(KERN_INFO "%c",                                flags->global_info_struct.codeversion[i]);                printk(KERN_INFO "\n");		/* Bug Fix: Mar 6 2000                 * If we get a corrupted mailbox, it measn that driver                  * is out of sync with the firmware. There is no recovery.                 * If we don't turn off all interrupts for this card                 * the machine will crash.                  */		printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname);		printk(KERN_INFO "Please contact Sangoma Technologies !\n");		chdlc_set_intr_mode(card,0);			return;	}	dev = card->wandev.dev;	if (!dev){ 		goto rx_exit;	}		if (!netif_running(dev)){		goto rx_exit;	}	chdlc_priv_area = dev->priv;	if (rxbuf->error_flag){			goto rx_exit;	}	/* Take off two CRC bytes */	if (rxbuf->frame_length < 7 || rxbuf->frame_length > 1506 ){		goto rx_exit;	}		len = rxbuf->frame_length - CRC_LENGTH;	/* Allocate socket buffer */	skb = dev_alloc_skb(len);	if (skb == NULL) {		if (net_ratelimit()){			printk(KERN_INFO "%s: no socket buffers available!\n",						card->devname);		}		++card->wandev.stats.rx_dropped;		goto rx_exit;	}	/* Copy data to the socket buffer */	if((addr + len) > card->u.c.rx_top + 1) {		unsigned tmp = card->u.c.rx_top - addr + 1;		buf = skb_put(skb, tmp);		sdla_peek(&card->hw, addr, buf, tmp);		addr = card->u.c.rx_base;		len -= tmp;	}			buf = skb_put(skb, len);	sdla_peek(&card->hw, addr, buf, len);	skb->protocol = htons(ETH_P_WAN_PPP);	card->wandev.stats.rx_packets ++;	card->wandev.stats.rx_bytes += skb->len;	udp_type = udp_pkt_type( skb, card );	if(udp_type == UDP_CPIPE_TYPE) {		if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK,   				      card, skb, dev, chdlc_priv_area)) {     		        flags->interrupt_info_struct.						interrupt_permission |= 							APP_INT_ON_TIMER; 		}	}else{               	/* Pass it up the protocol stack */                skb->dev = dev;                skb->mac.raw  = skb->data;                netif_rx(skb);                dev->last_rx = jiffies;	}rx_exit:	/* Release buffer element and calculate a pointer to the next one */	rxbuf->opp_flag = 0x00;	card->u.c.rxmb = ++ rxbuf;	if((void*)rxbuf > card->u.c.rxbuf_last){		card->u.c.rxmb = card->u.c.rxbuf_base;	}}/*============================================================================ * Timer interrupt handler. * The timer interrupt is used for two purposes: *    1) Processing udp calls from 'cpipemon'. *    2) Reading board-level statistics for updating the proc file system. */void timer_intr(sdla_t *card){        struct net_device* dev;        chdlc_private_area_t* chdlc_priv_area = NULL;        SHARED_MEMORY_INFO_STRUCT* flags = NULL;        dev = card->wandev.dev;         chdlc_priv_area = dev->priv;	if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) {		if (!config_chdlc(card)){			chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG;		}	}		/* process a udp call if pending */       	if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) {               	process_udp_mgmt_pkt(card, dev,                       chdlc_priv_area);		chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP;        }		/* read the communications statistics if required */	if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) {		update_comms_stats(card, chdlc_priv_area);                if(!(-- chdlc_priv_area->update_comms_stats)) {			chdlc_priv_area->timer_int_enabled &= 				~TMR_INT_ENABLED_UPDATE;		}        }	/* only disable the timer interrupt if there are no udp or statistic */	/* updates pending */        if(!chdlc_priv_area->timer_int_enabled) {                flags = card->u.c.flags;                flags->interrupt_info_struct.interrupt_permission &=                        ~APP_INT_ON_TIMER;        }}/*------------------------------------------------------------------------------  Miscellaneous Functions	- set_chdlc_config() used to set configuration options on the board------------------------------------------------------------------------------*/static int set_chdlc_config(sdla_t* card){	CHDLC_CONFIGURATION_STRUCT cfg;	memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT));	if(card->wandev.clocking)		cfg.baud_rate = card->wandev.bps;	cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?		INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;	cfg.modem_config_options	= 0;	//API OPTIONS	cfg.CHDLC_API_options		= DISCARD_RX_ERROR_FRAMES;	cfg.modem_status_timer		= 100;	cfg.CHDLC_protocol_options	= HDLC_STREAMING_MODE;	cfg.percent_data_buffer_for_Tx  = 50;	cfg.CHDLC_statistics_options	= (CHDLC_TX_DATA_BYTE_COUNT_STAT |		CHDLC_RX_DATA_BYTE_COUNT_STAT);	cfg.max_CHDLC_data_field_length	= card->wandev.mtu;	cfg.transmit_keepalive_timer	= 0;	cfg.receive_keepalive_timer	= 0;	cfg.keepalive_error_tolerance	= 0;	cfg.SLARP_request_timer		= 0;	cfg.IP_address		= 0;	cfg.IP_netmask		= 0;		return chdlc_configure(card, &cfg);}/*============================================================================ * Process global exception condition */static int process_global_exception(sdla_t *card){	CHDLC_MAILBOX_STRUCT* mbox = card->mbox;	int err;	mbox->buffer_length = 0;	mbox->command = READ_GLOBAL_EXCEPTION_CONDITION;	err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT;	if(err != CMD_TIMEOUT ){			switch(mbox->return_code) {         	      	case EXCEP_MODEM_STATUS_CHANGE:			printk(KERN_INFO "%s: Modem status change\n",				card->devname);			switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) {				case (DCD_HIGH):					printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname);					break;				case (CTS_HIGH):                                        printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname);                                        break;                                case ((DCD_HIGH | CTS_HIGH)):                                        printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname);                                        break;				default:                                        printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname);                                        break;			}			if (!(mbox->data[0] & DCD_HIGH) || !(mbox->data[0] & DCD_HIGH)){				//printk(KERN_INFO "Sending TERM Request Manually !\n");				send_ppp_term_request(card->wandev.dev);			}				break;                case EXCEP_TRC_DISABLED:                        printk(KERN_INFO "%s: Line trace disabled\n",				card->devname);                        break;		case EXCEP_IRQ_TIMEOUT:			printk(KERN_INFO "%s: IRQ timeout occurred\n",				card->devname); 			break;                default:                        printk(KERN_INFO "%s: Global exception %x\n",				card->devname, mbox->return_code);                        break;                }	}	return 0;}/*============================================================================ * Process chdlc exception condition */static int process_chdlc_exception(sdla_t *card){	CHDLC_MAILBOX_STRUCT* mb = card->mbox;	int err;	mb->buffer_length = 0;	mb->command = READ_CHDLC_EXCEPTION_CONDITION;	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;	if(err != CMD_TIMEOUT) {			switch (err) {		case EXCEP_LINK_ACTIVE:			port_set_state(card, WAN_CONNECTED);			break;		case EXCEP_LINK_INACTIVE_MODEM:			port_set_state(card, WAN_DISCONNECTED);			break;		case EXCEP_LOOPBACK_CONDITION:			printk(KERN_INFO "%s: Loopback Condition Detected.\n",						card->devname);			break;		case NO_CHDLC_EXCEP_COND_TO_REPORT:			printk(KERN_INFO "%s: No exceptions reported.\n",						card->devname);			break;		default:			printk(KERN_INFO "%s: Exception Condition %x!\n",					card->devname,err);			break;		}	}	return 0;}/*============================================================================= * Store a UDP management packet for later processing. */static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,			      struct sk_buff *skb, struct net_device* dev,			      chdlc_private_area_t* chdlc_priv_area ){	int udp_pkt_stored = 0;	if(!chdlc_priv_area->udp_pkt_lgth &&	  (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) {        	chdlc_priv_area->udp_pkt_lgth = skb->len;		chdlc_priv_area->udp_pkt_src = udp_pkt_src;       		memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len);		chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP;		udp_pkt_stored = 1;	}	if(udp_pkt_src == UDP_PKT_FRM_STACK)		dev_kfree_skb_any(skb);	else                dev_kfree_skb_any(skb);		return(udp_pkt_stored);}/*============================================================================= * Process UDP management packet. */static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev,				chdlc_private_area_t* chdlc_priv_area ) {	unsigned char *buf;	unsigned int frames, len;	struct sk_buff *new_skb;	unsigned short buffer_length, real_len;	unsigned long data_ptr;	unsigned data_length;	int udp_mgmt_req_valid = 1;	CHDLC_MAILBOX_STRUCT *mb = card->mbox;	SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;	chdlc_udp_pkt_t *chdlc_udp_pkt;	struct timeval tv;	int err;	char ut_char;	chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data;	if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) {		switch(chdlc_udp_pkt->cblock.command) {			case READ_GLOBAL_STATISTICS:			case READ_MODEM_STATUS:  			case READ_CHDLC_LINK_STATUS:			case CPIPE_ROUTER_UP_TIME:			case READ_COMMS_ERROR_STATS:			case READ_CHDLC_OPERATIONAL_STATS:			/* These two commands are executed for			 * each request */			case READ_CHDLC_CONFIGURATION:			case READ_CHDLC_CODE_VERSION:				udp_mgmt_req_valid = 1;				break;			default:				udp_mgmt_req_valid = 0;				break;		} 	}	  	if(!udp_mgmt_req_valid) {		/* set length to 0 */		chdlc_udp_pkt->cblock.buffer_length = 0;    		/* set return code */		chdlc_udp_pkt->cblock.return_code = 0xCD;		if (net_ratelimit()){				printk(KERN_INFO 			"%s: Warning, Illegal UDP command attempted from network: %x\n",			card->devname,chdlc_udp_pkt->cblock.command);		}   	} else {	   	unsigned long trace_status_cfg_addr = 0;		TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct;		TRACE_STATUS_ELEMENT_STRUCT trace_element_struct;		switch(chdlc_udp_pkt->cblock.command) {		case CPIPE_ENABLE_TRACING:		     if (!chdlc_priv_area->TracingEnabled) {			/* OPERATE_DATALINE_MONITOR */			mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);			mb->command = SET_TRACE_CONFIGURATION;    			((LINE_TRACE_CONFIG_STRUCT *)mb->data)->				trace_config = TRACE_ACTIVE;			/* Trace delay mode is not used because it slows			   down transfer and results in a standoff situation			   when there is a lot of data */			/* Configure the Trace based on user inputs */			((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |= 					chdlc_udp_pkt->data[0];			((LINE_TRACE_CONFIG_STRUCT *)mb->data)->			   trace_deactivation_timer = 4000;			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;			if (err != COMMAND_OK) {				chdlc_error(card,err,mb);				card->TracingEnabled = 0;				chdlc_udp_pkt->cblock.return_code = err;				mb->buffer_length = 0;				break;	    		} 			/* Get the base address of the trace element list */			mb->buffer_length = 0;			mb->command = READ_TRACE_CONFIGURATION;			err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;			if (err != COMMAND_OK) {				chdlc_error(card,err,mb);				chdlc_priv_area->TracingEnabled = 0;				chdlc_udp_pkt->cblock.return_code = err;				mb->buffer_length = 0;				break;	    		} 		   		trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *)				mb->data) -> ptr_trace_stat_el_cfg_struct;			sdla_peek(&card->hw, trace_status_cfg_addr,				 &trace_cfg_struct, sizeof(trace_cfg_struct));		    			chdlc_priv_area->start_trace_addr = trace_cfg_struct.

⌨️ 快捷键说明

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