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

📄 qeth_main.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		  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 + -