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

📄 yellowfin.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* MII transceiver section. */	int mii_cnt;						/* MII device addresses. */	u16 advertising;					/* NWay media advertisement */	unsigned char phys[MII_CNT];		/* MII device addresses, only first one used */	spinlock_t lock;};static int read_eeprom(long ioaddr, int location);static int mdio_read(long ioaddr, int phy_id, int location);static void mdio_write(long ioaddr, int phy_id, int location, int value);static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static int yellowfin_open(struct net_device *dev);static void yellowfin_timer(unsigned long data);static void yellowfin_tx_timeout(struct net_device *dev);static void yellowfin_init_ring(struct net_device *dev);static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev);static void yellowfin_interrupt(int irq, void *dev_instance, struct pt_regs *regs);static int yellowfin_rx(struct net_device *dev);static void yellowfin_error(struct net_device *dev, int intr_status);static int yellowfin_close(struct net_device *dev);static struct net_device_stats *yellowfin_get_stats(struct net_device *dev);static void set_rx_mode(struct net_device *dev);static int __devinit yellowfin_init_one(struct pci_dev *pdev,					const struct pci_device_id *ent){	struct net_device *dev;	struct yellowfin_private *np;	int irq;	int chip_idx = ent->driver_data;	static int find_cnt;	long ioaddr, real_ioaddr;	int i, option = find_cnt < MAX_UNITS ? options[find_cnt] : 0;	int drv_flags = pci_id_tbl[chip_idx].drv_flags;        void *ring_space;        dma_addr_t ring_dma;	/* 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	i = pci_enable_device(pdev);	if (i) return i;	dev = alloc_etherdev(sizeof(*np));	if (!dev) {		printk (KERN_ERR PFX "cannot allocate ethernet device\n");		return -ENOMEM;	}	SET_MODULE_OWNER(dev);	np = dev->priv;	if (pci_request_regions(pdev, dev->name))		goto err_out_free_netdev;	pci_set_master (pdev);#ifdef USE_IO_OPS	real_ioaddr = ioaddr = pci_resource_start (pdev, 0);#else	real_ioaddr = ioaddr = pci_resource_start (pdev, 1);	ioaddr = (long) ioremap(ioaddr, YELLOWFIN_SIZE);	if (!ioaddr)		goto err_out_free_res;#endif	irq = pdev->irq;	if (drv_flags & DontUseEeprom)		for (i = 0; i < 6; i++)			dev->dev_addr[i] = inb(ioaddr + StnAddr + i);	else {		int ee_offset = (read_eeprom(ioaddr, 6) == 0xff ? 0x100 : 0);		for (i = 0; i < 6; i++)			dev->dev_addr[i] = read_eeprom(ioaddr, ee_offset + i);	}	/* Reset the chip. */	outl(0x80000000, ioaddr + DMACtrl);	dev->base_addr = ioaddr;	dev->irq = irq;	pci_set_drvdata(pdev, dev);	spin_lock_init(&np->lock);	np->pci_dev = pdev;	np->chip_id = chip_idx;	np->drv_flags = drv_flags;	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);	if (!ring_space)		goto err_out_cleardev;	np->tx_ring = (struct yellowfin_desc *)ring_space;	np->tx_ring_dma = ring_dma;	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);	if (!ring_space)		goto err_out_unmap_tx;	np->rx_ring = (struct yellowfin_desc *)ring_space;	np->rx_ring_dma = ring_dma;	ring_space = pci_alloc_consistent(pdev, STATUS_TOTAL_SIZE, &ring_dma);	if (!ring_space)		goto err_out_unmap_rx;	np->tx_status = (struct tx_status_words *)ring_space;	np->tx_status_dma = ring_dma;	if (dev->mem_start)		option = dev->mem_start;	/* The lower four bits are the media type. */	if (option > 0) {		if (option & 0x200)			np->full_duplex = 1;		np->default_port = option & 15;		if (np->default_port)			np->medialock = 1;	}	if (find_cnt < MAX_UNITS  &&  full_duplex[find_cnt] > 0)		np->full_duplex = 1;	if (np->full_duplex)		np->duplex_lock = 1;	/* The Yellowfin-specific entries in the device structure. */	dev->open = &yellowfin_open;	dev->hard_start_xmit = &yellowfin_start_xmit;	dev->stop = &yellowfin_close;	dev->get_stats = &yellowfin_get_stats;	dev->set_multicast_list = &set_rx_mode;	dev->do_ioctl = &netdev_ioctl;	dev->tx_timeout = yellowfin_tx_timeout;	dev->watchdog_timeo = TX_TIMEOUT;	if (mtu)		dev->mtu = mtu;	i = register_netdev(dev);	if (i)		goto err_out_unmap_status;	printk(KERN_INFO "%s: %s type %8x at 0x%lx, ",		   dev->name, pci_id_tbl[chip_idx].name, inl(ioaddr + ChipRev), ioaddr);	for (i = 0; i < 5; i++)			printk("%2.2x:", dev->dev_addr[i]);	printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);	if (np->drv_flags & HasMII) {		int phy, phy_idx = 0;		for (phy = 0; phy < 32 && phy_idx < MII_CNT; phy++) {			int mii_status = mdio_read(ioaddr, phy, 1);			if (mii_status != 0xffff  &&  mii_status != 0x0000) {				np->phys[phy_idx++] = phy;				np->advertising = mdio_read(ioaddr, phy, 4);				printk(KERN_INFO "%s: MII PHY found at address %d, status "					   "0x%4.4x advertising %4.4x.\n",					   dev->name, phy, mii_status, np->advertising);			}		}		np->mii_cnt = phy_idx;	}	find_cnt++;		return 0;err_out_unmap_status:        pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, 		np->tx_status_dma);err_out_unmap_rx:        pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);err_out_unmap_tx:        pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);err_out_cleardev:	pci_set_drvdata(pdev, NULL);#ifndef USE_IO_OPS	iounmap((void *)ioaddr);err_out_free_res:#endif	pci_release_regions(pdev);err_out_free_netdev:	kfree (dev);	return -ENODEV;}static int __devinit read_eeprom(long ioaddr, int location){	int bogus_cnt = 10000;		/* Typical 33Mhz: 1050 ticks */	outb(location, ioaddr + EEAddr);	outb(0x30 | ((location >> 8) & 7), ioaddr + EECtrl);	while ((inb(ioaddr + EEStatus) & 0x80)  &&  --bogus_cnt > 0)		;	return inb(ioaddr + EERead);}/* MII Managemen Data I/O accesses.   These routines assume the MDIO controller is idle, and do not exit until   the command is finished. */static int mdio_read(long ioaddr, int phy_id, int location){	int i;	outw((phy_id<<8) + location, ioaddr + MII_Addr);	outw(1, ioaddr + MII_Cmd);	for (i = 10000; i >= 0; i--)		if ((inw(ioaddr + MII_Status) & 1) == 0)			break;	return inw(ioaddr + MII_Rd_Data);}static void mdio_write(long ioaddr, int phy_id, int location, int value){	int i;	outw((phy_id<<8) + location, ioaddr + MII_Addr);	outw(value, ioaddr + MII_Wr_Data);	/* Wait for the command to finish. */	for (i = 10000; i >= 0; i--)		if ((inw(ioaddr + MII_Status) & 1) == 0)			break;	return;}static int yellowfin_open(struct net_device *dev){	struct yellowfin_private *yp = dev->priv;	long ioaddr = dev->base_addr;	int i;	/* Reset the chip. */	outl(0x80000000, ioaddr + DMACtrl);	i = request_irq(dev->irq, &yellowfin_interrupt, SA_SHIRQ, dev->name, dev);	if (i) return i;	if (yellowfin_debug > 1)		printk(KERN_DEBUG "%s: yellowfin_open() irq %d.\n",			   dev->name, dev->irq);	yellowfin_init_ring(dev);	outl(yp->rx_ring_dma, ioaddr + RxPtr);	outl(yp->tx_ring_dma, ioaddr + TxPtr);	for (i = 0; i < 6; i++)		outb(dev->dev_addr[i], ioaddr + StnAddr + i);	/* Set up various condition 'select' registers.	   There are no options here. */	outl(0x00800080, ioaddr + TxIntrSel); 	/* Interrupt on Tx abort */	outl(0x00800080, ioaddr + TxBranchSel);	/* Branch on Tx abort */	outl(0x00400040, ioaddr + TxWaitSel); 	/* Wait on Tx status */	outl(0x00400040, ioaddr + RxIntrSel);	/* Interrupt on Rx done */	outl(0x00400040, ioaddr + RxBranchSel);	/* Branch on Rx error */	outl(0x00400040, ioaddr + RxWaitSel);	/* Wait on Rx done */	/* Initialize other registers: with so many this eventually this will	   converted to an offset/value list. */	outl(dma_ctrl, ioaddr + DMACtrl);	outw(fifo_cfg, ioaddr + FIFOcfg);	/* Enable automatic generation of flow control frames, period 0xffff. */	outl(0x0030FFFF, ioaddr + FlowCtrl);	yp->tx_threshold = 32;	outl(yp->tx_threshold, ioaddr + TxThreshold);	if (dev->if_port == 0)		dev->if_port = yp->default_port;	netif_start_queue(dev);	/* Setting the Rx mode will start the Rx process. */	if (yp->drv_flags & IsGigabit) {		/* We are always in full-duplex mode with gigabit! */		yp->full_duplex = 1;		outw(0x01CF, ioaddr + Cnfg);	} else {		outw(0x0018, ioaddr + FrameGap0); /* 0060/4060 for non-MII 10baseT */		outw(0x1018, ioaddr + FrameGap1);		outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);	}	set_rx_mode(dev);	/* Enable interrupts by setting the interrupt mask. */	outw(0x81ff, ioaddr + IntrEnb);			/* See enum intr_status_bits */	outw(0x0000, ioaddr + EventStatus);		/* Clear non-interrupting events */	outl(0x80008000, ioaddr + RxCtrl);		/* Start Rx and Tx channels. */	outl(0x80008000, ioaddr + TxCtrl);	if (yellowfin_debug > 2) {		printk(KERN_DEBUG "%s: Done yellowfin_open().\n",			   dev->name);	}	/* Set the timer to check for link beat. */	init_timer(&yp->timer);	yp->timer.expires = jiffies + 3*HZ;	yp->timer.data = (unsigned long)dev;	yp->timer.function = &yellowfin_timer;				/* timer handler */	add_timer(&yp->timer);	return 0;}static void yellowfin_timer(unsigned long data){	struct net_device *dev = (struct net_device *)data;	struct yellowfin_private *yp = dev->priv;	long ioaddr = dev->base_addr;	int next_tick = 60*HZ;	if (yellowfin_debug > 3) {		printk(KERN_DEBUG "%s: Yellowfin timer tick, status %8.8x.\n",			   dev->name, inw(ioaddr + IntrStatus));	}	if (yp->mii_cnt) {		int bmsr = mdio_read(ioaddr, yp->phys[0], MII_BMSR);		int lpa = mdio_read(ioaddr, yp->phys[0], MII_LPA);		int negotiated = lpa & yp->advertising;		if (yellowfin_debug > 1)			printk(KERN_DEBUG "%s: MII #%d status register is %4.4x, "				   "link partner capability %4.4x.\n",				   dev->name, yp->phys[0], bmsr, lpa);		yp->full_duplex = mii_duplex(yp->duplex_lock, negotiated);					outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);		if (bmsr & BMSR_LSTATUS)			next_tick = 60*HZ;		else			next_tick = 3*HZ;	}	yp->timer.expires = jiffies + next_tick;	add_timer(&yp->timer);}static void yellowfin_tx_timeout(struct net_device *dev){	struct yellowfin_private *yp = dev->priv;	long ioaddr = dev->base_addr;	printk(KERN_WARNING "%s: Yellowfin transmit timed out at %d/%d Tx "		   "status %4.4x, Rx status %4.4x, resetting...\n",		   dev->name, yp->cur_tx, yp->dirty_tx,		   inl(ioaddr + TxStatus), inl(ioaddr + RxStatus));	/* Note: these should be KERN_DEBUG. */	if (yellowfin_debug) {		int i;		printk(KERN_WARNING "  Rx ring %p: ", yp->rx_ring);		for (i = 0; i < RX_RING_SIZE; i++)			printk(" %8.8x", yp->rx_ring[i].result_status);		printk("\n"KERN_WARNING"  Tx ring %p: ", yp->tx_ring);		for (i = 0; i < TX_RING_SIZE; i++)			printk(" %4.4x /%8.8x", yp->tx_status[i].tx_errs,				   yp->tx_ring[i].result_status);		printk("\n");	}	/* If the hardware is found to hang regularly, we will update the code	   to reinitialize the chip here. */	dev->if_port = 0;	/* Wake the potentially-idle transmit channel. */	outl(0x10001000, dev->base_addr + TxCtrl);	if (yp->cur_tx - yp->dirty_tx < TX_QUEUE_SIZE)		netif_wake_queue (dev);		/* Typical path */	dev->trans_start = jiffies;	yp->stats.tx_errors++;}/* Initialize the Rx and Tx rings, along with various 'dev' bits. */static void yellowfin_init_ring(struct net_device *dev)

⌨️ 快捷键说明

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