📄 qeth_main.c
字号:
void *reply_param){ int rc; char prot_type; QETH_DBF_TEXT(trace,4,"sendipa"); if (card->options.layer2) if (card->info.type == QETH_CARD_TYPE_OSN) prot_type = QETH_PROT_OSN2; else prot_type = QETH_PROT_LAYER2; else prot_type = QETH_PROT_TCPIP; qeth_prepare_ipa_cmd(card,iob,prot_type); rc = qeth_send_control_data(card, IPA_CMD_LENGTH, iob, reply_cb, reply_param); return rc;}static intqeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data){ struct qeth_cmd_buffer *iob; QETH_DBF_TEXT(setup, 2, "cmenblcb"); iob = (struct qeth_cmd_buffer *) data; memcpy(&card->token.cm_filter_r, QETH_CM_ENABLE_RESP_FILTER_TOKEN(iob->data), QETH_MPC_TOKEN_LENGTH); QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc); return 0;}static intqeth_cm_enable(struct qeth_card *card){ int rc; struct qeth_cmd_buffer *iob; QETH_DBF_TEXT(setup,2,"cmenable"); iob = qeth_wait_for_buffer(&card->write); memcpy(iob->data, CM_ENABLE, CM_ENABLE_SIZE); memcpy(QETH_CM_ENABLE_ISSUER_RM_TOKEN(iob->data), &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH); memcpy(QETH_CM_ENABLE_FILTER_TOKEN(iob->data), &card->token.cm_filter_w, QETH_MPC_TOKEN_LENGTH); rc = qeth_send_control_data(card, CM_ENABLE_SIZE, iob, qeth_cm_enable_cb, NULL); return rc;}static intqeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data){ struct qeth_cmd_buffer *iob; QETH_DBF_TEXT(setup, 2, "cmsetpcb"); iob = (struct qeth_cmd_buffer *) data; memcpy(&card->token.cm_connection_r, QETH_CM_SETUP_RESP_DEST_ADDR(iob->data), QETH_MPC_TOKEN_LENGTH); QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc); return 0;}static intqeth_cm_setup(struct qeth_card *card){ int rc; struct qeth_cmd_buffer *iob; QETH_DBF_TEXT(setup,2,"cmsetup"); iob = qeth_wait_for_buffer(&card->write); memcpy(iob->data, CM_SETUP, CM_SETUP_SIZE); memcpy(QETH_CM_SETUP_DEST_ADDR(iob->data), &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH); memcpy(QETH_CM_SETUP_CONNECTION_TOKEN(iob->data), &card->token.cm_connection_w, QETH_MPC_TOKEN_LENGTH); memcpy(QETH_CM_SETUP_FILTER_TOKEN(iob->data), &card->token.cm_filter_r, QETH_MPC_TOKEN_LENGTH); rc = qeth_send_control_data(card, CM_SETUP_SIZE, iob, qeth_cm_setup_cb, NULL); return rc;}static intqeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data){ __u16 mtu, framesize; __u16 len; __u8 link_type; struct qeth_cmd_buffer *iob; QETH_DBF_TEXT(setup, 2, "ulpenacb"); iob = (struct qeth_cmd_buffer *) data; memcpy(&card->token.ulp_filter_r, QETH_ULP_ENABLE_RESP_FILTER_TOKEN(iob->data), QETH_MPC_TOKEN_LENGTH); if (qeth_get_mtu_out_of_mpc(card->info.type)) { memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(iob->data), 2); mtu = qeth_get_mtu_outof_framesize(framesize); if (!mtu) { iob->rc = -EINVAL; QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc); return 0; } card->info.max_mtu = mtu; card->info.initial_mtu = mtu; card->qdio.in_buf_size = mtu + 2 * PAGE_SIZE; } else { card->info.initial_mtu = qeth_get_initial_mtu_for_card(card); card->info.max_mtu = qeth_get_max_mtu_for_card(card->info.type); card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; } memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(iob->data), 2); if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) { memcpy(&link_type, QETH_ULP_ENABLE_RESP_LINK_TYPE(iob->data), 1); card->info.link_type = link_type; } else card->info.link_type = 0; QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc); return 0;}static intqeth_ulp_enable(struct qeth_card *card){ int rc; char prot_type; struct qeth_cmd_buffer *iob; /*FIXME: trace view callbacks*/ QETH_DBF_TEXT(setup,2,"ulpenabl"); iob = qeth_wait_for_buffer(&card->write); memcpy(iob->data, ULP_ENABLE, ULP_ENABLE_SIZE); *(QETH_ULP_ENABLE_LINKNUM(iob->data)) = (__u8) card->info.portno; if (card->options.layer2) if (card->info.type == QETH_CARD_TYPE_OSN) prot_type = QETH_PROT_OSN2; else prot_type = QETH_PROT_LAYER2; else prot_type = QETH_PROT_TCPIP; memcpy(QETH_ULP_ENABLE_PROT_TYPE(iob->data),&prot_type,1); memcpy(QETH_ULP_ENABLE_DEST_ADDR(iob->data), &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH); memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(iob->data), &card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH); memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(iob->data), card->info.portname, 9); rc = qeth_send_control_data(card, ULP_ENABLE_SIZE, iob, qeth_ulp_enable_cb, NULL); return rc;}static inline __u16__raw_devno_from_bus_id(char *id){ id += (strlen(id) - 4); return (__u16) simple_strtoul(id, &id, 16);}static intqeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data){ struct qeth_cmd_buffer *iob; QETH_DBF_TEXT(setup, 2, "ulpstpcb"); iob = (struct qeth_cmd_buffer *) data; memcpy(&card->token.ulp_connection_r, QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data), QETH_MPC_TOKEN_LENGTH); QETH_DBF_TEXT_(setup, 2, " rc%d", iob->rc); return 0;}static intqeth_ulp_setup(struct qeth_card *card){ int rc; __u16 temp; struct qeth_cmd_buffer *iob; QETH_DBF_TEXT(setup,2,"ulpsetup"); iob = qeth_wait_for_buffer(&card->write); memcpy(iob->data, ULP_SETUP, ULP_SETUP_SIZE); memcpy(QETH_ULP_SETUP_DEST_ADDR(iob->data), &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH); memcpy(QETH_ULP_SETUP_CONNECTION_TOKEN(iob->data), &card->token.ulp_connection_w, QETH_MPC_TOKEN_LENGTH); memcpy(QETH_ULP_SETUP_FILTER_TOKEN(iob->data), &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH); temp = __raw_devno_from_bus_id(CARD_DDEV_ID(card)); memcpy(QETH_ULP_SETUP_CUA(iob->data), &temp, 2); temp = (card->info.cula << 8) + card->info.unit_addr2; memcpy(QETH_ULP_SETUP_REAL_DEVADDR(iob->data), &temp, 2); rc = qeth_send_control_data(card, ULP_SETUP_SIZE, iob, qeth_ulp_setup_cb, NULL); return rc;}static inline intqeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error, unsigned int siga_error, const char *dbftext){ if (qdio_error || siga_error) { QETH_DBF_TEXT(trace, 2, dbftext); QETH_DBF_TEXT(qerr, 2, dbftext); QETH_DBF_TEXT_(qerr, 2, " F15=%02X", buf->element[15].flags & 0xff); QETH_DBF_TEXT_(qerr, 2, " F14=%02X", buf->element[14].flags & 0xff); QETH_DBF_TEXT_(qerr, 2, " qerr=%X", qdio_error); QETH_DBF_TEXT_(qerr, 2, " serr=%X", siga_error); return 1; } return 0;}static inline struct sk_buff *qeth_get_skb(unsigned int length, struct qeth_hdr *hdr){ struct sk_buff* skb; int add_len; add_len = 0; if (hdr->hdr.osn.id == QETH_HEADER_TYPE_OSN) add_len = sizeof(struct qeth_hdr);#ifdef CONFIG_QETH_VLAN else add_len = VLAN_HLEN;#endif skb = dev_alloc_skb(length + add_len); if (skb && add_len) skb_reserve(skb, add_len); return skb;}static inline struct sk_buff *qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, struct qdio_buffer_element **__element, int *__offset, struct qeth_hdr **hdr){ struct qdio_buffer_element *element = *__element; int offset = *__offset; struct sk_buff *skb = NULL; int skb_len; void *data_ptr; int data_len; QETH_DBF_TEXT(trace,6,"nextskb"); /* qeth_hdr must not cross element boundaries */ if (element->length < offset + sizeof(struct qeth_hdr)){ if (qeth_is_last_sbale(element)) return NULL; element++; offset = 0; if (element->length < sizeof(struct qeth_hdr)) return NULL; } *hdr = element->addr + offset; offset += sizeof(struct qeth_hdr); if (card->options.layer2) if (card->info.type == QETH_CARD_TYPE_OSN) skb_len = (*hdr)->hdr.osn.pdu_length; else skb_len = (*hdr)->hdr.l2.pkt_length; else skb_len = (*hdr)->hdr.l3.length; if (!skb_len) return NULL; if (card->options.fake_ll){ if(card->dev->type == ARPHRD_IEEE802_TR){ if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr))) goto no_mem; skb_reserve(skb,QETH_FAKE_LL_LEN_TR); } else { if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr))) goto no_mem; skb_reserve(skb,QETH_FAKE_LL_LEN_ETH); } } else if (!(skb = qeth_get_skb(skb_len, *hdr))) goto no_mem; data_ptr = element->addr + offset; while (skb_len) { data_len = min(skb_len, (int)(element->length - offset)); if (data_len) memcpy(skb_put(skb, data_len), data_ptr, data_len); skb_len -= data_len; if (skb_len){ if (qeth_is_last_sbale(element)){ QETH_DBF_TEXT(trace,4,"unexeob"); QETH_DBF_TEXT_(trace,4,"%s",CARD_BUS_ID(card)); QETH_DBF_TEXT(qerr,2,"unexeob"); QETH_DBF_TEXT_(qerr,2,"%s",CARD_BUS_ID(card)); QETH_DBF_HEX(misc,4,buffer,sizeof(*buffer)); dev_kfree_skb_any(skb); card->stats.rx_errors++; return NULL; } element++; offset = 0; data_ptr = element->addr; } else { offset += data_len; } } *__element = element; *__offset = offset; return skb;no_mem: if (net_ratelimit()){ PRINT_WARN("No memory for packet received on %s.\n", QETH_CARD_IFNAME(card)); QETH_DBF_TEXT(trace,2,"noskbmem"); QETH_DBF_TEXT_(trace,2,"%s",CARD_BUS_ID(card)); } card->stats.rx_dropped++; return NULL;}static inline __be16qeth_type_trans(struct sk_buff *skb, struct net_device *dev){ struct qeth_card *card; struct ethhdr *eth; QETH_DBF_TEXT(trace,6,"typtrans"); card = (struct qeth_card *)dev->priv;#ifdef CONFIG_TR if ((card->info.link_type == QETH_LINK_TYPE_HSTR) || (card->info.link_type == QETH_LINK_TYPE_LANE_TR)) return tr_type_trans(skb,dev);#endif /* CONFIG_TR */ skb->mac.raw = skb->data; skb_pull(skb, ETH_HLEN ); eth = eth_hdr(skb); if (*eth->h_dest & 1) { if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0) skb->pkt_type = PACKET_BROADCAST; else skb->pkt_type = PACKET_MULTICAST; } else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN)) skb->pkt_type = PACKET_OTHERHOST; if (ntohs(eth->h_proto) >= 1536) return eth->h_proto; if (*(unsigned short *) (skb->data) == 0xFFFF) return htons(ETH_P_802_3); return htons(ETH_P_802_2);}static inline voidqeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr){ struct trh_hdr *fake_hdr; struct trllc *fake_llc; struct iphdr *ip_hdr; QETH_DBF_TEXT(trace,5,"skbfktr"); skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_TR; /* this is a fake ethernet header */ fake_hdr = (struct trh_hdr *) skb->mac.raw; /* the destination MAC address */ switch (skb->pkt_type){ case PACKET_MULTICAST: switch (skb->protocol){#ifdef CONFIG_QETH_IPV6 case __constant_htons(ETH_P_IPV6): ndisc_mc_map((struct in6_addr *) skb->data + QETH_FAKE_LL_V6_ADDR_POS, fake_hdr->daddr, card->dev, 0); break;#endif /* CONFIG_QETH_IPV6 */ case __constant_htons(ETH_P_IP): ip_hdr = (struct iphdr *)skb->data; ip_tr_mc_map(ip_hdr->daddr, fake_hdr->daddr); break; default: memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN); } break; case PACKET_BROADCAST: memset(fake_hdr->daddr, 0xff, TR_ALEN); break; default: memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN); } /* the source MAC address */ if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR) memcpy(fake_hdr->saddr, &hdr->hdr.l3.dest_addr[2], TR_ALEN); else memset(fake_hdr->saddr, 0, TR_ALEN); fake_hdr->rcf=0; fake_llc = (struct trllc*)&(fake_hdr->rcf); fake_llc->dsap = EXTENDED_SAP; fake_llc->ssap = EXTENDED_SAP; fake_llc->llc = UI_CMD; fake_llc->protid[0] = 0; fake_llc->protid[1] = 0; fake_llc->protid[2] = 0; fake_llc->ethertype = ETH_P_IP;}static inline voidqeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr){ struct ethhdr *fake_hdr; struct iphdr *ip_hdr; QETH_DBF_TEXT(trace,5,"skbfketh"); skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_ETH; /* this is a fake ethernet header */ fake_hdr = (struct ethhdr *) skb->mac.raw; /* the destination MAC address */ switch (skb->pkt_type){ case PACKET_MULTICAST: switch (skb->protocol){#ifdef CONFIG_QETH_IPV6 case __constant_htons(ETH_P_IPV6): ndisc_mc_map((struct in6_addr *) skb->data + QETH_FAKE_LL_V6_ADDR_POS, fake_hdr->h_dest, card->dev, 0); break;#endif /* CONFIG_QETH_IPV6 */ case __constant_htons(ETH_P_IP): ip_hdr = (struct iphdr *)skb->data; ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest); break; default: memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN); } break; case PACKET_BROADCAST: memset(fake_hdr->h_dest, 0xff, ETH_ALEN); break; default: memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN); } /* the source MAC address */ if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR) memcpy(fake_hdr->h_source, &hdr->hdr.l3.dest_addr[2], ETH_ALEN); else memset(fake_hdr->h_source, 0, ETH_ALEN); /* the protocol */ fake_hdr->h_proto = skb->protocol;}static inline voidqeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr){ if (card->dev->type == ARPHRD_IEEE802_TR) qeth_rebuild_skb_fake_ll_tr(card, skb, hdr); else qeth_rebuild_skb_fake_ll_eth(card, skb, hdr);}static inline voidqeth_rebuild_skb_vlan(struct qeth_card
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -