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

📄 sdla_chdlc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* on the first timer interrupt, read the comms error statistics */	if(chdlc_priv_area->update_comms_stats == 2) {		if(chdlc_read_comm_err_stats(card))			return 1;		err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data;		card->wandev.stats.rx_over_errors = 				err_stats->Rx_overrun_err_count;		card->wandev.stats.rx_crc_errors = 				err_stats->CRC_err_count;		card->wandev.stats.rx_frame_errors = 				err_stats->Rx_abort_count;		card->wandev.stats.rx_fifo_errors = 				err_stats->Rx_dis_pri_bfrs_full_count; 		card->wandev.stats.rx_missed_errors =				card->wandev.stats.rx_fifo_errors;		card->wandev.stats.tx_aborted_errors =				err_stats->sec_Tx_abort_count;	}        /* on the second timer interrupt, read the operational statistics */	else {        	if(chdlc_read_op_stats(card))                	return 1;		op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data;		card->wandev.stats.rx_length_errors =			(op_stats->Rx_Data_discard_short_count +			op_stats->Rx_Data_discard_long_count);	}	return 0;}/*============================================================================ * Send packet. *	Return:	0 - o.k. *		1 - no transmit buffers available */static int chdlc_send (sdla_t* card, void* data, unsigned len){	CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf;	if (txbuf->opp_flag)		return 1;		sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len);	txbuf->frame_length = len;	txbuf->opp_flag = 1;		/* start transmission */		/* Update transmit buffer control fields */	card->u.c.txbuf = ++txbuf;	if ((void*)txbuf > card->u.c.txbuf_last)		card->u.c.txbuf = card->u.c.txbuf_base;	return 0;}/****** Firmware Error Handler **********************************************//*============================================================================ * Firmware error handler. *	This routine is called whenever firmware command returns non-zero *	return code. * * Return zero if previous command has to be cancelled. */static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb){	unsigned cmd = mb->command;	switch (err) {	case CMD_TIMEOUT:		printk(KERN_ERR "%s: command 0x%02X timed out!\n",			card->devname, cmd);		break;	case S514_BOTH_PORTS_SAME_CLK_MODE:		if(cmd == SET_CHDLC_CONFIGURATION) {			printk(KERN_INFO			 "%s: Configure both ports for the same clock source\n",				card->devname);			break;		}	default:		printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",			card->devname, cmd, err);	}	return 0;}/****** Interrupt Handlers **************************************************//*============================================================================ * Cisco HDLC interrupt service routine. */STATIC void wpc_isr (sdla_t* card){	struct net_device* dev;	chdlc_private_area_t* chdlc_priv_area;	SHARED_MEMORY_INFO_STRUCT* flags = NULL;	int i, interrupt_serviced = 0;	sdla_t *my_card;	/* 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;			}		}	}	dev = card->wandev.dev;		card->in_isr = 1;		/* if critical due to peripheral operations	 * ie. update() or getstats() then reset the interrupt and	 * wait for the board to retrigger.	 */	if(test_bit(1, (void*)&card->wandev.critical)) {               	if(card->u.c.flags != NULL) {                       	flags = card->u.c.flags;			if(flags->interrupt_info_struct.					interrupt_type) {					flags->interrupt_info_struct.						interrupt_type = 0;			}		}		card->in_isr = 0;		return;	}	/* On a 508 Card, if critical due to if_send          * Major Error !!!	 */	if(card->hw.type != SDLA_S514) {		if(test_and_set_bit(0, (void*)&card->wandev.critical)) {			printk(KERN_INFO "%s: Critical while in ISR: %x\n",				card->devname, card->wandev.critical);			card->in_isr = 0;			return;		}	}	/* FIXME: Take this check out later in the future */	if(card->u.c.flags != NULL) {			flags = card->u.c.flags;		switch(flags->interrupt_info_struct.interrupt_type) {		case RX_APP_INT_PEND:	/* 0x01: receive interrupt */			interrupt_serviced = 1;			rx_intr(card);			break;		case TX_APP_INT_PEND:	/* 0x02: transmit interrupt */			interrupt_serviced = 1;			flags->interrupt_info_struct.interrupt_permission &=				 ~APP_INT_ON_TX_FRAME;			chdlc_priv_area = dev->priv;			netif_wake_queue(dev);			break;		case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */			interrupt_serviced = 1;			++ Intr_test_counter;			break;		case CHDLC_EXCEP_COND_APP_INT_PEND:	/* 0x20 */			interrupt_serviced = 1;			process_chdlc_exception(card);			break;		case GLOBAL_EXCEP_COND_APP_INT_PEND:			interrupt_serviced = 1;			process_global_exception(card);			break;		case TIMER_APP_INT_PEND:			interrupt_serviced = 1;			timer_intr(card);			break;		default:			break;		}		}	if(!interrupt_serviced) {		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");		}	card->in_isr = 0;	flags->interrupt_info_struct.interrupt_type = 0;        if(card->hw.type != SDLA_S514){        	clear_bit(0, (void*)&card->wandev.critical);	}        }/*============================================================================ * 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;	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");		return;	}	dev = card->wandev.dev;	chdlc_priv_area = dev->priv;	if(dev && netif_running(dev)) {		len  = rxbuf->frame_length;		/* Allocate socket buffer */		skb = dev_alloc_skb(len);		if (skb != NULL) {			/* Copy data to the socket buffer */			unsigned addr = rxbuf->ptr_data_bfr;					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);			/* Decapsulate packet */			skb->protocol = htons(ETH_P_IP);			card->wandev.stats.rx_packets ++;#ifdef LINUX_2_1			card->wandev.stats.rx_bytes += skb->len;#endif			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(0x16);                                	skb->pkt_type = PACKET_HOST;				}/* 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);			}		} else {			printk(KERN_INFO				"%s: no socket buffers available!\n",					card->devname);			++card->wandev.stats.rx_dropped;		}     	}	/* 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;	/* 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){	struct net_device * dev = card->wandev.dev;	chdlc_private_area_t *chdlc_priv_area = dev->priv;	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;	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	= 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 {#ifdef LINUX_2_1                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); 			}		}#else                cfg.IP_address          = ntohl(dev->pa_addr);                cfg.IP_netmask          = ntohl(dev->pa_mask);		chdlc_priv_area->IP_address = ntohl(dev->pa_addr);		chdlc_priv_area->IP_netmask = ntohl(dev->pa_mask);#endif		/* 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");

⌨️ 快捷键说明

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