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

📄 winbond-840.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* Reset the chip to erase previous misconfiguration.	   No hold time required! */	writel(0x00000001, ioaddr + PCIBusCfg);	dev->base_addr = ioaddr;	dev->irq = irq;	np = dev->priv;	np->pci_dev = pdev;	np->chip_id = chip_idx;	np->drv_flags = pci_id_tbl[chip_idx].drv_flags;	spin_lock_init(&np->lock);	np->mii_if.dev = dev;	np->mii_if.mdio_read = mdio_read;	np->mii_if.mdio_write = mdio_write;		pci_set_drvdata(pdev, dev);	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;		if (option & 15)			printk(KERN_INFO "%s: ignoring user supplied media type %d",				dev->name, option & 15);	}	if (find_cnt < MAX_UNITS  &&  full_duplex[find_cnt] > 0)		np->mii_if.full_duplex = 1;	if (np->mii_if.full_duplex)		np->mii_if.force_media = 1;	/* The chip-specific entries in the device structure. */	dev->open = &netdev_open;	dev->hard_start_xmit = &start_tx;	dev->stop = &netdev_close;	dev->get_stats = &get_stats;	dev->set_multicast_list = &set_rx_mode;	dev->do_ioctl = &netdev_ioctl;	dev->ethtool_ops = &netdev_ethtool_ops;	dev->tx_timeout = &tx_timeout;	dev->watchdog_timeo = TX_TIMEOUT;	i = register_netdev(dev);	if (i)		goto err_out_cleardev;	printk(KERN_INFO "%s: %s at 0x%lx, ",		   dev->name, pci_id_tbl[chip_idx].name, 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 & CanHaveMII) {		int phy, phy_idx = 0;		for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {			int mii_status = mdio_read(dev, phy, MII_BMSR);			if (mii_status != 0xffff  &&  mii_status != 0x0000) {				np->phys[phy_idx++] = phy;				np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);				np->mii = (mdio_read(dev, phy, MII_PHYSID1) << 16)+						mdio_read(dev, phy, MII_PHYSID2);				printk(KERN_INFO "%s: MII PHY %8.8xh found at address %d, status "					   "0x%4.4x advertising %4.4x.\n",					   dev->name, np->mii, phy, mii_status, np->mii_if.advertising);			}		}		np->mii_cnt = phy_idx;		np->mii_if.phy_id = np->phys[0];		if (phy_idx == 0) {				printk(KERN_WARNING "%s: MII PHY not found -- this device may "					   "not operate correctly.\n", dev->name);		}	}	find_cnt++;	return 0;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_netdev:	free_netdev (dev);	return -ENODEV;}/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces.  These are   often serial bit streams generated by the host processor.   The example below is for the common 93c46 EEPROM, 64 16 bit words. *//* Delay between EEPROM clock transitions.   No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need   a delay.  Note that pre-2.0.34 kernels had a cache-alignment bug that   made udelay() unreliable.   The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is   depricated.*/#define eeprom_delay(ee_addr)	readl(ee_addr)enum EEPROM_Ctrl_Bits {	EE_ShiftClk=0x02, EE_Write0=0x801, EE_Write1=0x805,	EE_ChipSelect=0x801, EE_DataIn=0x08,};/* The EEPROM commands include the alway-set leading bit. */enum EEPROM_Cmds {	EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),};static int eeprom_read(long addr, int location){	int i;	int retval = 0;	long ee_addr = addr + EECtrl;	int read_cmd = location | EE_ReadCmd;	writel(EE_ChipSelect, ee_addr);	/* Shift the read command bits out. */	for (i = 10; i >= 0; i--) {		short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;		writel(dataval, ee_addr);		eeprom_delay(ee_addr);		writel(dataval | EE_ShiftClk, ee_addr);		eeprom_delay(ee_addr);	}	writel(EE_ChipSelect, ee_addr);	eeprom_delay(ee_addr);	for (i = 16; i > 0; i--) {		writel(EE_ChipSelect | EE_ShiftClk, ee_addr);		eeprom_delay(ee_addr);		retval = (retval << 1) | ((readl(ee_addr) & EE_DataIn) ? 1 : 0);		writel(EE_ChipSelect, ee_addr);		eeprom_delay(ee_addr);	}	/* Terminate the EEPROM access. */	writel(0, ee_addr);	return retval;}/*  MII transceiver control section.	Read and write the MII registers using software-generated serial	MDIO protocol.  See the MII specifications or DP83840A data sheet	for details.	The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually	met by back-to-back 33Mhz PCI cycles. */#define mdio_delay(mdio_addr) readl(mdio_addr)/* Set iff a MII transceiver on any interface requires mdio preamble.   This only set with older transceivers, so the extra   code size of a per-interface flag is not worthwhile. */static char mii_preamble_required = 1;#define MDIO_WRITE0 (MDIO_EnbOutput)#define MDIO_WRITE1 (MDIO_DataOut | MDIO_EnbOutput)/* Generate the preamble required for initial synchronization and   a few older transceivers. */static void mdio_sync(long mdio_addr){	int bits = 32;	/* Establish sync by sending at least 32 logic ones. */	while (--bits >= 0) {		writel(MDIO_WRITE1, mdio_addr);		mdio_delay(mdio_addr);		writel(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);		mdio_delay(mdio_addr);	}}static int mdio_read(struct net_device *dev, int phy_id, int location){	long mdio_addr = dev->base_addr + MIICtrl;	int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;	int i, retval = 0;	if (mii_preamble_required)		mdio_sync(mdio_addr);	/* Shift the read command bits out. */	for (i = 15; i >= 0; i--) {		int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;		writel(dataval, mdio_addr);		mdio_delay(mdio_addr);		writel(dataval | MDIO_ShiftClk, mdio_addr);		mdio_delay(mdio_addr);	}	/* Read the two transition, 16 data, and wire-idle bits. */	for (i = 20; i > 0; i--) {		writel(MDIO_EnbIn, mdio_addr);		mdio_delay(mdio_addr);		retval = (retval << 1) | ((readl(mdio_addr) & MDIO_DataIn) ? 1 : 0);		writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);		mdio_delay(mdio_addr);	}	return (retval>>1) & 0xffff;}static void mdio_write(struct net_device *dev, int phy_id, int location, int value){	struct netdev_private *np = dev->priv;	long mdio_addr = dev->base_addr + MIICtrl;	int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;	int i;	if (location == 4  &&  phy_id == np->phys[0])		np->mii_if.advertising = value;	if (mii_preamble_required)		mdio_sync(mdio_addr);	/* Shift the command bits out. */	for (i = 31; i >= 0; i--) {		int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;		writel(dataval, mdio_addr);		mdio_delay(mdio_addr);		writel(dataval | MDIO_ShiftClk, mdio_addr);		mdio_delay(mdio_addr);	}	/* Clear out extra bits. */	for (i = 2; i > 0; i--) {		writel(MDIO_EnbIn, mdio_addr);		mdio_delay(mdio_addr);		writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);		mdio_delay(mdio_addr);	}	return;}static int netdev_open(struct net_device *dev){	struct netdev_private *np = dev->priv;	long ioaddr = dev->base_addr;	int i;	writel(0x00000001, ioaddr + PCIBusCfg);		/* Reset */	netif_device_detach(dev);	i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);	if (i)		goto out_err;	if (debug > 1)		printk(KERN_DEBUG "%s: w89c840_open() irq %d.\n",			   dev->name, dev->irq);	if((i=alloc_ringdesc(dev)))		goto out_err;	spin_lock_irq(&np->lock);	netif_device_attach(dev);	init_registers(dev);	spin_unlock_irq(&np->lock);	netif_start_queue(dev);	if (debug > 2)		printk(KERN_DEBUG "%s: Done netdev_open().\n", dev->name);	/* Set the timer to check for link beat. */	init_timer(&np->timer);	np->timer.expires = jiffies + 1*HZ;	np->timer.data = (unsigned long)dev;	np->timer.function = &netdev_timer;				/* timer handler */	add_timer(&np->timer);	return 0;out_err:	netif_device_attach(dev);	return i;}#define MII_DAVICOM_DM9101	0x0181b800static int update_link(struct net_device *dev){	struct netdev_private *np = dev->priv;	int duplex, fasteth, result, mii_reg;	/* BSMR */	mii_reg = mdio_read(dev, np->phys[0], MII_BMSR);	if (mii_reg == 0xffff)		return np->csr6;	/* reread: the link status bit is sticky */	mii_reg = mdio_read(dev, np->phys[0], MII_BMSR);	if (!(mii_reg & 0x4)) {		if (netif_carrier_ok(dev)) {			if (debug)				printk(KERN_INFO "%s: MII #%d reports no link. Disabling watchdog.\n",					dev->name, np->phys[0]);			netif_carrier_off(dev);		}		return np->csr6;	}	if (!netif_carrier_ok(dev)) {		if (debug)			printk(KERN_INFO "%s: MII #%d link is back. Enabling watchdog.\n",				dev->name, np->phys[0]);		netif_carrier_on(dev);	}		if ((np->mii & ~0xf) == MII_DAVICOM_DM9101) {		/* If the link partner doesn't support autonegotiation		 * the MII detects it's abilities with the "parallel detection".		 * Some MIIs update the LPA register to the result of the parallel		 * detection, some don't.		 * The Davicom PHY [at least 0181b800] doesn't.		 * Instead bit 9 and 13 of the BMCR are updated to the result		 * of the negotiation..		 */		mii_reg = mdio_read(dev, np->phys[0], MII_BMCR);		duplex = mii_reg & BMCR_FULLDPLX;		fasteth = mii_reg & BMCR_SPEED100;	} else {		int negotiated;		mii_reg	= mdio_read(dev, np->phys[0], MII_LPA);		negotiated = mii_reg & np->mii_if.advertising;		duplex = (negotiated & LPA_100FULL) || ((negotiated & 0x02C0) == LPA_10FULL);		fasteth = negotiated & 0x380;	}	duplex |= np->mii_if.force_media;	/* remove fastether and fullduplex */	result = np->csr6 & ~0x20000200;	if (duplex)		result |= 0x200;	if (fasteth)		result |= 0x20000000;	if (result != np->csr6 && debug)		printk(KERN_INFO "%s: Setting %dMBit-%s-duplex based on MII#%d\n",				 dev->name, fasteth ? 100 : 10, 			   	duplex ? "full" : "half", np->phys[0]);	return result;}#define RXTX_TIMEOUT	2000static inline void update_csr6(struct net_device *dev, int new){	struct netdev_private *np = dev->priv;	long ioaddr = dev->base_addr;	int limit = RXTX_TIMEOUT;	if (!netif_device_present(dev))		new = 0;	if (new==np->csr6)		return;	/* stop both Tx and Rx processes */	writel(np->csr6 & ~0x2002, ioaddr + NetworkConfig);	/* wait until they have really stopped */	for (;;) {		int csr5 = readl(ioaddr + IntrStatus);		int t;		t = (csr5 >> 17) & 0x07;		if (t==0||t==1) {			/* rx stopped */			t = (csr5 >> 20) & 0x07;			if (t==0||t==1)				break;		}		limit--;		if(!limit) {			printk(KERN_INFO "%s: couldn't stop rxtx, IntrStatus %xh.\n",					dev->name, csr5);			break;		}		udelay(1);	}	np->csr6 = new;	/* and restart them with the new configuration */	writel(np->csr6, ioaddr + NetworkConfig);	if (new & 0x200)		np->mii_if.full_duplex = 1;}static void netdev_timer(unsigned long data){	struct net_device *dev = (struct net_device *)data;	struct netdev_private *np = dev->priv;	long ioaddr = dev->base_addr;	if (debug > 2)		printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x "			   "config %8.8x.\n",			   dev->name, (int)readl(ioaddr + IntrStatus),			   (int)readl(ioaddr + NetworkConfig));	spin_lock_irq(&np->lock);	update_csr6(dev, update_link(dev));	spin_unlock_irq(&np->lock);	np->timer.expires = jiffies + 10*HZ;	add_timer(&np->timer);}static void init_rxtx_rings(struct net_device *dev){	struct netdev_private *np = dev->priv;	int i;	np->rx_head_desc = &np->rx_ring[0];	np->tx_ring = (struct w840_tx_desc*)&np->rx_ring[RX_RING_SIZE];	/* Initial all Rx descriptors. */	for (i = 0; i < RX_RING_SIZE; i++) {		np->rx_ring[i].length = np->rx_buf_sz;		np->rx_ring[i].status = 0;		np->rx_skbuff[i] = NULL;	}	/* Mark the last entry as wrapping the ring. */	np->rx_ring[i-1].length |= DescEndRing;	/* 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_addr[i] = pci_map_single(np->pci_dev,skb->tail,

⌨️ 快捷键说明

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