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

📄 sdla_chdlc.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Check for which port the interrupt has been generated	 * Since Secondary Port is piggybacking on the Primary         * the check must be done here. 	 */	flags = card->u.c.flags;	if (!flags->interrupt_info_struct.interrupt_type){		/* Check for a second port (piggybacking) */		if ((my_card = card->next)){			flags = my_card->u.c.flags;			if (flags->interrupt_info_struct.interrupt_type){				card = my_card;				card->isr(card);				return;			}		}	}	flags = card->u.c.flags;	card->in_isr = 1;	dev = card->wandev.dev;		/* If we get an interrupt with no network device, stop the interrupts	 * and issue an error */	if (!card->tty_opt && !dev && 	    flags->interrupt_info_struct.interrupt_type != 	    	COMMAND_COMPLETE_APP_INT_PEND){		goto isr_done;	}		/* if critical due to peripheral operations	 * ie. update() or getstats() then reset the interrupt and	 * wait for the board to retrigger.	 */	if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) {		printk(KERN_INFO "ISR CRIT TO PERI\n");		goto isr_done;	}	/* On a 508 Card, if critical due to if_send          * Major Error !!! */	if(card->hw.type != SDLA_S514) {		if(test_bit(SEND_CRIT, (void*)&card->wandev.critical)) {			printk(KERN_INFO "%s: Critical while in ISR: %lx\n",				card->devname, card->wandev.critical);			card->in_isr = 0;			flags->interrupt_info_struct.interrupt_type = 0;			return;		}	}	switch(flags->interrupt_info_struct.interrupt_type) {	case RX_APP_INT_PEND:	/* 0x01: receive interrupt */		rx_intr(card);		break;	case TX_APP_INT_PEND:	/* 0x02: transmit interrupt */		flags->interrupt_info_struct.interrupt_permission &=			 ~APP_INT_ON_TX_FRAME;		if (card->tty_opt){			wanpipe_tty_trigger_poll(card);			break;		}		if (dev && netif_queue_stopped(dev)){			if (card->u.c.usedby == API){				netif_start_queue(dev);				wakeup_sk_bh(dev);			}else{				netif_wake_queue(dev);			}		}		break;	case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */		++ Intr_test_counter;		break;	case CHDLC_EXCEP_COND_APP_INT_PEND:	/* 0x20 */		process_chdlc_exception(card);		break;	case GLOBAL_EXCEP_COND_APP_INT_PEND:		process_global_exception(card);		break;	case TIMER_APP_INT_PEND:		timer_intr(card);		break;	default:		printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", 			card->devname,			flags->interrupt_info_struct.interrupt_type);		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");			break;	}isr_done:	card->in_isr = 0;	flags->interrupt_info_struct.interrupt_type = 0;	return;}/*============================================================================ * Receive interrupt handler. */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;	}	len  = rxbuf->frame_length;	if (card->tty_opt){		if (rxbuf->error_flag){				goto rx_exit;		}		if (len <= CRC_LENGTH){			goto rx_exit;		}				if (!card->u.c.async_mode){			len -= CRC_LENGTH;		}		wanpipe_tty_receive(card,addr,len);		goto rx_exit;	}	dev = card->wandev.dev;	if (!dev){		goto rx_exit;	}	if (!netif_running(dev))		goto rx_exit;	chdlc_priv_area = dev->priv;		/* Allocate socket buffer */	skb = dev_alloc_skb(len);	if (skb == NULL) {		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_IP);	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 if(card->u.c.usedby == API) {		api_rx_hdr_t* api_rx_hdr;       		skb_push(skb, sizeof(api_rx_hdr_t));                api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00];		api_rx_hdr->error_flag = rxbuf->error_flag;     		api_rx_hdr->time_stamp = rxbuf->time_stamp;                skb->protocol = htons(PVC_PROT);     		skb->mac.raw  = skb->data;		skb->dev      = dev;               	skb->pkt_type = WAN_PACKET_DATA;		bh_enqueue(dev, skb);		if (!test_and_set_bit(0,&chdlc_priv_area->tq_working))			wanpipe_queue_work(&chdlc_priv_area->common.wanpipe_work);	}else{		/* FIXME: we should check to see if the received packet is a                           multicast packet so that we can increment the multicast                           statistic                          ++ chdlc_priv_area->if_stats.multicast;		*/               	/* 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;        if ((dev = card->wandev.dev)==NULL){		flags = card->u.c.flags;                flags->interrupt_info_struct.interrupt_permission &=                        ~APP_INT_ON_TIMER;		return;	}	        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;	cfg.modem_status_timer		= 100;	cfg.CHDLC_protocol_options	= card->u.c.protocol_options;	if (card->tty_opt){		cfg.CHDLC_API_options	= DISCARD_RX_ERROR_FRAMES;	}		cfg.percent_data_buffer_for_Tx  = (card->u.c.receive_only) ? 0 : 50;	cfg.CHDLC_statistics_options	= (CHDLC_TX_DATA_BYTE_COUNT_STAT |		CHDLC_RX_DATA_BYTE_COUNT_STAT);		if (card->tty_opt){		card->wandev.mtu = TTY_CHDLC_MAX_MTU;	}	cfg.max_CHDLC_data_field_length	= card->wandev.mtu;	cfg.transmit_keepalive_timer	= card->u.c.kpalv_tx;	cfg.receive_keepalive_timer	= card->u.c.kpalv_rx;	cfg.keepalive_error_tolerance	= card->u.c.kpalv_err;	cfg.SLARP_request_timer		= card->u.c.slarp_timer;	if (cfg.SLARP_request_timer) {		cfg.IP_address		= 0;		cfg.IP_netmask		= 0;			}else if (card->wandev.dev){		struct net_device *dev = card->wandev.dev;		chdlc_private_area_t *chdlc_priv_area = dev->priv;		                struct in_device *in_dev = dev->ip_ptr;		if(in_dev != NULL) {			struct in_ifaddr *ifa = in_dev->ifa_list;			if (ifa != NULL ) {				cfg.IP_address	= ntohl(ifa->ifa_local);				cfg.IP_netmask	= ntohl(ifa->ifa_mask); 				chdlc_priv_area->IP_address = ntohl(ifa->ifa_local);				chdlc_priv_area->IP_netmask = ntohl(ifa->ifa_mask); 			}		}		/* FIXME: We must re-think this message in next release		if((cfg.IP_address & 0x000000FF) > 2) {			printk(KERN_WARNING "\n");	                printk(KERN_WARNING "  WARNING:%s configured with an\n",				card->devname);			printk(KERN_WARNING "  invalid local IP address.\n");                        printk(KERN_WARNING "  Slarp pragmatics will fail.\n");                        printk(KERN_WARNING "  IP address should be of the\n");			printk(KERN_WARNING "  format A.B.C.1 or A.B.C.2.\n");		}		*/			}		return chdlc_configure(card, &cfg);}/*-----------------------------------------------------------------------------   set_asy_config() used to set asynchronous configuration options on the board------------------------------------------------------------------------------*/static int set_asy_config(sdla_t* card){        ASY_CONFIGURATION_STRUCT cfg; 	CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;	int err;	memset(&cfg, 0, sizeof(ASY_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;	cfg.asy_API_options 		= card->u.c.api_options;	cfg.asy_protocol_options	= card->u.c.protocol_options;	cfg.Tx_bits_per_char		= card->u.c.tx_bits_per_char;	cfg.Rx_bits_per_char		= card->u.c.rx_bits_per_char;	cfg.stop_bits			= card->u.c.stop_bits;	cfg.parity			= card->u.c.parity;	cfg.break_timer			= card->u.c.break_timer;	cfg.asy_Rx_inter_char_timer	= card->u.c.inter_char_timer; 	cfg.asy_Rx_complete_length	= card->u.c.rx_complete_length; 	cfg.XON_char			= card->u.c.xon_char;	cfg.XOFF_char			= card->u.c.xoff_char;	cfg.asy_statistics_options	= (CHDLC_TX_DATA_BYTE_COUNT_STAT |		CHDLC_RX_DATA_BYTE_COUNT_STAT);	mailbox->buffer_length = sizeof(ASY_CONFIGURATION_STRUCT);	memcpy(mailbox->data, &cfg, mailbox->buffer_length);	mailbox->command = SET_ASY_CONFIGURATION;	err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;	if (err != COMMAND_OK) 		chdlc_error (card, err, mailbox);	return err;}/*============================================================================ * Enable asynchronous communications. */static int asy_comm_enable (sdla_t* card){	int err;	CHDLC_MAILBOX_STRUCT* mb = card->mbox;	mb->buffer_len

⌨️ 快捷键说明

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