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

📄 8139too.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
		 RTL_R16 (RxBufAddr),		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));	tp->cur_rx = cur_rx;}static void rtl8139_weird_interrupt (struct net_device *dev,				     struct rtl8139_private *tp,				     void *ioaddr,				     int status, int link_changed){	DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n",		 dev->name, status);	assert (dev != NULL);	assert (tp != NULL);	assert (ioaddr != NULL);	/* Update the error count. */	tp->stats.rx_missed_errors += RTL_R32 (RxMissed);	RTL_W32 (RxMissed, 0);	if ((status & RxUnderrun) && link_changed &&	    (tp->drv_flags & HAS_LNK_CHNG)) {		/* Really link-change on new chips. */		int lpar = RTL_R16 (NWayLPAR);		int duplex = (lpar & LPA_100FULL) || (lpar & 0x01C0) == 0x0040				|| tp->mii.duplex_lock;		if (tp->mii.full_duplex != duplex) {			tp->mii.full_duplex = duplex;#if 0			RTL_W8 (Cfg9346, Cfg9346_Unlock);			RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20);			RTL_W8 (Cfg9346, Cfg9346_Lock);#endif		}		status &= ~RxUnderrun;	}	/* XXX along with rtl8139_rx_err, are we double-counting errors? */	if (status &	    (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))		tp->stats.rx_errors++;	if (status & PCSTimeout)		tp->stats.rx_length_errors++;	if (status & (RxUnderrun | RxFIFOOver))		tp->stats.rx_fifo_errors++;	if (status & PCIErr) {		u16 pci_cmd_status;		pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status);		pci_write_config_word (tp->pci_dev, PCI_STATUS, pci_cmd_status);		printk (KERN_ERR "%s: PCI Bus error %4.4x.\n",			dev->name, pci_cmd_status);	}}/* The interrupt handler does all of the Rx thread work and cleans up   after the Tx thread. */static void rtl8139_interrupt (int irq, void *dev_instance,			       struct pt_regs *regs){	struct net_device *dev = (struct net_device *) dev_instance;	struct rtl8139_private *tp = dev->priv;	int boguscnt = max_interrupt_work;	void *ioaddr = tp->mmio_addr;	int ackstat, status;	int link_changed = 0; /* avoid bogus "uninit" warning */	spin_lock (&tp->lock);	do {		status = RTL_R16 (IntrStatus);		/* h/w no longer present (hotplug?) or major error, bail */		if (status == 0xFFFF)			break;		if ((status &		     (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |		      RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0)			break;		/* Acknowledge all of the current interrupt sources ASAP, but		   an first get an additional status bit from CSCR. */		if (status & RxUnderrun)			link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;		/* The chip takes special action when we clear RxAckBits,		 * so we clear them later in rtl8139_rx_interrupt		 */		ackstat = status & ~(RxAckBits | TxErr);		RTL_W16 (IntrStatus, ackstat);		DPRINTK ("%s: interrupt  status=%#4.4x ackstat=%#4.4x new intstat=%#4.4x.\n",			 dev->name, ackstat, status, RTL_R16 (IntrStatus));		if (netif_running (dev) && (status & RxAckBits))			rtl8139_rx_interrupt (dev, tp, ioaddr);		/* Check uncommon events with one test. */		if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |		  	      RxFIFOOver | RxErr))			rtl8139_weird_interrupt (dev, tp, ioaddr,						 status, link_changed);		if (netif_running (dev) && (status & (TxOK | TxErr))) {			rtl8139_tx_interrupt (dev, tp, ioaddr);			if (status & TxErr)				RTL_W16 (IntrStatus, TxErr);		}		boguscnt--;	} while (boguscnt > 0);	if (boguscnt <= 0) {		printk (KERN_WARNING "%s: Too much work at interrupt, "			"IntrStatus=0x%4.4x.\n", dev->name, status);		/* Clear all interrupt sources. */		RTL_W16 (IntrStatus, 0xffff);	}	spin_unlock (&tp->lock);	DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n",		 dev->name, RTL_R16 (IntrStatus));}static int rtl8139_close (struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	void *ioaddr = tp->mmio_addr;	int ret = 0;	unsigned long flags;	netif_stop_queue (dev);	if (tp->thr_pid >= 0) {		tp->time_to_die = 1;		wmb();		ret = kill_proc (tp->thr_pid, SIGTERM, 1);		if (ret) {			printk (KERN_ERR "%s: unable to signal thread\n", dev->name);			return ret;		}		wait_for_completion (&tp->thr_exited);	}	DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n",			dev->name, RTL_R16 (IntrStatus));	spin_lock_irqsave (&tp->lock, flags);	/* Stop the chip's Tx and Rx DMA processes. */	RTL_W8 (ChipCmd, 0);	/* Disable interrupts by clearing the interrupt mask. */	RTL_W16 (IntrMask, 0);	/* Update the error counts. */	tp->stats.rx_missed_errors += RTL_R32 (RxMissed);	RTL_W32 (RxMissed, 0);	spin_unlock_irqrestore (&tp->lock, flags);	synchronize_irq ();	free_irq (dev->irq, dev);	rtl8139_tx_clear (tp);	pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,			    tp->rx_ring, tp->rx_ring_dma);	pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN,			    tp->tx_bufs, tp->tx_bufs_dma);	tp->rx_ring = NULL;	tp->tx_bufs = NULL;	/* Green! Put the chip in low-power mode. */	RTL_W8 (Cfg9346, Cfg9346_Unlock);	if (rtl_chip_info[tp->chipset].flags & HasHltClk)		RTL_W8 (HltClk, 'H');	/* 'R' would leave the clock running. */	return 0;}/* Get the ethtool Wake-on-LAN settings.  Assumes that wol points to   kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and   other threads or interrupts aren't messing with the 8139.  */static void netdev_get_wol (struct net_device *dev, struct ethtool_wolinfo *wol){	struct rtl8139_private *np = dev->priv;	void *ioaddr = np->mmio_addr;	if (rtl_chip_info[np->chipset].flags & HasLWake) {		u8 cfg3 = RTL_R8 (Config3);		u8 cfg5 = RTL_R8 (Config5);		wol->supported = WAKE_PHY | WAKE_MAGIC			| WAKE_UCAST | WAKE_MCAST | WAKE_BCAST;		wol->wolopts = 0;		if (cfg3 & Cfg3_LinkUp)			wol->wolopts |= WAKE_PHY;		if (cfg3 & Cfg3_Magic)			wol->wolopts |= WAKE_MAGIC;		/* (KON)FIXME: See how netdev_set_wol() handles the		   following constants.  */		if (cfg5 & Cfg5_UWF)			wol->wolopts |= WAKE_UCAST;		if (cfg5 & Cfg5_MWF)			wol->wolopts |= WAKE_MCAST;		if (cfg5 & Cfg5_BWF)			wol->wolopts |= WAKE_BCAST;	}}/* Set the ethtool Wake-on-LAN settings.  Return 0 or -errno.  Assumes   that wol points to kernel memory and other threads or interrupts   aren't messing with the 8139.  */static int netdev_set_wol (struct net_device *dev,			   const struct ethtool_wolinfo *wol){	struct rtl8139_private *np = dev->priv;	void *ioaddr = np->mmio_addr;	u32 support;	u8 cfg3, cfg5;	support = ((rtl_chip_info[np->chipset].flags & HasLWake)		   ? (WAKE_PHY | WAKE_MAGIC		      | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST)		   : 0);	if (wol->wolopts & ~support)		return -EINVAL;	cfg3 = RTL_R8 (Config3) & ~(Cfg3_LinkUp | Cfg3_Magic);	if (wol->wolopts & WAKE_PHY)		cfg3 |= Cfg3_LinkUp;	if (wol->wolopts & WAKE_MAGIC)		cfg3 |= Cfg3_Magic;	RTL_W8 (Cfg9346, Cfg9346_Unlock);	RTL_W8 (Config3, cfg3);	RTL_W8 (Cfg9346, Cfg9346_Lock);	cfg5 = RTL_R8 (Config5) & ~(Cfg5_UWF | Cfg5_MWF | Cfg5_BWF);	/* (KON)FIXME: These are untested.  We may have to set the	   CRC0, Wakeup0 and LSBCRC0 registers too, but I have no	   documentation.  */	if (wol->wolopts & WAKE_UCAST)		cfg5 |= Cfg5_UWF;	if (wol->wolopts & WAKE_MCAST)		cfg5 |= Cfg5_MWF;	if (wol->wolopts & WAKE_BCAST)		cfg5 |= Cfg5_BWF;	RTL_W8 (Config5, cfg5);	/* need not unlock via Cfg9346 */	return 0;}static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr){	struct rtl8139_private *np = dev->priv;	u32 ethcmd;	/* dev_ioctl() in ../../net/core/dev.c has already checked	   capable(CAP_NET_ADMIN), so don't bother with that here.  */	if (get_user(ethcmd, (u32 *)useraddr))		return -EFAULT;	switch (ethcmd) {	case ETHTOOL_GDRVINFO: {		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };		strcpy (info.driver, DRV_NAME);		strcpy (info.version, DRV_VERSION);		strcpy (info.bus_info, np->pci_dev->slot_name);		if (copy_to_user (useraddr, &info, sizeof (info)))			return -EFAULT;		return 0;	}	/* get settings */	case ETHTOOL_GSET: {		struct ethtool_cmd ecmd = { ETHTOOL_GSET };		spin_lock_irq(&np->lock);		mii_ethtool_gset(&np->mii, &ecmd);		spin_unlock_irq(&np->lock);		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))			return -EFAULT;		return 0;	}	/* set settings */	case ETHTOOL_SSET: {		int r;		struct ethtool_cmd ecmd;		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))			return -EFAULT;		spin_lock_irq(&np->lock);		r = mii_ethtool_sset(&np->mii, &ecmd);		spin_unlock_irq(&np->lock);		return r;	}	/* restart autonegotiation */	case ETHTOOL_NWAY_RST: {		return mii_nway_restart(&np->mii);	}	/* get link status */	case ETHTOOL_GLINK: {		struct ethtool_value edata = {ETHTOOL_GLINK};		edata.data = mii_link_ok(&np->mii);		if (copy_to_user(useraddr, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* get message-level */	case ETHTOOL_GMSGLVL: {		struct ethtool_value edata = {ETHTOOL_GMSGLVL};		edata.data = debug;		if (copy_to_user(useraddr, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* set message-level */	case ETHTOOL_SMSGLVL: {		struct ethtool_value edata;		if (copy_from_user(&edata, useraddr, sizeof(edata)))			return -EFAULT;		debug = edata.data;		return 0;	}	case ETHTOOL_GWOL:		{			struct ethtool_wolinfo wol = { ETHTOOL_GWOL };			spin_lock_irq (&np->lock);			netdev_get_wol (dev, &wol);			spin_unlock_irq (&np->lock);			if (copy_to_user (useraddr, &wol, sizeof (wol)))				return -EFAULT;			return 0;		}	case ETHTOOL_SWOL:		{			struct ethtool_wolinfo wol;			int rc;			if (copy_from_user (&wol, useraddr, sizeof (wol)))				return -EFAULT;			spin_lock_irq (&np->lock);			rc = netdev_set_wol (dev, &wol);			spin_unlock_irq (&np->lock);			return rc;		}	default:		break;	}	return -EOPNOTSUPP;}static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd){	struct rtl8139_private *tp = dev->priv;	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;	int rc = 0;	int phy = tp->phys[0] & 0x3f;	if (!netif_running(dev))		return -EINVAL;	if (cmd != SIOCETHTOOL) {		/* With SIOCETHTOOL, this would corrupt the pointer.  */		data->phy_id &= 0x1f;		data->reg_num &= 0x1f;	}	switch (cmd) {	case SIOCETHTOOL:		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);	case SIOCGMIIPHY:	/* Get the address of the PHY in use. */	case SIOCDEVPRIVATE:	/* binary compat, remove in 2.5 */		data->phy_id = phy;		/* Fall Through */	case SIOCGMIIREG:	/* Read the specified MII register. */	case SIOCDEVPRIVATE+1:	/* binary compat, remove in 2.5 */		data->val_out = mdio_read (dev, data->phy_id, data->reg_num);		break;	case SIOCSMIIREG:	/* Write the specified MII register */	case SIOCDEVPRIVATE+2:	/* binary compat, remove in 2.5 */		if (!capable (CAP_NET_ADMIN)) {			rc = -EPERM;			break;		}		if (data->phy_id == phy) {			u16 value = data->val_in;			switch (data->reg_num) {			case 0:				/* Check for autonegotiation on or reset. */				tp->medialock = (value & 0x9000) ? 0 : 1;				if (tp->medialock)					tp->mii.full_duplex = (value & 0x0100) ? 1 : 0;				break;			case 4: tp->mii.advertising = value; break;			}		}		mdio_write(dev, data->phy_id, data->reg_num, data->val_in);		break;	default:		rc = -EOPNOTSUPP;		break;	}	return rc;}static struct net_device_stats *rtl8139_get_stats (struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	void *ioaddr = tp->mmio_addr;	unsigned long flags;	if (netif_running(dev)) {		spin_lock_irqsave (&tp->lock, flags);		tp->stats.rx_missed_errors += RTL_R32 (RxMissed);		RTL_W32 (RxMissed, 0);		spin_unlock_irqrestore (&tp->lock, flags);	}	return &tp->stats;}/* Set or clear the multicast filter for this adaptor.   This routine is not state sensitive and need not be SMP locked. */static unsigned const ethernet_polynomial = 0x04c11db7U;static inline u32 ether_crc (int length, unsigned char *data){	int crc = -1;	while (--length >= 0) {		unsigned char current_octet = *data++;		int bit;		for (bit = 0; bit < 8; bit++, current_octet >>= 1)			crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ?			     ethernet_polynomial : 0);	}	return crc;}static void __set_rx_mode (struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	void *ioaddr = tp->mmio_addr;	u32 mc_filter[2];	/* Multicast hash filter */	int i, rx_mode;	u32 tmp;	DPRINTK ("%s:   rtl8139_set_rx_mode(%4.4x) done -- Rx config %8.8lx.\n",			dev->name, dev->flags, RTL_R32 (RxConfig));	/* Note: do not reorder, GCC is clever about common statements. */	if (dev->flags & IFF_PROMISC) {		/* Unconditionally log net taps. */		printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n",			dev->name);		rx_mode =		    AcceptBroadcast | A

⌨️ 快捷键说明

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