qeth.c

来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 2,327 行 · 第 1/5 页

C
2,327
字号
}static qeth_card_t *qeth_get_card_by_name(char *name){        qeth_card_t *card;	my_read_lock(&list_lock);        card=firstcard;        while (card) {		if (!strncmp(name,card->dev_name,DEV_NAME_LEN)) break;                card=card->next;        }	my_read_unlock(&list_lock);        return card;}static void qeth_convert_addr_to_text(int version,__u8 *addr,char *text){	if (version==4) {		sprintf(text,"%02x%02x%02x%02x",			addr[0],addr[1],addr[2],addr[3]);	} else {		sprintf(text,"%02x%02x%02x%02x%02x%02x%02x%02x" \			"%02x%02x%02x%02x%02x%02x%02x%02x",			addr[0],addr[1],addr[2],addr[3],			addr[4],addr[5],addr[6],addr[7],			addr[8],addr[9],addr[10],addr[11],			addr[12],addr[13],addr[14],addr[15]);	}}static int qeth_convert_text_to_addr(int version,char *text,__u8 *addr){	int olen=(version==4)?4:16;	while (olen--) {		if ( (!isxdigit(*text)) || (!isxdigit(*(text+1))) )			return -EINVAL;		*addr=(qeth_getxdigit(*text)<<4)+qeth_getxdigit(*(text+1));		addr++;		text+=2;	}	return 0;}static void qeth_add_ipato_entry(int version,__u8 *addr,int mask_bits,				 char *dev_name){	ipato_entry_t *entry,*e;	int len=(version==4)?4:16;	entry=(ipato_entry_t*)kmalloc(sizeof(ipato_entry_t),GFP_KERNEL);	if (!entry) {		PRINT_ERR("not enough memory for ipato allocation\n");		return;	}	entry->version=version;	memcpy(entry->addr,addr,len);	if (dev_name) {		strncpy(entry->dev_name,dev_name,DEV_NAME_LEN);		if (qeth_get_card_by_name(dev_name)->options.ena_ipat!=		    ENABLE_TAKEOVER)			PRINT_WARN("IP takeover is not enabled on %s! " \				   "Ignoring line\n",dev_name);	} else		memset(entry->dev_name,0,DEV_NAME_LEN);	entry->mask_bits=mask_bits;	entry->next=NULL;	my_spin_lock(&ipato_list_lock);	if (ipato_entries) {		e=ipato_entries;		while (e) {			if ( (e->version==version) &&			     (e->mask_bits==mask_bits) &&			     ( ((dev_name)&&!strncmp(e->dev_name,dev_name,						     DEV_NAME_LEN)) ||			       (!dev_name) ) &&			     (!memcmp(e->addr,addr,len)) ) {				PRINT_INFO("ipato to be added does already " \					   "exist\n");				kfree(entry);				goto out;			     }			if (e->next) e=e->next; else break;		}		e->next=entry;	} else		ipato_entries=entry;out:	my_spin_unlock(&ipato_list_lock);}static void qeth_del_ipato_entry(int version,__u8 *addr,int mask_bits,				 char *dev_name){	ipato_entry_t *e,*e_before;	int len=(version==4)?4:16;	int found=0;		my_spin_lock(&ipato_list_lock);	e=ipato_entries;	if ( (e->version==version) &&	     (e->mask_bits==mask_bits) &&	     (!memcmp(e->addr,addr,len)) ) {		ipato_entries=e->next;		kfree(e);	} else while (e) {		e_before=e;		e=e->next;		if (!e) break;		if ( (e->version==version) &&		     (e->mask_bits==mask_bits) &&		     ( ((dev_name)&&!strncmp(e->dev_name,dev_name,					     DEV_NAME_LEN)) ||		       (!dev_name) ) &&		     (!memcmp(e->addr,addr,len)) ) {			e_before->next=e->next;			kfree(e);			found=1;			break;		}	}	if (!found)		PRINT_INFO("ipato to be deleted does not exist\n");	my_spin_unlock(&ipato_list_lock);}static void qeth_convert_addr_to_bits(__u8 *addr,char *bits,int len){	int i,j;	__u8 octet;		for (i=0;i<len;i++) {		octet=addr[i];		for (j=7;j>=0;j--) {			bits[i*8+j]=(octet&1)?1:0;			octet>>=1;		}	}}static int qeth_is_ipa_covered_by_ipato_entries(int version,__u8 *addr,						qeth_card_t *card){	char *memarea,*addr_bits,*entry_bits;	int len=(version==4)?4:16;	int invert=(version==4)?ipato_inv4:ipato_inv6;	int result=0;	ipato_entry_t *e;	if (card->options.ena_ipat!=ENABLE_TAKEOVER) {		return 0;	}	memarea=kmalloc(256,GFP_KERNEL);	if (!memarea) {		PRINT_ERR("not enough memory to check out whether to " \			  "use ipato\n");		return 0;	}	addr_bits=memarea;	entry_bits=memarea+128;	qeth_convert_addr_to_bits(addr,addr_bits,len);	e=ipato_entries;	while (e) {		qeth_convert_addr_to_bits(e->addr,entry_bits,len);		if ( (!memcmp(addr_bits,entry_bits,			      __min(len*8,e->mask_bits))) &&		     ( (e->dev_name[0]&&			(!strncmp(e->dev_name,card->dev_name,DEV_NAME_LEN))) ||		       (!e->dev_name[0]) ) ) {			result=1;			break;		}		e=e->next;	}	kfree(memarea);	if (invert)		return !result;	else		return result;}static void qeth_set_dev_flag_running(qeth_card_t *card){	if (card) {		card->dev->flags|=IFF_RUNNING;/*		clear_bit(__LINK_STATE_DOWN,&dev->flags);*/	}}static void qeth_set_dev_flag_norunning(qeth_card_t *card){	if (card) {		card->dev->flags&=~IFF_RUNNING;/*		set_bit(__LINK_STATE_DOWN,&dev->flags);*/	}}static void qeth_restore_dev_flag_state(qeth_card_t *card){	if (card) {		if (card->saved_dev_flags&IFF_RUNNING)			card->dev->flags|=IFF_RUNNING;		else			card->dev->flags&=~IFF_RUNNING;/*		if (card->saved_dev_flags&__LINK_STATE_DOWN)			set_bit(__LINK_STATE_DOWN,&card->dev->flags);		else			clear_bit(__LINK_STATE_DOWN,&card->dev->flags);*/	}}static void qeth_save_dev_flag_state(qeth_card_t *card){	if (card) {		card->saved_dev_flags=card->dev->flags&IFF_RUNNING;/*		card->saved_dev_flags=card->dev->flags&__LINK_STATE_DOWN;*/	}}static inline int netif_is_busy(struct net_device *dev){        return(test_bit(__LINK_STATE_XOFF,&dev->flags));}static int qeth_open(struct net_device *dev){	char dbf_text[15];	qeth_card_t *card;	card=(qeth_card_t *)dev->priv;	sprintf(dbf_text,"open%4x",card->irq0);	QETH_DBF_TEXT2(0,trace,dbf_text);	QETH_DBF_TEXT2(0,setup,dbf_text);	qeth_save_dev_flag_state(card);	netif_start_queue(dev);        if (!atomic_swap(&((qeth_card_t*)dev->priv)->is_open,1)) {                MOD_INC_USE_COUNT;        }	return 0;}static int qeth_set_config(struct net_device *dev,struct ifmap *map){	qeth_card_t *card=(qeth_card_t*)dev->priv;	char dbf_text[15];	sprintf(dbf_text,"nscf%04x",card->irq0);	QETH_DBF_TEXT3(0,trace,dbf_text);	return -EOPNOTSUPP;}static int qeth_is_multicast_skb_at_all(struct sk_buff *skb,int version){	int i=RTN_UNSPEC;	qeth_card_t *card = (qeth_card_t *)skb->dev->priv;	if (skb->dst && skb->dst->neighbour) {		i=skb->dst->neighbour->type;		return ((i==RTN_BROADCAST)||			(i==RTN_MULTICAST)||			(i==RTN_ANYCAST))?i:0;	}	/* ok, we've to try it somehow else */	if (version==4) {		return ((skb->nh.raw[16]&0xf0)==0xe0)?RTN_MULTICAST:0;	} else if (version==6) {		return (skb->nh.raw[24]==0xff)?RTN_MULTICAST:0;	}	if (!memcmp(skb->nh.raw,skb->dev->broadcast,6)) {		i=RTN_BROADCAST;	} else {	        __u16 hdr_mac;	        hdr_mac=*((__u16*)skb->nh.raw);	        /* tr multicast? */	        switch (card->link_type) {	        case QETH_MPC_LINK_TYPE_HSTR:	        case QETH_MPC_LINK_TYPE_LANE_TR:	        	if ( (hdr_mac==QETH_TR_MAC_NC) ||			     (hdr_mac==QETH_TR_MAC_C) )				i = RTN_MULTICAST;			break;	        /* eth or so multicast? */                default:                      	if ( (hdr_mac==QETH_ETH_MAC_V4) ||			     (hdr_mac==QETH_ETH_MAC_V6) )			        i = RTN_MULTICAST;	        }        }	return ((i==RTN_BROADCAST)||	        (i==RTN_MULTICAST)||	        (i==RTN_ANYCAST))?i:0;}static int qeth_get_prioqueue(qeth_card_t *card,struct sk_buff *skb,			      int multicast,int version){	if (!version &&	    (card->type==QETH_CARD_TYPE_OSAE))		return QETH_DEFAULT_QUEUE;        switch (card->no_queues) {        case 1:                return 0;        case 4:		if ( (card->can_do_async_iqd) &&		     (card->options.async_iqd==ASYNC_IQD) ) {			return card->no_queues-1;		}		if (card->is_multicast_different) {			if (multicast) {			    return card->is_multicast_different&				    (card->no_queues-1);			} else {				return 0;			}		}		if (card->options.do_prio_queueing) {			if (version==4) {				if (card->options.do_prio_queueing==				    PRIO_QUEUEING_TOS) {					if (skb->nh.iph->tos&					    IP_TOS_NOTIMPORTANT) {						return 3;					}					if (skb->nh.iph->tos&					    IP_TOS_LOWDELAY) {						return 0;					}					if (skb->nh.iph->tos&					    IP_TOS_HIGHTHROUGHPUT) {						return 1;					}					if (skb->nh.iph->tos&					    IP_TOS_HIGHRELIABILITY) {						return 2;					}					return QETH_DEFAULT_QUEUE;				}				if (card->options.do_prio_queueing==				    PRIO_QUEUEING_PREC) {					return 3-(skb->nh.iph->tos>>6);				}			} else if (version==6) {/******************** ********************TODO: IPv6!!!********************/			}                        return card->options.default_queue;                } else return card->options.default_queue;        default:                return 0;        }}static void qeth_wakeup(qeth_card_t *card) {	char dbf_text[15];	sprintf(dbf_text,"wkup%4x",card->irq0);	QETH_DBF_TEXT5(0,trace,dbf_text);        atomic_set(&card->data_has_arrived,1);	spin_lock(&card->wait_q_lock);	if (atomic_read(&card->wait_q_active)) {		wake_up(&card->wait_q);	}	spin_unlock(&card->wait_q_lock);}static int qeth_check_idx_response(unsigned char *buffer){	if (!buffer)		return 0;        if ((buffer[2]&0xc0)==0xc0) {                return -EIO;        }        return 0;}static int qeth_get_cards_problem(qeth_card_t *card,unsigned char *buffer,				  int irq,int dstat,int cstat,int rqparam,				  char *irb,char *sense){	char dbf_text[15];	int problem=0;	if (atomic_read(&card->shutdown_phase)) return 0;	if (dstat&DEV_STAT_UNIT_CHECK) {		if (irq==card->irq2) {			sprintf(dbf_text,"ACHK%04x",card->irq0);			QETH_DBF_TEXT1(0,trace,dbf_text);			problem=PROBLEM_ACTIVATE_CHECK_CONDITION;			goto out;		}		if (sense[SENSE_RESETTING_EVENT_BYTE]&		    SENSE_RESETTING_EVENT_FLAG) {			sprintf(dbf_text,"REVN%04x",card->irq0);			QETH_DBF_TEXT1(0,trace,dbf_text);			problem=PROBLEM_RESETTING_EVENT_INDICATOR;			goto out;		}		if (sense[SENSE_COMMAND_REJECT_BYTE]&		    SENSE_COMMAND_REJECT_FLAG) {			sprintf(dbf_text,"CREJ%04x",card->irq0);			QETH_DBF_TEXT1(0,trace,dbf_text);			problem=PROBLEM_COMMAND_REJECT;			goto out;		}		if ( (sense[2]==0xaf)&&(sense[3]==0xfe) ) {			sprintf(dbf_text,"AFFE%04x",card->irq0);			QETH_DBF_TEXT1(0,trace,dbf_text);			problem=PROBLEM_AFFE;			goto out;		}		if ( (!sense[0]) && (!sense[1]) &&		     (!sense[2]) && (!sense[3]) ) {			sprintf(dbf_text,"ZSNS%04x",card->irq0);			QETH_DBF_TEXT1(0,trace,dbf_text);			problem=PROBLEM_ZERO_SENSE_DATA;			goto out;		}		sprintf(dbf_text,"GCHK%04x",card->irq0);		QETH_DBF_TEXT1(0,trace,dbf_text);		problem=PROBLEM_GENERAL_CHECK;		goto out;	}	if (cstat& (SCHN_STAT_CHN_CTRL_CHK|SCHN_STAT_INTF_CTRL_CHK|		    SCHN_STAT_CHN_DATA_CHK|SCHN_STAT_CHAIN_CHECK|		    SCHN_STAT_PROT_CHECK|SCHN_STAT_PROG_CHECK) ) {		sprintf(dbf_text,"GCHK%04x",card->irq0);		QETH_DBF_TEXT1(0,trace,dbf_text);		QETH_DBF_HEX1(0,misc,irb,__max(QETH_DBF_MISC_LEN,64));		PRINT_WARN("check on irq x%x, dstat=x%x, cstat=x%x, " \			   "rqparam=x%x\n",irq,dstat,cstat,rqparam);		HEXDUMP16(WARN,"irb: ",irb);		HEXDUMP16(WARN,"irb: ",((char*)irb)+32);		problem=PROBLEM_GENERAL_CHECK;		goto out;	}        if (qeth_check_idx_response(buffer)) {                PRINT_WARN("received an IDX TERMINATE on irq 0x%X/0x%X " \			   "with cause code 0x%02x%s\n",			   card->irq0,card->irq1,buffer[4],			   (buffer[4]==0x22)?" -- try another portname":"");		sprintf(dbf_text,"RTRM%04x",card->irq0);		QETH_DBF_TEXT1(0,trace,dbf_text);                problem=PROBLEM_RECEIVED_IDX_TERMINATE;		goto out;        }        if (IS_IPA(buffer) && !IS_IPA_REPLY(buffer)) {                if ( *(PDU_ENCAPSULATION(buffer))==IPA_CMD_STOPLAN ) {

⌨️ 快捷键说明

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