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

📄 8139too.c

📁 rtl8139网卡
💻 C
📖 第 1 页 / 共 5 页
字号:
	DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x,"		 " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx,		 RTL_R16 (RxBufAddr),		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));	while (netif_running(dev) && received < budget	       && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {		u32 ring_offset = cur_rx % RX_BUF_LEN;		u32 rx_status;		unsigned int pkt_size;		struct sk_buff *skb;		rmb();		/* read size+status of next frame from DMA ring buffer */		rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));		rx_size = rx_status >> 16;		pkt_size = rx_size - 4;		if (netif_msg_rx_status(tp))			printk(KERN_DEBUG "%s:  rtl8139_rx() status %4.4x, size %4.4x,"				" cur %4.4x.\n", dev->name, rx_status,			 rx_size, cur_rx);#if RTL8139_DEBUG > 2		{			int i;			DPRINTK ("%s: Frame contents ", dev->name);			for (i = 0; i < 70; i++)				printk (" %2.2x",					rx_ring[ring_offset + i]);			printk (".\n");		}#endif		/* Packet copy from FIFO still in progress.		 * Theoretically, this should never happen		 * since EarlyRx is disabled.		 */		if (unlikely(rx_size == 0xfff0)) {			if (!tp->fifo_copy_timeout)				tp->fifo_copy_timeout = jiffies + 2;			else if (time_after(jiffies, tp->fifo_copy_timeout)) {				DPRINTK ("%s: hung FIFO. Reset.", dev->name);				rx_size = 0;				goto no_early_rx;			}			if (netif_msg_intr(tp)) {				printk(KERN_DEBUG "%s: fifo copy in progress.",				       dev->name);			}			tp->xstats.early_rx++;			break;		}no_early_rx:		tp->fifo_copy_timeout = 0;		/* If Rx err or invalid rx_size/rx_status received		 * (which happens if we get lost in the ring),		 * Rx process gets reset, so we abort any further		 * Rx processing.		 */		if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||			     (rx_size < 8) ||			     (!(rx_status & RxStatusOK)))) {			rtl8139_rx_err (rx_status, dev, tp, ioaddr);			received = -1;			goto out;		}		/* Malloc up new buffer, compatible with net-2e. */		/* Omit the four octet CRC from the length. */		skb = dev_alloc_skb (pkt_size + 2);		if (likely(skb)) {			skb_reserve (skb, 2);	/* 16 byte align the IP fields. */#if RX_BUF_IDX == 3			wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);#else			eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);#endif			skb_put (skb, pkt_size);			skb->protocol = eth_type_trans (skb, dev);			dev->last_rx = jiffies;			tp->stats.rx_bytes += pkt_size;			tp->stats.rx_packets++;			netif_receive_skb (skb);		} else {			if (net_ratelimit())				printk (KERN_WARNING					"%s: Memory squeeze, dropping packet.\n",					dev->name);			tp->stats.rx_dropped++;		}		received++;		cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;		RTL_W16 (RxBufPtr, (u16) (cur_rx - 16));		rtl8139_isr_ack(tp);	}	if (unlikely(!received || rx_size == 0xfff0))		rtl8139_isr_ack(tp);#if RTL8139_DEBUG > 1	DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"		 " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,		 RTL_R16 (RxBufAddr),		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));#endif	tp->cur_rx = cur_rx;	/*	 * The receive buffer should be mostly empty.	 * Tell NAPI to reenable the Rx irq.	 */	if (tp->fifo_copy_timeout)		received = budget;out:	return received;}static void rtl8139_weird_interrupt (struct net_device *dev,				     struct rtl8139_private *tp,				     void __iomem *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)) {		rtl_check_media(dev, 0);		status &= ~RxUnderrun;	}	if (status & (RxUnderrun | RxErr))		tp->stats.rx_errors++;	if (status & PCSTimeout)		tp->stats.rx_length_errors++;	if (status & RxUnderrun)		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);	}}static int rtl8139_poll(struct net_device *dev, int *budget){	struct rtl8139_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	int orig_budget = min(*budget, dev->quota);	int done = 1;	spin_lock(&tp->rx_lock);	if (likely(RTL_R16(IntrStatus) & RxAckBits)) {		int work_done;		work_done = rtl8139_rx(dev, tp, orig_budget);		if (likely(work_done > 0)) {			*budget -= work_done;			dev->quota -= work_done;			done = (work_done < orig_budget);		}	}	if (done) {		unsigned long flags;		/*		 * Order is important since data can get interrupted		 * again when we think we are done.		 */		local_irq_save(flags);		RTL_W16_F(IntrMask, rtl8139_intr_mask);		__netif_rx_complete(dev);		local_irq_restore(flags);	}	spin_unlock(&tp->rx_lock);	return !done;}/* The interrupt handler does all of the Rx thread work and cleans up   after the Tx thread. */static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance){	struct net_device *dev = (struct net_device *) dev_instance;	struct rtl8139_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	u16 status, ackstat;	int link_changed = 0; /* avoid bogus "uninit" warning */	int handled = 0;	spin_lock (&tp->lock);	status = RTL_R16 (IntrStatus);	/* shared irq? */	if (unlikely((status & rtl8139_intr_mask) == 0))		goto out;	handled = 1;	/* h/w no longer present (hotplug?) or major error, bail */	if (unlikely(status == 0xFFFF))		goto out;	/* close possible race's with dev_close */	if (unlikely(!netif_running(dev))) {		RTL_W16 (IntrMask, 0);		goto out;	}	/* Acknowledge all of the current interrupt sources ASAP, but	   an first get an additional status bit from CSCR. */	if (unlikely(status & RxUnderrun))		link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;	ackstat = status & ~(RxAckBits | TxErr);	if (ackstat)		RTL_W16 (IntrStatus, ackstat);	/* Receive packets are processed by poll routine.	   If not running start it now. */	if (status & RxAckBits){		if (netif_rx_schedule_prep(dev)) {			RTL_W16_F (IntrMask, rtl8139_norx_intr_mask);			__netif_rx_schedule (dev);		}	}	/* Check uncommon events with one test. */	if (unlikely(status & (PCIErr | PCSTimeout | RxUnderrun | RxErr)))		rtl8139_weird_interrupt (dev, tp, ioaddr,					 status, link_changed);	if (status & (TxOK | TxErr)) {		rtl8139_tx_interrupt (dev, tp, ioaddr);		if (status & TxErr)			RTL_W16 (IntrStatus, TxErr);	} out:	spin_unlock (&tp->lock);	DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n",		 dev->name, RTL_R16 (IntrStatus));	return IRQ_RETVAL(handled);}#ifdef CONFIG_NET_POLL_CONTROLLER/* * Polling receive - used by netconsole and other diagnostic tools * to allow network i/o with interrupts disabled. */static void rtl8139_poll_controller(struct net_device *dev){	disable_irq(dev->irq);	rtl8139_interrupt(dev->irq, dev);	enable_irq(dev->irq);}#endifstatic int rtl8139_close (struct net_device *dev){	struct rtl8139_private *tp = netdev_priv(dev);	void __iomem *ioaddr = tp->mmio_addr;	unsigned long flags;	netif_stop_queue (dev);	if (netif_msg_ifdown(tp))		printk(KERN_DEBUG "%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 (dev->irq);	/* racy, but that's ok here */	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 rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol){	struct rtl8139_private *np = netdev_priv(dev);	void __iomem *ioaddr = np->mmio_addr;	spin_lock_irq(&np->lock);	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;	}	spin_unlock_irq(&np->lock);}/* 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 rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol){	struct rtl8139_private *np = netdev_priv(dev);	void __iomem *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;	spin_lock_irq(&np->lock);	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 */	spin_unlock_irq(&np->lock);	return 0;}static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info){	struct rtl8139_private *np = netdev_priv(dev);	strcpy(info->driver, DRV_NAME);	strcpy(info->version, DRV_VERSION);	strcpy(info->bus_info, pci_name(np->pci_dev));	info->regdump_len = np->regs_len;}static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct rtl8139_private *np = netdev_priv(dev);	spin_lock_irq(&np->lock);	mii_ethtool_gset(&np->mii, cmd);	spin_unlock_irq(&np->lock);	return 0;}static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd){	struct rtl8139_private *np = netdev_priv(dev);	int rc;	spin_lock_irq(&np->lock);	rc = mii_ethtool_sset(&np->mii, cmd);	spin_unlock_irq(&np->lock);	return rc;}static int rtl8139_nway_reset(struct net_device *dev){	struct rtl8139_private *np = netdev_priv(dev);	return mii_nway_restart(&np->mii);}static u32 rtl8139_get_link(struct net_device *dev){	struct rtl8139_private *np = netdev_priv(dev);	return mii_link_ok(&np->mii);}static u32 rtl8139_get_msglevel(struct net_device *dev){	struct rtl8139_private *np = netdev_priv(dev);	return np->msg_enable;}static void rtl8139_set_msglevel(struct net_device *dev, u32 datum){	struct rtl8139_private *np = netdev_priv(dev);	np->msg_enable = datum;}/* TODO: we are too slack to do reg dumping for pio, for now */#ifdef CONFIG_8139TOO_PIO#define rtl8139_get_regs_len	NULL#define rtl8139_get_regs	NULL#elsestatic int rtl8139_get_regs_len(struct net_device *dev){	struct rtl8139_private *np = netdev_priv(dev);	return np->regs_len;}static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf){	struct rtl8139_private *np = netdev_priv(dev);	regs->version = RTL_REGS_VER;	spin_lock_irq(&np->lock);	memcpy_fromio(regbuf, np->mmio_addr, regs->len);	spin_unlock_irq(&np->lock);}#endif /* CONFIG_8139

⌨️ 快捷键说明

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