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

📄 hamachi.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				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, bus_to_virt(desc->addr), pkt_len, 0);				skb_put(skb, pkt_len);#else				memcpy(skb_put(skb, pkt_len), bus_to_virt(desc->addr),pkt_len);#endif			} else {				char *temp = skb_put(skb = hmp->rx_skbuff[entry], pkt_len);				hmp->rx_skbuff[entry] = NULL;#ifndef final_version				/* Remove after testing. */				if (bus_to_virt(desc->addr) != temp)					printk(KERN_ERR "%s: Internal fault: The skbuff addresses "						   "do not match in hamachi_rx: %p vs. %p / %p.\n",						   dev->name, bus_to_virt(desc->addr),						   skb->head, temp);#else				(void) temp;#endif			}#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;		hmp->rx_head_desc = &hmp->rx_ring[entry];	}	/* Refill the Rx ring buffers. */	for (; hmp->cur_rx - hmp->dirty_rx > 0; hmp->dirty_rx++) {		struct sk_buff *skb;		entry = hmp->dirty_rx % RX_RING_SIZE;		if (hmp->rx_skbuff[entry] == NULL) {			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 */			hmp->rx_ring[entry].addr = virt_to_desc(skb->tail);		}		hmp->rx_ring[entry].status_n_length = cpu_to_le32(hmp->rx_buf_sz);		if (entry >= RX_RING_SIZE-1)			hmp->rx_ring[entry].status_n_length |=				cpu_to_le32(DescOwn | DescEndPacket | DescEndRing | DescIntr);		else			hmp->rx_ring[entry].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 = (struct hamachi_private *)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 = (struct hamachi_private *)dev->priv;	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)virt_to_bus(hmp->tx_ring));		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)virt_to_bus(hmp->rx_ring));		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*)bus_to_virt(hmp->rx_ring[i].addr) != 0x69) {					int j;					for (j = 0; j < 0x50; j++)						printk(" %4.4x",((u16*)le32desc_to_virt(hmp->rx_ring[i].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++) {		hmp->rx_ring[i].status_n_length = 0;		hmp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */		if (hmp->rx_skbuff[i]) {			dev_kfree_skb(hmp->rx_skbuff[i]);		}		hmp->rx_skbuff[i] = 0;	}	for (i = 0; i < TX_RING_SIZE; i++) {		if (hmp->tx_skbuff[i])			dev_kfree_skb(hmp->tx_skbuff[i]);		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 = (struct hamachi_private *)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);	}}#ifdef HAVE_PRIVATE_IOCTLstatic int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	long ioaddr = dev->base_addr;	u16 *data = (u16 *)&rq->ifr_data;	switch(cmd) {	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */		data[0] = ((struct hamachi_private *)dev->priv)->phys[0] & 0x1f;		/* Fall Through */	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);		return 0;	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */		/* 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[0] & 0x1f, data[1] & 0x1f, data[2]);		return 0;	case SIOCDEVPRIVATE+3: { /* set rx,tx intr params */		u32 *d = (u32 *)&rq->ifr_data;		/* Should add this check here or an ordinary user can do nasty		 * things. -KDU		 *		 * TODO: Shut down the Rx and Tx engines while doing this.		 */		if (!capable(CAP_NET_ADMIN))			return -EPERM;		writel(d[0], dev->base_addr + TxIntrCtrl);		writel(d[1], dev->base_addr + RxIntrCtrl);		printk(KERN_NOTICE "%s: tx %08x, rx %08x intr\n", dev->name,		  (u32) readl(dev->base_addr + TxIntrCtrl),		  (u32) readl(dev->base_addr + RxIntrCtrl));		return 0;	    }	default:		return -EOPNOTSUPP;	}}#endif  /* HAVE_PRIVATE_IOCTL */static void __exit hamachi_remove_one (struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata(pdev);	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */	if (dev) {		unregister_netdev(dev);		iounmap((char *)dev->base_addr);		kfree(dev);		pci_set_drvdata(pdev, NULL);	}}static struct pci_device_id hamachi_pci_tbl[] __initdata = {	{ 0x1318, 0x0911, PCI_ANY_ID, PCI_ANY_ID, },	{ 0, }};MODULE_DEVICE_TABLE(pci, hamachi_pci_tbl);static struct pci_driver hamachi_driver = {	name:		"hamachi",	id_table:	hamachi_pci_tbl,	probe:		hamachi_init_one,	remove:		hamachi_remove_one,};static int __init hamachi_init (void){	if (pci_register_driver(&hamachi_driver) > 0)		return 0;	pci_unregister_driver(&hamachi_driver);	return -ENODEV;}static void __exit hamachi_exit (void){	pci_unregister_driver(&hamachi_driver);}module_init(hamachi_init);module_exit(hamachi_exit);

⌨️ 快捷键说明

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