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

📄 sdla_chdlc.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	temp = c_udp_pkt->udp_pkt.udp_src_port;	c_udp_pkt->udp_pkt.udp_src_port = 			c_udp_pkt->udp_pkt.udp_dst_port; 	c_udp_pkt->udp_pkt.udp_dst_port = temp;	/* add UDP pseudo header */	temp = 0x1100;	*((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp;		temp = (udp_length<<8)|(udp_length>>8);	*((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp;		 	/* calculate UDP checksum */	c_udp_pkt->udp_pkt.udp_checksum = 0;	c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET);	/* fill in IP length */	ip_length = len;	temp = (ip_length<<8)|(ip_length>>8);	c_udp_pkt->ip_pkt.total_length = temp;  	/* swap IP addresses */	ip_temp = c_udp_pkt->ip_pkt.ip_src_address;	c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address;	c_udp_pkt->ip_pkt.ip_dst_address = ip_temp;	/* fill in IP checksum */	c_udp_pkt->ip_pkt.hdr_checksum = 0;	c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t));	return len;} /* reply_udp */unsigned short calc_checksum (char *data, int len){	unsigned short temp; 	unsigned long sum=0;	int i;	for( i = 0; i <len; i+=2 ) {		memcpy(&temp,&data[i],2);		sum += (unsigned long)temp;	}	while (sum >> 16 ) {		sum = (sum & 0xffffUL) + (sum >> 16);	}	temp = (unsigned short)sum;	temp = ~temp;	if( temp == 0 ) 		temp = 0xffff;	return temp;	}/*============================================================================ * Get ethernet-style interface statistics. * Return a pointer to struct enet_statistics. */static struct net_device_stats* if_stats(struct net_device* dev){	sdla_t *my_card;	chdlc_private_area_t* chdlc_priv_area;	if ((chdlc_priv_area=dev->priv) == NULL)		return NULL;	my_card = chdlc_priv_area->card;	return &my_card->wandev.stats; }/****** Cisco HDLC Firmware Interface Functions *******************************//*============================================================================ * Read firmware code version. *	Put code version as ASCII string in str.  */static int chdlc_read_version (sdla_t* card, char* str){	CHDLC_MAILBOX_STRUCT* mb = card->mbox;	int len;	char err;	mb->buffer_length = 0;	mb->command = READ_CHDLC_CODE_VERSION;	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;	if(err != COMMAND_OK) {		chdlc_error(card,err,mb);	}	else if (str) {  /* is not null */		len = mb->buffer_length;		memcpy(str, mb->data, len);		str[len] = '\0';	}	return (err);}/*----------------------------------------------------------------------------- *  Configure CHDLC firmware. */static int chdlc_configure (sdla_t* card, void* data){	int err;	CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;	int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT);		mailbox->buffer_length = data_length;  	memcpy(mailbox->data, data, data_length);	mailbox->command = SET_CHDLC_CONFIGURATION;	err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;		if (err != COMMAND_OK) chdlc_error (card, err, mailbox);                           	return err;}/*============================================================================ * Set interrupt mode -- HDLC Version. */static int chdlc_set_intr_mode (sdla_t* card, unsigned mode){	CHDLC_MAILBOX_STRUCT* mb = card->mbox;	CHDLC_INT_TRIGGERS_STRUCT* int_data =		 (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;	int err;	int_data->CHDLC_interrupt_triggers 	= mode;	int_data->IRQ				= card->hw.irq;	int_data->interrupt_timer               = 1;   	mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);	mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;	if (err != COMMAND_OK)		chdlc_error (card, err, mb);	return err;}/*=========================================================== * chdlc_disable_comm_shutdown * * Shutdown() disables the communications. We must * have a sparate functions, because we must not * call chdlc_error() hander since the private * area has already been replaced */static int chdlc_disable_comm_shutdown (sdla_t *card){	CHDLC_MAILBOX_STRUCT* mb = card->mbox;	CHDLC_INT_TRIGGERS_STRUCT* int_data =		 (CHDLC_INT_TRIGGERS_STRUCT *)mb->data;	int err;	/* Disable Interrutps */	int_data->CHDLC_interrupt_triggers 	= 0;	int_data->IRQ				= card->hw.irq;	int_data->interrupt_timer               = 1;   	mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT);	mb->command = SET_CHDLC_INTERRUPT_TRIGGERS;	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;	/* Disable Communications */	if (card->u.c.async_mode) {		mb->command = DISABLE_ASY_COMMUNICATIONS;	}else{		mb->command = DISABLE_CHDLC_COMMUNICATIONS;	}		mb->buffer_length = 0;	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;		card->u.c.comm_enabled = 0;		return 0;}/*============================================================================ * Enable communications. */static int chdlc_comm_enable (sdla_t* card){	int err;	CHDLC_MAILBOX_STRUCT* mb = card->mbox;	mb->buffer_length = 0;	mb->command = ENABLE_CHDLC_COMMUNICATIONS;	err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;	if (err != COMMAND_OK)		chdlc_error(card, err, mb);	else		card->u.c.comm_enabled = 1;		return err;}/*============================================================================ * Read communication error statistics. */static int chdlc_read_comm_err_stats (sdla_t* card){        int err;        CHDLC_MAILBOX_STRUCT* mb = card->mbox;        mb->buffer_length = 0;        mb->command = READ_COMMS_ERROR_STATS;        err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;        if (err != COMMAND_OK)                chdlc_error(card,err,mb);        return err;}/*============================================================================ * Read CHDLC operational statistics. */static int chdlc_read_op_stats (sdla_t* card){        int err;        CHDLC_MAILBOX_STRUCT* mb = card->mbox;        mb->buffer_length = 0;        mb->command = READ_CHDLC_OPERATIONAL_STATS;        err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;        if (err != COMMAND_OK)                chdlc_error(card,err,mb);        return err;}/*============================================================================ * Update communications error and general packet statistics. */static int update_comms_stats(sdla_t* card,	chdlc_private_area_t* chdlc_priv_area){        CHDLC_MAILBOX_STRUCT* mb = card->mbox;  	COMMS_ERROR_STATS_STRUCT* err_stats;        CHDLC_OPERATIONAL_STATS_STRUCT *op_stats;	/* 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_INFO "%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;}/********** Bottom Half Handlers ********************************************//* NOTE: There is no API, BH support for Kernels lower than 2.2.X. *       DO NOT INSERT ANY CODE HERE, NOTICE THE  *       PREPROCESSOR STATEMENT ABOVE, UNLESS YOU KNOW WHAT YOU ARE *       DOING */static void chdlc_work(struct net_device * dev){	chdlc_private_area_t* chan = dev->priv;	sdla_t *card = chan->card;	struct sk_buff *skb;	if (atomic_read(&chan->bh_buff_used) == 0){		clear_bit(0, &chan->tq_working);		return;	}	while (atomic_read(&chan->bh_buff_used)){		skb  = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb;		if (skb != NULL){			if (chan->common.sk == NULL || chan->common.func == NULL){				++card->wandev.stats.rx_dropped;				dev_kfree_skb_any(skb);				chdlc_work_cleanup(dev);				continue;			}			if (chan->common.func(skb,dev,chan->common.sk) != 0){				/* Sock full cannot send, queue us for another                                 * try */				atomic_set(&chan->common.receive_block,1);				return;			}else{				chdlc_work_cleanup(dev);			}		}else{			chdlc_work_cleanup(dev);		}	}		clear_bit(0, &chan->tq_working);	return;}static int chdlc_work_cleanup(struct net_device *dev){	chdlc_private_area_t* chan = dev->priv;	((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL;	if (chan->bh_read == MAX_BH_BUFF){		chan->bh_read=0;	}else{		++chan->bh_read;		}	atomic_dec(&chan->bh_buff_used);	return 0;}static int bh_enqueue(struct net_device *dev, struct sk_buff *skb){	/* Check for full */	chdlc_private_area_t* chan = dev->priv;	sdla_t *card = chan->card;	if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){		++card->wandev.stats.rx_dropped;		dev_kfree_skb_any(skb);		return 1; 	}	((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb;	if (chan->bh_write == MAX_BH_BUFF){		chan->bh_write=0;	}else{		++chan->bh_write;	}	atomic_inc(&chan->bh_buff_used);	return 0;}/* END OF API BH Support *//****** Interrupt Handlers **************************************************//*============================================================================ * Cisco HDLC interrupt service routine. */static void wpc_isr (sdla_t* card){	struct net_device* dev;	SHARED_MEMORY_INFO_STRUCT* flags = NULL;	int i;	sdla_t *my_card;

⌨️ 快捷键说明

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