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

📄 8139too.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (tp->twist_col == 0)			RTL_W16 (FIFOTMS, 0);		RTL_W32 (PARA7c, param[(int) tp->twist_row]			 [(int) tp->twist_col]);		next_tick = HZ / 10;		if (++tp->twist_col >= 4) {			/* For short cables we are done.			   For long cables (row == 3) check for mistune. */			tp->twistie =			    (tp->twist_row == 3) ? 4 : 0;		}		break;	case 4:		/* Special case for long cables: check for mistune. */		if ((RTL_R16 (CSCR) &		     CSCR_LinkStatusBits) == 0x7000) {			tp->twistie = 0;			break;		} else {			RTL_W32 (PARA7c, 0xfb38de03);			tp->twistie = 5;			next_tick = HZ / 10;		}		break;	case 5:		/* Retune for shorter cable (column 2). */		RTL_W32 (FIFOTMS, 0x20);		RTL_W32 (PARA78, PARA78_default);		RTL_W32 (PARA7c, PARA7c_default);		RTL_W32 (FIFOTMS, 0x00);		tp->twist_row = 2;		tp->twist_col = 0;		tp->twistie = 3;		next_tick = HZ / 10;		break;	default:		/* do nothing */		break;	}}#endif /* CONFIG_8139TOO_TUNE_TWISTER */static inline void rtl8139_thread_iter (struct net_device *dev,				 struct rtl8139_private *tp,				 void *ioaddr){	int mii_lpa;	mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);	if (!tp->mii.duplex_lock && mii_lpa != 0xffff) {		int duplex = (mii_lpa & LPA_100FULL)		    || (mii_lpa & 0x01C0) == 0x0040;		if (tp->mii.full_duplex != duplex) {			tp->mii.full_duplex = duplex;			if (mii_lpa) {				printk (KERN_INFO					"%s: Setting %s-duplex based on MII #%d link"					" partner ability of %4.4x.\n",					dev->name,					tp->mii.full_duplex ? "full" : "half",					tp->phys[0], mii_lpa);			} else {				printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n",				       dev->name);			}#if 0			RTL_W8 (Cfg9346, Cfg9346_Unlock);			RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20);			RTL_W8 (Cfg9346, Cfg9346_Lock);#endif		}	}	next_tick = HZ * 60;	rtl8139_tune_twister (dev, tp);	DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n",		 dev->name, RTL_R16 (NWayLPAR));	DPRINTK ("%s:  Other registers are IntMask %4.4x IntStatus %4.4x\n",		 dev->name, RTL_R16 (IntrMask), RTL_R16 (IntrStatus));	DPRINTK ("%s:  Chip config %2.2x %2.2x.\n",		 dev->name, RTL_R8 (Config0),		 RTL_R8 (Config1));}static int rtl8139_thread (void *data){	struct net_device *dev = data;	struct rtl8139_private *tp = dev->priv;	unsigned long timeout;	daemonize ();	reparent_to_init();	spin_lock_irq(&current->sigmask_lock);	sigemptyset(&current->blocked);	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	strncpy (current->comm, dev->name, sizeof(current->comm) - 1);	current->comm[sizeof(current->comm) - 1] = '\0';	while (1) {		timeout = next_tick;		do {			timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);		} while (!signal_pending (current) && (timeout > 0));		if (signal_pending (current)) {			spin_lock_irq(&current->sigmask_lock);			flush_signals(current);			spin_unlock_irq(&current->sigmask_lock);		}		if (tp->time_to_die)			break;		rtnl_lock ();		rtl8139_thread_iter (dev, tp, tp->mmio_addr);		rtnl_unlock ();	}	complete_and_exit (&tp->thr_exited, 0);}static void rtl8139_tx_clear (struct rtl8139_private *tp){	tp->cur_tx = 0;	tp->dirty_tx = 0;	/* XXX account for unsent Tx packets in tp->stats.tx_dropped */}static void rtl8139_tx_timeout (struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	void *ioaddr = tp->mmio_addr;	int i;	u8 tmp8;	unsigned long flags;	DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x "		 "media %2.2x.\n", dev->name,		 RTL_R8 (ChipCmd),		 RTL_R16 (IntrStatus),		 RTL_R8 (MediaStatus));	tp->xstats.tx_timeouts++;	/* disable Tx ASAP, if not already */	tmp8 = RTL_R8 (ChipCmd);	if (tmp8 & CmdTxEnb)		RTL_W8 (ChipCmd, CmdRxEnb);	/* Disable interrupts by clearing the interrupt mask. */	RTL_W16 (IntrMask, 0x0000);	/* Emit info to figure out what went wrong. */	printk (KERN_DEBUG "%s: Tx queue start entry %ld  dirty entry %ld.\n",		dev->name, tp->cur_tx, tp->dirty_tx);	for (i = 0; i < NUM_TX_DESC; i++)		printk (KERN_DEBUG "%s:  Tx descriptor %d is %8.8lx.%s\n",			dev->name, i, RTL_R32 (TxStatus0 + (i * 4)),			i == tp->dirty_tx % NUM_TX_DESC ?				" (queue head)" : "");	/* Stop a shared interrupt from scavenging while we are. */	spin_lock_irqsave (&tp->lock, flags);	rtl8139_tx_clear (tp);	spin_unlock_irqrestore (&tp->lock, flags);	/* ...and finally, reset everything */	rtl8139_hw_start (dev);	netif_wake_queue (dev);}static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	void *ioaddr = tp->mmio_addr;	unsigned int entry;	unsigned int len = skb->len;	/* Calculate the next Tx descriptor entry. */	entry = tp->cur_tx % NUM_TX_DESC;	if (likely(len < TX_BUF_SIZE)) {		skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);		dev_kfree_skb(skb);	} else {		dev_kfree_skb(skb);		tp->stats.tx_dropped++;		return 0;	}	/* Note: the chip doesn't have auto-pad! */	spin_lock_irq(&tp->lock);	RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),		   tp->tx_flag | max(len, (unsigned int)ETH_ZLEN));	dev->trans_start = jiffies;	tp->cur_tx++;	wmb();	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)		netif_stop_queue (dev);	spin_unlock_irq(&tp->lock);	DPRINTK ("%s: Queued Tx packet size %u to slot %d.\n",		 dev->name, len, entry);	return 0;}static void rtl8139_tx_interrupt (struct net_device *dev,				  struct rtl8139_private *tp,				  void *ioaddr){	unsigned long dirty_tx, tx_left;	assert (dev != NULL);	assert (tp != NULL);	assert (ioaddr != NULL);	dirty_tx = tp->dirty_tx;	tx_left = tp->cur_tx - dirty_tx;	while (tx_left > 0) {		int entry = dirty_tx % NUM_TX_DESC;		int txstatus;		txstatus = RTL_R32 (TxStatus0 + (entry * sizeof (u32)));		if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted)))			break;	/* It still hasn't been Txed */		/* Note: TxCarrierLost is always asserted at 100mbps. */		if (txstatus & (TxOutOfWindow | TxAborted)) {			/* There was an major error, log it. */			DPRINTK ("%s: Transmit error, Tx status %8.8x.\n",				 dev->name, txstatus);			tp->stats.tx_errors++;			if (txstatus & TxAborted) {				tp->stats.tx_aborted_errors++;				RTL_W32 (TxConfig, TxClearAbt);				RTL_W16 (IntrStatus, TxErr);				wmb();			}			if (txstatus & TxCarrierLost)				tp->stats.tx_carrier_errors++;			if (txstatus & TxOutOfWindow)				tp->stats.tx_window_errors++;#ifdef ETHER_STATS			if ((txstatus & 0x0f000000) == 0x0f000000)				tp->stats.collisions16++;#endif		} else {			if (txstatus & TxUnderrun) {				/* Add 64 to the Tx FIFO threshold. */				if (tp->tx_flag < 0x00300000)					tp->tx_flag += 0x00020000;				tp->stats.tx_fifo_errors++;			}			tp->stats.collisions += (txstatus >> 24) & 15;			tp->stats.tx_bytes += txstatus & 0x7ff;			tp->stats.tx_packets++;		}		dirty_tx++;		tx_left--;	}#ifndef RTL8139_NDEBUG	if (tp->cur_tx - dirty_tx > NUM_TX_DESC) {		printk (KERN_ERR "%s: Out-of-sync dirty pointer, %ld vs. %ld.\n",		        dev->name, dirty_tx, tp->cur_tx);		dirty_tx += NUM_TX_DESC;	}#endif /* RTL8139_NDEBUG */	/* only wake the queue if we did work, and the queue is stopped */	if (tp->dirty_tx != dirty_tx) {		tp->dirty_tx = dirty_tx;		mb();		if (netif_queue_stopped (dev))			netif_wake_queue (dev);	}}/* TODO: clean this up!  Rx reset need not be this intensive */static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,			    struct rtl8139_private *tp, void *ioaddr){	u8 tmp8;#ifndef CONFIG_8139_NEW_RX_RESET	int tmp_work;#endif	DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n",	         dev->name, rx_status);	tp->stats.rx_errors++;	if (!(rx_status & RxStatusOK)) {		if (rx_status & RxTooLong) {			DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",			 	dev->name, rx_status);			/* A.C.: The chip hangs here. */		}		if (rx_status & (RxBadSymbol | RxBadAlign))			tp->stats.rx_frame_errors++;		if (rx_status & (RxRunt | RxTooLong))			tp->stats.rx_length_errors++;		if (rx_status & RxCRCErr)			tp->stats.rx_crc_errors++;	} else {		tp->xstats.rx_lost_in_ring++;	}#ifdef CONFIG_8139_NEW_RX_RESET	tmp8 = RTL_R8 (ChipCmd);	RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb);	RTL_W8 (ChipCmd, tmp8);	RTL_W32 (RxConfig, tp->rx_config);	tp->cur_rx = 0;#else	/* Reset the receiver, based on RealTek recommendation. (Bug?) */	/* disable receive */	RTL_W8_F (ChipCmd, CmdTxEnb);	tmp_work = 200;	while (--tmp_work > 0) {		udelay(1);		tmp8 = RTL_R8 (ChipCmd);		if (!(tmp8 & CmdRxEnb))			break;	}	if (tmp_work <= 0)		printk (KERN_WARNING PFX "rx stop wait too long\n");	/* restart receive */	tmp_work = 200;	while (--tmp_work > 0) {		RTL_W8_F (ChipCmd, CmdRxEnb | CmdTxEnb);		udelay(1);		tmp8 = RTL_R8 (ChipCmd);		if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb))			break;	}	if (tmp_work <= 0)		printk (KERN_WARNING PFX "tx/rx enable wait too long\n");	/* and reinitialize all rx related registers */	RTL_W8_F (Cfg9346, Cfg9346_Unlock);	/* 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);	tp->cur_rx = 0;	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);	/* A.C.: Reset the multicast list. */	__set_rx_mode (dev);#endif}static void rtl8139_rx_interrupt (struct net_device *dev,				  struct rtl8139_private *tp, void *ioaddr){	unsigned char *rx_ring;	u16 cur_rx;	assert (dev != NULL);	assert (tp != NULL);	assert (ioaddr != NULL);	rx_ring = tp->rx_ring;	cur_rx = tp->cur_rx;	DPRINTK ("%s: In 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));	while ((RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {		int ring_offset = cur_rx % RX_BUF_LEN;		u32 rx_status;		unsigned int rx_size;		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;		DPRINTK ("%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 (rx_size == 0xfff0) {			tp->xstats.early_rx++;			break;		}		/* 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 ((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||		    (rx_size < 8) ||		    (!(rx_status & RxStatusOK))) {			rtl8139_rx_err (rx_status, dev, tp, ioaddr);			return;		}		/* Malloc up new buffer, compatible with net-2e. */		/* Omit the four octet CRC from the length. */		/* TODO: consider allocating skb's outside of		 * interrupt context, both to speed interrupt processing,		 * and also to reduce the chances of having to		 * drop packets here under memory pressure.		 */		skb = dev_alloc_skb (pkt_size + 2);		if (skb) {			skb->dev = dev;			skb_reserve (skb, 2);	/* 16 byte align the IP fields. */			eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);			skb_put (skb, pkt_size);			skb->protocol = eth_type_trans (skb, dev);			netif_rx (skb);			dev->last_rx = jiffies;			tp->stats.rx_bytes += pkt_size;			tp->stats.rx_packets++;		} else {			printk (KERN_WARNING				"%s: Memory squeeze, dropping packet.\n",				dev->name);			tp->stats.rx_dropped++;		}		cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;		RTL_W16 (RxBufPtr, cur_rx - 16);		if (RTL_R16 (IntrStatus) & RxAckBits)			RTL_W16_F (IntrStatus, RxAckBits);	}	DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"		 " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,

⌨️ 快捷键说明

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