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

📄 via-rhine.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
	struct sk_buff *tx_skbuff[TX_RING_SIZE];	dma_addr_t tx_skbuff_dma[TX_RING_SIZE];	/* Tx bounce buffers */	unsigned char *tx_buf[TX_RING_SIZE];	unsigned char *tx_bufs;	dma_addr_t tx_bufs_dma;	struct pci_dev *pdev;	struct net_device_stats stats;	struct timer_list timer;	/* Media monitoring timer. */	spinlock_t lock;	/* Frequently used values: keep some adjacent for cache effect. */	int chip_id, drv_flags;	struct rx_desc *rx_head_desc;	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */	unsigned int cur_tx, dirty_tx;	unsigned int rx_buf_sz;				/* Based on MTU+slack. */	u16 chip_cmd;						/* Current setting for ChipCmd */	/* These values are keep track of the transceiver/media in use. */	unsigned int full_duplex:1;			/* Full-duplex operation requested. */	unsigned int duplex_lock:1;	unsigned int default_port:4;		/* Last dev->if_port value. */	u8 tx_thresh, rx_thresh;	/* MII transceiver section. */	u16 advertising;					/* NWay media advertisement */	unsigned char phys[MAX_MII_CNT];			/* MII device addresses. */	unsigned int mii_cnt;			/* number of MIIs found, but only the first one is used */	u16 mii_status;						/* last read MII status */	struct mii_if_info mii_if;};static int  mdio_read(struct net_device *dev, int phy_id, int location);static void mdio_write(struct net_device *dev, int phy_id, int location, int value);static int  via_rhine_open(struct net_device *dev);static void via_rhine_check_duplex(struct net_device *dev);static void via_rhine_timer(unsigned long data);static void via_rhine_tx_timeout(struct net_device *dev);static int  via_rhine_start_tx(struct sk_buff *skb, struct net_device *dev);static void via_rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);static void via_rhine_tx(struct net_device *dev);static void via_rhine_rx(struct net_device *dev);static void via_rhine_error(struct net_device *dev, int intr_status);static void via_rhine_set_rx_mode(struct net_device *dev);static struct net_device_stats *via_rhine_get_stats(struct net_device *dev);static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static int  via_rhine_close(struct net_device *dev);static inline void clear_tally_counters(long ioaddr);static void wait_for_reset(struct net_device *dev, char *name){	struct netdev_private *np = dev->priv;	long ioaddr = dev->base_addr;	int chip_id = np->chip_id;	int i;	/* 3043 may need long delay after reset (dlink) */	if (chip_id == VT3043 || chip_id == VT86C100A)		udelay(100);	i = 0;	do {		udelay(5);		i++;		if(i > 2000) {			printk(KERN_ERR "%s: reset did not complete in 10 ms.\n", name);			break;		}	} while(readw(ioaddr + ChipCmd) & CmdReset);	if (debug > 1)		printk(KERN_INFO "%s: reset finished after %d microseconds.\n",			   name, 5*i);}#ifdef USE_MEMstatic void __devinit enable_mmio(long ioaddr, int chip_id){	int n;	if (chip_id == VT3043 || chip_id == VT86C100A) {		/* More recent docs say that this bit is reserved ... */		n = inb(ioaddr + ConfigA) | 0x20;		outb(n, ioaddr + ConfigA);	} else if (chip_id == VT6102) {		n = inb(ioaddr + ConfigD) | 0x80;		outb(n, ioaddr + ConfigD);	}}#endifstatic void __devinit reload_eeprom(long ioaddr){	int i;	outb(0x20, ioaddr + MACRegEEcsr);	/* Typically 2 cycles to reload. */	for (i = 0; i < 150; i++)		if (! (inb(ioaddr + MACRegEEcsr) & 0x20))			break;}static int __devinit via_rhine_init_one (struct pci_dev *pdev,					 const struct pci_device_id *ent){	struct net_device *dev;	struct netdev_private *np;	int i, option;	int chip_id = (int) ent->driver_data;	static int card_idx = -1;	long ioaddr;	long memaddr;	int io_size;	int pci_flags;#ifdef USE_MEM	long ioaddr0;#endif	/* when built into the kernel, we only print version if device is found */#ifndef MODULE	static int printed_version;	if (!printed_version++)		printk(version);#endif	card_idx++;	option = card_idx < MAX_UNITS ? options[card_idx] : 0;	io_size = via_rhine_chip_info[chip_id].io_size;	pci_flags = via_rhine_chip_info[chip_id].pci_flags;	if (pci_enable_device (pdev))		goto err_out;	/* this should always be supported */	if (pci_set_dma_mask(pdev, 0xffffffff)) {		printk(KERN_ERR "32-bit PCI DMA addresses not supported by the card!?\n");		goto err_out;	}		/* sanity check */	if ((pci_resource_len (pdev, 0) < io_size) ||	    (pci_resource_len (pdev, 1) < io_size)) {		printk (KERN_ERR "Insufficient PCI resources, aborting\n");		goto err_out;	}	ioaddr = pci_resource_start (pdev, 0);	memaddr = pci_resource_start (pdev, 1);	if (pci_flags & PCI_USES_MASTER)		pci_set_master (pdev);	dev = alloc_etherdev(sizeof(*np));	if (dev == NULL) {		printk (KERN_ERR "init_ethernet failed for card #%d\n", card_idx);		goto err_out;	}	SET_MODULE_OWNER(dev);		if (pci_request_regions(pdev, shortname))		goto err_out_free_netdev;#ifdef USE_MEM	ioaddr0 = ioaddr;	enable_mmio(ioaddr0, chip_id);	ioaddr = (long) ioremap (memaddr, io_size);	if (!ioaddr) {		printk (KERN_ERR "ioremap failed for device %s, region 0x%X @ 0x%lX\n",				pdev->slot_name, io_size, memaddr);		goto err_out_free_res;	}	/* Check that selected MMIO registers match the PIO ones */	i = 0;	while (mmio_verify_registers[i]) {		int reg = mmio_verify_registers[i++];		unsigned char a = inb(ioaddr0+reg);		unsigned char b = readb(ioaddr+reg);		if (a != b) {			printk (KERN_ERR "MMIO do not match PIO [%02x] (%02x != %02x)\n",					reg, a, b);			goto err_out_unmap;		}	}#endif	/* D-Link provided reset code (with comment additions) */	if (via_rhine_chip_info[chip_id].drv_flags & HasWOL) {		unsigned char byOrgValue;		/* clear sticky bit before reset & read ethernet address */		byOrgValue = readb(ioaddr + StickyHW);		byOrgValue = byOrgValue & 0xFC;		writeb(byOrgValue, ioaddr + StickyHW);		/* (bits written are cleared?) */		/* disable force PME-enable */		writeb(0x80, ioaddr + WOLcgClr);		/* disable power-event config bit */		writeb(0xFF, ioaddr + WOLcrClr);		/* clear power status (undocumented in vt6102 docs?) */		writeb(0xFF, ioaddr + PwrcsrClr);	}	/* Reset the chip to erase previous misconfiguration. */	writew(CmdReset, ioaddr + ChipCmd);	dev->base_addr = ioaddr;	wait_for_reset(dev, shortname);	/* Reload the station address from the EEPROM. */#ifdef USE_IO	reload_eeprom(ioaddr);#else	reload_eeprom(ioaddr0);	/* Reloading from eeprom overwrites cfgA-D, so we must re-enable MMIO.	   If reload_eeprom() was done first this could be avoided, but it is	   not known if that still works with the "win98-reboot" problem. */	enable_mmio(ioaddr0, chip_id);#endif	for (i = 0; i < 6; i++)		dev->dev_addr[i] = readb(ioaddr + StationAddr + i);	if (!is_valid_ether_addr(dev->dev_addr)) {		printk(KERN_ERR "Invalid MAC address for card #%d\n", card_idx);		goto err_out_unmap;	}	if (chip_id == VT6102) {		/*		 * for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA		 * turned on.  it makes MAC receive magic packet		 * automatically. So, we turn it off. (D-Link)		 */		writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA);	}	dev->irq = pdev->irq;	np = dev->priv;	spin_lock_init (&np->lock);	np->chip_id = chip_id;	np->drv_flags = via_rhine_chip_info[chip_id].drv_flags;	np->pdev = pdev;	np->mii_if.dev = dev;	np->mii_if.mdio_read = mdio_read;	np->mii_if.mdio_write = mdio_write;	if (dev->mem_start)		option = dev->mem_start;	/* The lower four bits are the media type. */	if (option > 0) {		if (option & 0x200)			np->mii_if.full_duplex = 1;		np->default_port = option & 15;	}	if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)		np->mii_if.full_duplex = 1;	if (np->mii_if.full_duplex) {		printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation"			   " disabled.\n", dev->name);		np->mii_if.duplex_lock = 1;	}	/* The chip-specific entries in the device structure. */	dev->open = via_rhine_open;	dev->hard_start_xmit = via_rhine_start_tx;	dev->stop = via_rhine_close;	dev->get_stats = via_rhine_get_stats;	dev->set_multicast_list = via_rhine_set_rx_mode;	dev->do_ioctl = via_rhine_ioctl;	dev->tx_timeout = via_rhine_tx_timeout;	dev->watchdog_timeo = TX_TIMEOUT;	if (np->drv_flags & ReqTxAlign)		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;		i = register_netdev(dev);	if (i)		goto err_out_unmap;	printk(KERN_INFO "%s: %s at 0x%lx, ",		   dev->name, via_rhine_chip_info[chip_id].name,		   (pci_flags & PCI_USES_IO) ? ioaddr : memaddr);	for (i = 0; i < 5; i++)			printk("%2.2x:", dev->dev_addr[i]);	printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], pdev->irq);	pci_set_drvdata(pdev, dev);	if (np->drv_flags & CanHaveMII) {		int phy, phy_idx = 0;		np->phys[0] = 1;		/* Standard for this chip. */		for (phy = 1; phy < 32 && phy_idx < MAX_MII_CNT; phy++) {			int mii_status = mdio_read(dev, phy, 1);			if (mii_status != 0xffff  &&  mii_status != 0x0000) {				np->phys[phy_idx++] = phy;				np->mii_if.advertising = mdio_read(dev, phy, 4);				printk(KERN_INFO "%s: MII PHY found at address %d, status "					   "0x%4.4x advertising %4.4x Link %4.4x.\n",					   dev->name, phy, mii_status, np->mii_if.advertising,					   mdio_read(dev, phy, 5));				/* set IFF_RUNNING */				if (mii_status & MIILink)					netif_carrier_on(dev);				else					netif_carrier_off(dev);			}		}		np->mii_cnt = phy_idx;		np->mii_if.phy_id = np->phys[0];	}	/* Allow forcing the media type. */	if (option > 0) {		if (option & 0x220)			np->mii_if.full_duplex = 1;		np->default_port = option & 0x3ff;		if (np->default_port & 0x330) {			/* FIXME: shouldn't someone check this variable? */			/* np->medialock = 1; */			printk(KERN_INFO "  Forcing %dMbs %s-duplex operation.\n",				   (option & 0x300 ? 100 : 10),				   (option & 0x220 ? "full" : "half"));			if (np->mii_cnt)				mdio_write(dev, np->phys[0], 0,						   ((option & 0x300) ? 0x2000 : 0) |  /* 100mbps? */						   ((option & 0x220) ? 0x0100 : 0));  /* Full duplex? */		}	}	return 0;err_out_unmap:#ifdef USE_MEM	iounmap((void *)ioaddr);err_out_free_res:#endif	pci_release_regions(pdev);err_out_free_netdev:	kfree (dev);err_out:	return -ENODEV;}static int alloc_ring(struct net_device* dev){	struct netdev_private *np = dev->priv;	void *ring;	dma_addr_t ring_dma;	ring = pci_alloc_consistent(np->pdev, 				    RX_RING_SIZE * sizeof(struct rx_desc) +				    TX_RING_SIZE * sizeof(struct tx_desc),				    &ring_dma);	if (!ring) {		printk(KERN_ERR "Could not allocate DMA memory.\n");		return -ENOMEM;	}	if (np->drv_flags & ReqTxAlign) {		np->tx_bufs = pci_alloc_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE,								   &np->tx_bufs_dma);		if (np->tx_bufs == NULL) {			pci_free_consistent(np->pdev, 				    RX_RING_SIZE * sizeof(struct rx_desc) +				    TX_RING_SIZE * sizeof(struct tx_desc),				    ring, ring_dma);			return -ENOMEM;		}	}	np->rx_ring = ring;	np->tx_ring = ring + RX_RING_SIZE * sizeof(struct rx_desc);	np->rx_ring_dma = ring_dma;	np->tx_ring_dma = ring_dma + RX_RING_SIZE * sizeof(struct rx_desc);	return 0;}void free_ring(struct net_device* dev){	struct netdev_private *np = dev->priv;	pci_free_consistent(np->pdev, 			    RX_RING_SIZE * sizeof(struct rx_desc) +			    TX_RING_SIZE * sizeof(struct tx_desc),			    np->rx_ring, np->rx_ring_dma);	np->tx_ring = NULL;	if (np->tx_bufs)		pci_free_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE,							np->tx_bufs, np->tx_bufs_dma);	np->tx_bufs = NULL;}static void alloc_rbufs(struct net_device *dev){	struct netdev_private *np = dev->priv;	dma_addr_t next;	int i;	np->dirty_rx = np->cur_rx = 0;	np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);	np->rx_head_desc = &np->rx_ring[0];	next = np->rx_ring_dma;		/* Init the ring entries */	for (i = 0; i < RX_RING_SIZE; i++) {		np->rx_ring[i].rx_status = 0;		np->rx_ring[i].desc_length = cpu_to_le32(np->rx_buf_sz);		next += sizeof(struct rx_desc);		np->rx_ring[i].next_desc = cpu_to_le32(next);		np->rx_skbuff[i] = 0;	}	/* Mark the last entry as wrapping the ring. */	np->rx_ring[i-1].next_desc = cpu_to_le32(np->rx_ring_dma);	/* Fill in the Rx buffers.  Handle allocation failure gracefully. */	for (i = 0; i < RX_RING_SIZE; i++) {		struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);		np->rx_skbuff[i] = skb;		if (skb == NULL)			break;		skb->dev = dev;                 /* Mark as being used by this device. */		np->rx_skbuff_dma[i] =			pci_map_single(np->pdev, skb->tail, np->rx_buf_sz,						   PCI_DMA_FROMDEVICE);		np->rx_ring[i].addr = cpu_to_le32(np->rx_skbuff_dma[i]);		np->rx_ring[i].rx_status = cpu_to_le32(DescOwn);	}	np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);}static void free_rbufs(struct net_device* dev){	struct netdev_private *np = dev->priv;	int i;	/* Free all the skbuffs in the Rx queue. */	for (i = 0; i < RX_RING_SIZE; i++) {		np->rx_ring[i].rx_status = 0;

⌨️ 快捷键说明

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