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

📄 8139too.c

📁 rtl8139网卡
💻 C
📖 第 1 页 / 共 5 页
字号:
	assert (ioaddr != NULL);	addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;	for (i = 0; i < 3; i++)		((u16 *) (dev->dev_addr))[i] =		    le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);	/* The Rtl8139-specific entries in the device structure. */	dev->open = rtl8139_open;	dev->hard_start_xmit = rtl8139_start_xmit;	dev->poll = rtl8139_poll;	dev->weight = 64;	dev->stop = rtl8139_close;	dev->get_stats = rtl8139_get_stats;	dev->set_multicast_list = rtl8139_set_rx_mode;	dev->do_ioctl = netdev_ioctl;	dev->ethtool_ops = &rtl8139_ethtool_ops;	dev->tx_timeout = rtl8139_tx_timeout;	dev->watchdog_timeo = TX_TIMEOUT;#ifdef CONFIG_NET_POLL_CONTROLLER	dev->poll_controller = rtl8139_poll_controller;#endif	/* note: the hardware is not capable of sg/csum/highdma, however	 * through the use of skb_copy_and_csum_dev we enable these	 * features	 */	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA;	dev->irq = pdev->irq;	/* tp zeroed and aligned in alloc_etherdev */	tp = netdev_priv(dev);	/* note: tp->chipset set in rtl8139_init_board */	tp->drv_flags = board_info[ent->driver_data].hw_flags;	tp->mmio_addr = ioaddr;	tp->msg_enable =		(debug < 0 ? RTL8139_DEF_MSG_ENABLE : ((1 << debug) - 1));	spin_lock_init (&tp->lock);	spin_lock_init (&tp->rx_lock);	INIT_DELAYED_WORK(&tp->thread, rtl8139_thread);	tp->mii.dev = dev;	tp->mii.mdio_read = mdio_read;	tp->mii.mdio_write = mdio_write;	tp->mii.phy_id_mask = 0x3f;	tp->mii.reg_num_mask = 0x1f;	/* dev is fully set up and ready to use now */	DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);	i = register_netdev (dev);	if (i) goto err_out;	pci_set_drvdata (pdev, dev);	printk (KERN_INFO "%s: %s at 0x%lx, "		"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "		"IRQ %d\n",		dev->name,		board_info[ent->driver_data].name,		dev->base_addr,		dev->dev_addr[0], dev->dev_addr[1],		dev->dev_addr[2], dev->dev_addr[3],		dev->dev_addr[4], dev->dev_addr[5],		dev->irq);	printk (KERN_DEBUG "%s:  Identified 8139 chip type '%s'\n",		dev->name, rtl_chip_info[tp->chipset].name);	/* Find the connected MII xcvrs.	   Doing this in open() would allow detecting external xcvrs later, but	   takes too much time. */#ifdef CONFIG_8139TOO_8129	if (tp->drv_flags & HAS_MII_XCVR) {		int phy, phy_idx = 0;		for (phy = 0; phy < 32 && phy_idx < sizeof(tp->phys); phy++) {			int mii_status = mdio_read(dev, phy, 1);			if (mii_status != 0xffff  &&  mii_status != 0x0000) {				u16 advertising = mdio_read(dev, phy, 4);				tp->phys[phy_idx++] = phy;				printk(KERN_INFO "%s: MII transceiver %d status 0x%4.4x "					   "advertising %4.4x.\n",					   dev->name, phy, mii_status, advertising);			}		}		if (phy_idx == 0) {			printk(KERN_INFO "%s: No MII transceivers found!  Assuming SYM "				   "transceiver.\n",				   dev->name);			tp->phys[0] = 32;		}	} else#endif		tp->phys[0] = 32;	tp->mii.phy_id = tp->phys[0];	/* The lower four bits are the media type. */	option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];	if (option > 0) {		tp->mii.full_duplex = (option & 0x210) ? 1 : 0;		tp->default_port = option & 0xFF;		if (tp->default_port)			tp->mii.force_media = 1;	}	if (board_idx < MAX_UNITS  &&  full_duplex[board_idx] > 0)		tp->mii.full_duplex = full_duplex[board_idx];	if (tp->mii.full_duplex) {		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);		/* Changing the MII-advertised media because might prevent		   re-connection. */		tp->mii.force_media = 1;	}	if (tp->default_port) {		printk(KERN_INFO "  Forcing %dMbps %s-duplex operation.\n",			   (option & 0x20 ? 100 : 10),			   (option & 0x10 ? "full" : "half"));		mdio_write(dev, tp->phys[0], 0,				   ((option & 0x20) ? 0x2000 : 0) | 	/* 100Mbps? */				   ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */	}	/* Put the chip into low-power mode. */	if (rtl_chip_info[tp->chipset].flags & HasHltClk)		RTL_W8 (HltClk, 'H');	/* 'R' would leave the clock running. */	return 0;err_out:	__rtl8139_cleanup_dev (dev);	pci_disable_device (pdev);	return i;}static void __devexit rtl8139_remove_one (struct pci_dev *pdev){	struct net_device *dev = pci_get_drvdata (pdev);	assert (dev != NULL);	flush_scheduled_work();	unregister_netdev (dev);	__rtl8139_cleanup_dev (dev);	pci_disable_device (pdev);}/* Serial EEPROM section. *//*  EEPROM_Ctrl bits. */#define EE_SHIFT_CLK	0x04	/* EEPROM shift clock. */#define EE_CS			0x08	/* EEPROM chip select. */#define EE_DATA_WRITE	0x02	/* EEPROM chip data in. */#define EE_WRITE_0		0x00#define EE_WRITE_1		0x02#define EE_DATA_READ	0x01	/* EEPROM chip data out. */#define EE_ENB			(0x80 | EE_CS)/* Delay between EEPROM clock transitions.   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this. */#define eeprom_delay()	(void)RTL_R32(Cfg9346)/* The EEPROM commands include the alway-set leading bit. */#define EE_WRITE_CMD	(5)#define EE_READ_CMD		(6)#define EE_ERASE_CMD	(7)static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len){	int i;	unsigned retval = 0;	int read_cmd = location | (EE_READ_CMD << addr_len);	RTL_W8 (Cfg9346, EE_ENB & ~EE_CS);	RTL_W8 (Cfg9346, EE_ENB);	eeprom_delay ();	/* Shift the read command bits out. */	for (i = 4 + addr_len; i >= 0; i--) {		int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;		RTL_W8 (Cfg9346, EE_ENB | dataval);		eeprom_delay ();		RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK);		eeprom_delay ();	}	RTL_W8 (Cfg9346, EE_ENB);	eeprom_delay ();	for (i = 16; i > 0; i--) {		RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK);		eeprom_delay ();		retval =		    (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 :				     0);		RTL_W8 (Cfg9346, EE_ENB);		eeprom_delay ();	}	/* Terminate the EEPROM access. */	RTL_W8 (Cfg9346, ~EE_CS);	eeprom_delay ();	return retval;}/* MII serial management: mostly bogus for now. *//* Read and write the MII management registers using software-generated   serial MDIO protocol.   The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually   met by back-to-back PCI I/O cycles, but we insert a delay to avoid   "overclocking" issues. */#define MDIO_DIR		0x80#define MDIO_DATA_OUT	0x04#define MDIO_DATA_IN	0x02#define MDIO_CLK		0x01#define MDIO_WRITE0 (MDIO_DIR)#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)#define mdio_delay()	RTL_R8(Config4)static const char mii_2_8139_map[8] = {	BasicModeCtrl,	BasicModeStatus,	0,	0,	NWayAdvert,	NWayLPAR,	NWayExpansion,	0};#ifdef CONFIG_8139TOO_8129/* Syncronize the MII management interface by shifting 32 one bits out. */static void mdio_sync (void __iomem *ioaddr){	int i;	for (i = 32; i >= 0; i--) {		RTL_W8 (Config4, MDIO_WRITE1);		mdio_delay ();		RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK);		mdio_delay ();	}}#endifstatic int mdio_read (struct net_device *dev, int phy_id, int location){	struct rtl8139_private *tp = netdev_priv(dev);	int retval = 0;#ifdef CONFIG_8139TOO_8129	void __iomem *ioaddr = tp->mmio_addr;	int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;	int i;#endif	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */		void __iomem *ioaddr = tp->mmio_addr;		return location < 8 && mii_2_8139_map[location] ?		    RTL_R16 (mii_2_8139_map[location]) : 0;	}#ifdef CONFIG_8139TOO_8129	mdio_sync (ioaddr);	/* Shift the read command bits out. */	for (i = 15; i >= 0; i--) {		int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;		RTL_W8 (Config4, MDIO_DIR | dataval);		mdio_delay ();		RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK);		mdio_delay ();	}	/* Read the two transition, 16 data, and wire-idle bits. */	for (i = 19; i > 0; i--) {		RTL_W8 (Config4, 0);		mdio_delay ();		retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0);		RTL_W8 (Config4, MDIO_CLK);		mdio_delay ();	}#endif	return (retval >> 1) & 0xffff;}static void mdio_write (struct net_device *dev, int phy_id, int location,			int value){	struct rtl8139_private *tp = netdev_priv(dev);#ifdef CONFIG_8139TOO_8129	void __iomem *ioaddr = tp->mmio_addr;	int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;	int i;#endif	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */		void __iomem *ioaddr = tp->mmio_addr;		if (location == 0) {			RTL_W8 (Cfg9346, Cfg9346_Unlock);			RTL_W16 (BasicModeCtrl, value);			RTL_W8 (Cfg9346, Cfg9346_Lock);		} else if (location < 8 && mii_2_8139_map[location])			RTL_W16 (mii_2_8139_map[location], value);		return;	}#ifdef CONFIG_8139TOO_8129	mdio_sync (ioaddr);	/* Shift the command bits out. */	for (i = 31; i >= 0; i--) {		int dataval =		    (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;		RTL_W8 (Config4, dataval);		mdio_delay ();		RTL_W8 (Config4, dataval | MDIO_CLK);		mdio_delay ();	}	/* Clear out extra bits. */	for (i = 2; i > 0; i--) {		RTL_W8 (Config4, 0);		mdio_delay ();		RTL_W8 (Config4, MDIO_CLK);		mdio_delay ();	}#endif}static int rtl8139_open (struct net_device *dev){	struct rtl8139_private *tp = netdev_priv(dev);	int retval;	void __iomem *ioaddr = tp->mmio_addr;	retval = request_irq (dev->irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev);	if (retval)		return retval;	tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN,					   &tp->tx_bufs_dma);	tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN,					   &tp->rx_ring_dma);	if (tp->tx_bufs == NULL || tp->rx_ring == NULL) {		free_irq(dev->irq, dev);		if (tp->tx_bufs)			pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN,					    tp->tx_bufs, tp->tx_bufs_dma);		if (tp->rx_ring)			pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,					    tp->rx_ring, tp->rx_ring_dma);		return -ENOMEM;	}	tp->mii.full_duplex = tp->mii.force_media;	tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;	rtl8139_init_ring (dev);	rtl8139_hw_start (dev);	netif_start_queue (dev);	if (netif_msg_ifup(tp))		printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#llx IRQ %d"			" GP Pins %2.2x %s-duplex.\n", dev->name,			(unsigned long long)pci_resource_start (tp->pci_dev, 1),			dev->irq, RTL_R8 (MediaStatus),			tp->mii.full_duplex ? "full" : "half");	rtl8139_start_thread(tp);	return 0;}static void rtl_check_media (struct net_device *dev, unsigned int init_media){	struct rtl8139_private *tp = netdev_priv(dev);	if (tp->phys[0] >= 0) {		mii_check_media(&tp->mii, netif_msg_link(tp), init_media);	}}/* Start the hardware at open or resume. */static void rtl8139_hw_start (struct net_device *dev){	struct rtl8139_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	u32 i;	u8 tmp;	/* Bring old chips out of low-power mode. */	if (rtl_chip_info[tp->chipset].flags & HasHltClk)		RTL_W8 (HltClk, 'R');	rtl8139_chip_reset (ioaddr);	/* unlock Config[01234] and BMCR register writes */	RTL_W8_F (Cfg9346, Cfg9346_Unlock);	/* Restore our idea of the MAC address. */	RTL_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));	RTL_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));	/* Must enable Tx/Rx before setting transfer thresholds! */	RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);	tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys;	RTL_W32 (RxConfig, tp->rx_config);	RTL_W32 (TxConfig, rtl8139_tx_config);	tp->cur_rx = 0;	rtl_check_media (dev, 1);	if (tp->chipset >= CH_8139B) {		/* Disable magic packet scanning, which is enabled		 * when PM is enabled in Config1.  It can be reenabled		 * via ETHTOOL_SWOL if desired.  */		RTL_W8 (Config3, RTL_R8 (Config3) & ~Cfg3_Magic);	}	DPRINTK("init buffer addresses\n");	/* Lock Config[01234] and BMCR register writes */	RTL_W8 (Cfg9346, Cfg9346_Lock);	/* init Rx ring buffer DMA address */	RTL_W32_F (RxBuf, tp->rx_ring_dma);	/* init Tx buffer DMA addresses */	for (i = 0; i < NUM_TX_DESC; i++)		RTL_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs));	RTL_W32 (RxMissed, 0);	rtl8139_set_rx_mode (dev);	/* no early-rx interrupts */	RTL_W16 (MultiIntr, RTL_R16 (MultiIntr) & MultiIntrClear);	/* make sure RxTx has started */	tmp = RTL_R8 (ChipCmd);	if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb)))		RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);	/* Enable all known interrupts by setting the interrupt mask. */	RTL_W16 (IntrMask, rtl8139_intr_mask);}/* Initialize the Rx and Tx rings, along with various 'dev' bits. */static void rtl8139_init_ring (struct net_device *dev){	struct rtl8139_private *tp = netdev_priv(dev);	int i;	tp->cur_rx = 0;	tp->cur_tx = 0;	tp->dirty_tx = 0;	for (i = 0; i < NUM_TX_DESC; i++)		tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];}/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */static int next_tick = 3 * HZ;#ifndef CONFIG_8139TOO_TUNE_TWISTERstatic inline void rtl8139_tune_twister (struct net_device *dev,				  struct rtl8139_private *tp) {}#else

⌨️ 快捷键说明

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