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 + -
显示快捷键?