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

📄 hamachi.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (hamachi_debug > 2)				printk(KERN_DEBUG "  hamachi_rx() Rx error was %8.8x.\n",					   frame_status);			hmp->stats.rx_errors++;			if (frame_status & 0x00600000) hmp->stats.rx_length_errors++;			if (frame_status & 0x00080000) hmp->stats.rx_frame_errors++;			if (frame_status & 0x00100000) hmp->stats.rx_crc_errors++;			if (frame_status < 0) hmp->stats.rx_dropped++;		} else {			struct sk_buff *skb;			/* Omit CRC */			u16 pkt_len = (frame_status & 0x07ff) - 4;	#ifdef RX_CHECKSUM			u32 pfck = *(u32 *) &buf_addr[data_size - 8];#endif#ifndef final_version			if (hamachi_debug > 4)				printk(KERN_DEBUG "  hamachi_rx() normal Rx pkt length %d"					   " of %d, bogus_cnt %d.\n",					   pkt_len, data_size, boguscnt);			if (hamachi_debug > 5)				printk(KERN_DEBUG"%s:  rx status %8.8x %8.8x %8.8x %8.8x %8.8x.\n",					   dev->name,					   *(s32*)&(buf_addr[data_size - 20]),					   *(s32*)&(buf_addr[data_size - 16]),					   *(s32*)&(buf_addr[data_size - 12]),					   *(s32*)&(buf_addr[data_size - 8]),					   *(s32*)&(buf_addr[data_size - 4]));#endif			/* Check if the packet is long enough to accept without copying			   to a minimally-sized skbuff. */			if (pkt_len < rx_copybreak				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {#ifdef RX_CHECKSUM				printk(KERN_ERR "%s: rx_copybreak non-zero "				  "not good with RX_CHECKSUM\n", dev->name);#endif				skb->dev = dev;				skb_reserve(skb, 2);	/* 16 byte align the IP header */				/* Call copy + cksum if available. */#if 1 || USE_IP_COPYSUM				eth_copy_and_sum(skb, 					hmp->rx_skbuff[entry]->data, pkt_len, 0);				skb_put(skb, pkt_len);#else				memcpy(skb_put(skb, pkt_len), hmp->rx_ring_dma					+ entry*sizeof(*desc), pkt_len);#endif			} else {				pci_unmap_single(hmp->pci_dev, 					hmp->rx_ring[entry].addr, 					hmp->rx_buf_sz, PCI_DMA_FROMDEVICE);				skb_put(skb = hmp->rx_skbuff[entry], pkt_len);				hmp->rx_skbuff[entry] = NULL;			}#ifdef TX_CHECKSUM			/* account for extra TX hard_header bytes */			skb->protocol = hamachi_eth_type_trans(skb, dev);#else			skb->protocol = eth_type_trans(skb, dev);#endif#ifdef RX_CHECKSUM			/* TCP or UDP on ipv4, DIX encoding */			if (pfck>>24 == 0x91 || pfck>>24 == 0x51) {				struct iphdr *ih = (struct iphdr *) skb->data;				/* Check that IP packet is at least 46 bytes, otherwise,				 * there may be pad bytes included in the hardware checksum.				 * This wouldn't happen if everyone padded with 0.				 */				if (ntohs(ih->tot_len) >= 46){					/* don't worry about frags */					if (!(ih->frag_off & __constant_htons(IP_MF|IP_OFFSET))) {						u32 inv = *(u32 *) &buf_addr[data_size - 16];						u32 *p = (u32 *) &buf_addr[data_size - 20];						register u32 crc, p_r, p_r1;						if (inv & 4) {							inv &= ~4;							--p;						}						p_r = *p;						p_r1 = *(p-1);						switch (inv) {							case 0:									crc = (p_r & 0xffff) + (p_r >> 16);								break;							case 1:									crc = (p_r >> 16) + (p_r & 0xffff)									+ (p_r1 >> 16 & 0xff00); 								break;							case 2:									crc = p_r + (p_r1 >> 16); 								break;							case 3:									crc = p_r + (p_r1 & 0xff00) + (p_r1 >> 16); 								break;							default:	/*NOTREACHED*/ crc = 0;						}						if (crc & 0xffff0000) {							crc &= 0xffff;							++crc;						}						/* tcp/udp will add in pseudo */						skb->csum = ntohs(pfck & 0xffff);						if (skb->csum > crc)							skb->csum -= crc;						else							skb->csum += (~crc & 0xffff);						/*						* could do the pseudo myself and return						* CHECKSUM_UNNECESSARY						*/						skb->ip_summed = CHECKSUM_HW;					}				}				}#endif  /* RX_CHECKSUM */			netif_rx(skb);			dev->last_rx = jiffies;			hmp->stats.rx_packets++;		}		entry = (++hmp->cur_rx) % RX_RING_SIZE;	}	/* Refill the Rx ring buffers. */	for (; hmp->cur_rx - hmp->dirty_rx > 0; hmp->dirty_rx++) {		struct hamachi_desc *desc;		entry = hmp->dirty_rx % RX_RING_SIZE;		desc = &(hmp->rx_ring[entry]);		if (hmp->rx_skbuff[entry] == NULL) {			struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz);			hmp->rx_skbuff[entry] = skb;			if (skb == NULL)				break;		/* Better luck next round. */			skb->dev = dev;		/* Mark as being used by this device. */			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */                	desc->addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, 				skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));		}		desc->status_n_length = cpu_to_le32(hmp->rx_buf_sz);		if (entry >= RX_RING_SIZE-1)			desc->status_n_length |= cpu_to_le32(DescOwn | 				DescEndPacket | DescEndRing | DescIntr);		else			desc->status_n_length |= cpu_to_le32(DescOwn | 				DescEndPacket | DescIntr);	}	/* Restart Rx engine if stopped. */	/* If we don't need to check status, don't. -KDU */	if (readw(dev->base_addr + RxStatus) & 0x0002)		writew(0x0001, dev->base_addr + RxCmd);	return 0;}/* This is more properly named "uncommon interrupt events", as it covers more   than just errors. */static void hamachi_error(struct net_device *dev, int intr_status){	long ioaddr = dev->base_addr;	struct hamachi_private *hmp = dev->priv;	if (intr_status & (LinkChange|NegotiationChange)) {		if (hamachi_debug > 1)			printk(KERN_INFO "%s: Link changed: AutoNegotiation Ctrl"				   " %4.4x, Status %4.4x %4.4x Intr status %4.4x.\n",				   dev->name, readw(ioaddr + 0x0E0), readw(ioaddr + 0x0E2),				   readw(ioaddr + ANLinkPartnerAbility),				   readl(ioaddr + IntrStatus));		if (readw(ioaddr + ANStatus) & 0x20)			writeb(0x01, ioaddr + LEDCtrl);		else			writeb(0x03, ioaddr + LEDCtrl);	}	if (intr_status & StatsMax) {		hamachi_get_stats(dev);		/* Read the overflow bits to clear. */		readl(ioaddr + 0x370);		readl(ioaddr + 0x3F0);	}	if ((intr_status & ~(LinkChange|StatsMax|NegotiationChange|IntrRxDone|IntrTxDone))		&& hamachi_debug)		printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n",			   dev->name, intr_status);	/* Hmmmmm, it's not clear how to recover from PCI faults. */	if (intr_status & (IntrTxPCIErr | IntrTxPCIFault))		hmp->stats.tx_fifo_errors++;	if (intr_status & (IntrRxPCIErr | IntrRxPCIFault))		hmp->stats.rx_fifo_errors++;}static int hamachi_close(struct net_device *dev){	long ioaddr = dev->base_addr;	struct hamachi_private *hmp = dev->priv;	struct sk_buff *skb;	int i;	netif_stop_queue(dev);	if (hamachi_debug > 1) {		printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n",			   dev->name, readw(ioaddr + TxStatus),			   readw(ioaddr + RxStatus), readl(ioaddr + IntrStatus));		printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d,  Rx %d / %d.\n",			   dev->name, hmp->cur_tx, hmp->dirty_tx, hmp->cur_rx, hmp->dirty_rx);	}	/* Disable interrupts by clearing the interrupt mask. */	writel(0x0000, ioaddr + InterruptEnable);	/* Stop the chip's Tx and Rx processes. */	writel(2, ioaddr + RxCmd);	writew(2, ioaddr + TxCmd);#ifdef __i386__	if (hamachi_debug > 2) {		printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",			   (int)hmp->tx_ring_dma);		for (i = 0; i < TX_RING_SIZE; i++)			printk(" %c #%d desc. %8.8x %8.8x.\n",				   readl(ioaddr + TxCurPtr) == (long)&hmp->tx_ring[i] ? '>' : ' ',				   i, hmp->tx_ring[i].status_n_length, hmp->tx_ring[i].addr);		printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",			   (int)hmp->rx_ring_dma);		for (i = 0; i < RX_RING_SIZE; i++) {			printk(KERN_DEBUG " %c #%d desc. %4.4x %8.8x\n",				   readl(ioaddr + RxCurPtr) == (long)&hmp->rx_ring[i] ? '>' : ' ',				   i, hmp->rx_ring[i].status_n_length, hmp->rx_ring[i].addr);			if (hamachi_debug > 6) {				if (*(u8*)hmp->rx_skbuff[i]->tail != 0x69) {					u16 *addr = (u16 *)						hmp->rx_skbuff[i]->tail;					int j;					for (j = 0; j < 0x50; j++)						printk(" %4.4x", addr[j]);					printk("\n");				}			}		}	}#endif /* __i386__ debugging only */	free_irq(dev->irq, dev);	del_timer_sync(&hmp->timer);	/* Free all the skbuffs in the Rx queue. */	for (i = 0; i < RX_RING_SIZE; i++) {		skb = hmp->rx_skbuff[i];		hmp->rx_ring[i].status_n_length = 0;		hmp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */		if (skb) {			pci_unmap_single(hmp->pci_dev, 				hmp->rx_ring[i].addr, hmp->rx_buf_sz, 				PCI_DMA_FROMDEVICE);			dev_kfree_skb(skb);			hmp->rx_skbuff[i] = 0;		}	}	for (i = 0; i < TX_RING_SIZE; i++) {		skb = hmp->tx_skbuff[i];		if (skb) {			pci_unmap_single(hmp->pci_dev, 				hmp->tx_ring[i].addr, skb->len, 				PCI_DMA_TODEVICE);			dev_kfree_skb(skb);			hmp->tx_skbuff[i] = 0;		}	}	writeb(0x00, ioaddr + LEDCtrl);	return 0;}static struct net_device_stats *hamachi_get_stats(struct net_device *dev){	long ioaddr = dev->base_addr;	struct hamachi_private *hmp = dev->priv;	/* We should lock this segment of code for SMP eventually, although	   the vulnerability window is very small and statistics are	   non-critical. */        /* Ok, what goes here?  This appears to be stuck at 21 packets           according to ifconfig.  It does get incremented in hamachi_tx(),           so I think I'll comment it out here and see if better things           happen.        */ 	/* hmp->stats.tx_packets	= readl(ioaddr + 0x000); */	hmp->stats.rx_bytes = readl(ioaddr + 0x330); /* Total Uni+Brd+Multi */	hmp->stats.tx_bytes = readl(ioaddr + 0x3B0); /* Total Uni+Brd+Multi */	hmp->stats.multicast		= readl(ioaddr + 0x320); /* Multicast Rx */	hmp->stats.rx_length_errors	= readl(ioaddr + 0x368); /* Over+Undersized */	hmp->stats.rx_over_errors	= readl(ioaddr + 0x35C); /* Jabber */	hmp->stats.rx_crc_errors	= readl(ioaddr + 0x360); /* Jabber */	hmp->stats.rx_frame_errors	= readl(ioaddr + 0x364); /* Symbol Errs */	hmp->stats.rx_missed_errors	= readl(ioaddr + 0x36C); /* Dropped */	return &hmp->stats;}static void set_rx_mode(struct net_device *dev){	long ioaddr = dev->base_addr;	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */		/* Unconditionally log net taps. */		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);		writew(0x000F, ioaddr + AddrMode);	} else if ((dev->mc_count > 63)  ||  (dev->flags & IFF_ALLMULTI)) {		/* Too many to match, or accept all multicasts. */		writew(0x000B, ioaddr + AddrMode);	} else if (dev->mc_count > 0) { /* Must use the CAM filter. */		struct dev_mc_list *mclist;		int i;		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;			 i++, mclist = mclist->next) {			writel(*(u32*)(mclist->dmi_addr), ioaddr + 0x100 + i*8);			writel(0x20000 | (*(u16*)&mclist->dmi_addr[4]),				   ioaddr + 0x104 + i*8);		}		/* Clear remaining entries. */		for (; i < 64; i++)			writel(0, ioaddr + 0x104 + i*8);		writew(0x0003, ioaddr + AddrMode);	} else {					/* Normal, unicast/broadcast-only mode. */		writew(0x0001, ioaddr + AddrMode);	}}static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr){	struct hamachi_private *hmp = dev->priv;	u32 ethcmd;			if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))		return -EFAULT;        switch (ethcmd) {        case ETHTOOL_GDRVINFO: {		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};		strcpy(info.driver, DRV_NAME);		strcpy(info.version, DRV_VERSION);		strcpy(info.bus_info, hmp->pci_dev->slot_name);		if (copy_to_user(useraddr, &info, sizeof(info)))			return -EFAULT;		return 0;	}        }		return -EOPNOTSUPP;}static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	long ioaddr = dev->base_addr;	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;	switch(cmd) {	case SIOCETHTOOL:		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */		data->phy_id = ((struct hamachi_private *)dev->priv)->phys[0] & 0x1f;		/* Fall Through */	case SIOCGMIIREG:		/* Read MII PHY register. */	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */		data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f);		return 0;	case SIOCSMIIREG:		/* Write MII PHY register. */	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */		/* TODO: Check the sequencing of this.  Might need to stop and		 * restart Rx and Tx engines. -KDU		 */		if (!capable(CAP_NET_ADMIN))			return -EPERM;		mdio_write(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f, data-

⌨️ 快捷键说明

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