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

📄 8139too.c

📁 8139driver_in)linux2.4.x
💻 C
📖 第 1 页 / 共 5 页
字号:
				"%s: Setting %s-duplex based on MII #%d link"				" partner ability of %4.4x.\n", dev->name,				tp->full_duplex ? "full" : "half",				tp->phys[0], mii_reg5);			RTL_W8 (Cfg9346, Cfg9346_Unlock);			RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);			RTL_W8 (Cfg9346, Cfg9346_Lock);		}	}	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"		 " RxStatus %4.4lx.\n", dev->name,		 RTL_R16 (IntrMask),		 RTL_R16 (IntrStatus),		 RTL_R32 (RxEarlyStatus));	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 ();	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))			break;		rtnl_lock ();		rtl8139_thread_iter (dev, tp, tp->mmio_addr);		rtnl_unlock ();	}#if LINUX_VERSION_CODE < 0x20407	up_and_exit (&tp->thr_exited, 0);#else	complete_and_exit (&tp->thr_exited, 0);#endif}static void rtl8139_tx_clear (struct rtl8139_private *tp){	int i;	tp->cur_tx = 0;	tp->dirty_tx = 0;	/* Dump the unsent Tx packets. */	for (i = 0; i < NUM_TX_DESC; i++) {		struct ring_info *rp = &tp->tx_info[i];		if (rp->mapping != 0) {			pci_unmap_single (tp->pci_dev, rp->mapping,					  rp->skb->len, PCI_DMA_TODEVICE);			rp->mapping = 0;		}		if (rp->skb) {			dev_kfree_skb (rp->skb);			rp->skb = NULL;			tp->stats.tx_dropped++;		}	}}static void rtl8139CP_tx_clear (struct rtl8139_private *tp){	int i;	tp->CP_cur_tx=0;	for (i=0 ; i<NUM_CP_TX_DESC ; i++){		if ( tp->Tx_skbuff[i]!=NULL ) {			dev_kfree_skb (tp->Tx_skbuff[i]);			tp->Tx_skbuff[i] = NULL;			tp->stats.tx_dropped++;		}	}}static void rtl8139_tx_timeout (struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	void *ioaddr = tp->mmio_addr;	u8 tmp8;	DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x "		 "media %2.2x.\n", dev->name,		 RTL_R8 (ChipCmd),		 RTL_R16 (IntrStatus),		 RTL_R8 (MediaStatus));	/* disable Tx ASAP, if not already */	tmp8 = RTL_R8 (ChipCmd);	if (tmp8 & CmdTxEnb)		RTL_W8 (ChipCmd, tmp8 & ~CmdTxEnb);	/* Disable interrupts by clearing the interrupt mask. */	RTL_W16 (IntrMask, 0x0000);	/* Stop a shared interrupt from scavenging while we are. */	spin_lock_irq (&tp->lock);	rtl8139_tx_clear (tp);	spin_unlock_irq (&tp->lock);	/* ...and finally, reset everything */	rtl8139_hw_start (dev);		netif_wake_queue (dev);}static void rtl8139CP_tx_timeout (struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	void *ioaddr = tp->mmio_addr;	u8 tmp8;	DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x "		 "media %2.2x.\n", dev->name,		 RTL_R8 (ChipCmd),		 RTL_R16 (IntrStatus),		 RTL_R8 (MediaStatus));	/* disable Tx ASAP, if not already */	tmp8 = RTL_R8 (ChipCmd);	if (tmp8 & CmdTxEnb)		RTL_W8 (ChipCmd, tmp8 & ~CmdTxEnb);	/* Disable interrupts by clearing the interrupt mask. */	RTL_W16 (IntrMask, 0x0000);	/* Stop a shared interrupt from scavenging while we are. */	spin_lock_irq (&tp->lock);	rtl8139CP_tx_clear (tp);	spin_unlock_irq (&tp->lock);	/* ...and finally, reset everything */	rtl8139CP_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;	int entry;	/* Calculate the next Tx descriptor entry. */	entry = tp->cur_tx % NUM_TX_DESC;	assert (tp->tx_info[entry].skb == NULL);	assert (tp->tx_info[entry].mapping == 0);	tp->tx_info[entry].skb = skb;	if ((long) skb->data & 3) {	/* Must use alignment buffer. */		/* tp->tx_info[entry].mapping = 0; */		memcpy (tp->tx_buf[entry], skb->data, skb->len);		RTL_W32 (TxAddr0 + (entry * 4),			 tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs));	} else {		tp->tx_info[entry].mapping =		    pci_map_single (tp->pci_dev, skb->data, skb->len,				    PCI_DMA_TODEVICE);		RTL_W32 (TxAddr0 + (entry * 4), tp->tx_info[entry].mapping);	}	/* Note: the chip doesn't have auto-pad! */	RTL_W32 (TxStatus0 + (entry * sizeof (u32)),		 tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));	dev->trans_start = jiffies;	spin_lock_irq (&tp->lock);	tp->cur_tx++;	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)		netif_stop_queue (dev);	spin_unlock_irq (&tp->lock);	DPRINTK ("%s: Queued Tx packet at %p size %u to slot %d.\n",		 dev->name, skb->data, skb->len, entry);	return 0;}static int rtl8139CP_start_xmit (struct sk_buff *skb, struct net_device *dev){	struct rtl8139_private *tp = dev->priv;	void *ioaddr = tp->mmio_addr;	int CP_entry;	struct ethernet_ii_header *eIIHeader;    	ip_v4_header   *IPPacket = NULL;	mb();	CP_entry = tp->CP_cur_tx % NUM_CP_TX_DESC;			//C+ mode only	spin_lock_irq (&tp->lock);	if( (tp->TxDescArray[CP_entry].status & 0x80000000)==0 ){		tp->Tx_skbuff[CP_entry] = skb;								//C+ mode only		tp->TxDescArray[CP_entry].buf_addr=virt_to_bus(skb->data);	//C+ mode only		if( CP_entry != (NUM_CP_TX_DESC-1) )		  tp->TxDescArray[CP_entry].status= 0xB0000000 |( (skb->len > ETH_ZLEN) ? skb->len : ETH_ZLEN);	        else		  tp->TxDescArray[CP_entry].status= 0xF0000000 |( (skb->len > ETH_ZLEN) ? skb->len : ETH_ZLEN);			//////////////////////////////////////////////////////////////////////////////		if( skb->ip_summed == CHECKSUM_HW ){			eIIHeader = (struct ethernet_ii_header *) skb->data;    			// Check for Ethernet_II IP encapsulation //    			if (eIIHeader->TypeLength == IP_PROTOCOL) {        			// We need to point the IPPacket past the Ethernet_II header. //        			IPPacket = (ip_v4_header *) ((uint8_t *) eIIHeader + sizeof(struct ethernet_ii_header));		        			if (IPPacket->ProtocolCarried == TCP_PROTOCOL) {					tp->TxDescArray[CP_entry].status |= (CPlusTxIPchecksumOffload | CPlusTxTCPchecksumOffload);        			}        			else if (IPPacket->ProtocolCarried == UDP_PROTOCOL) {					tp->TxDescArray[CP_entry].status |= (CPlusTxIPchecksumOffload | CPlusTxUDPchecksumOffload);        			}    			}		}//end of if( skb->ip_summed == CHECKSUM_HW )		//////////////////////////////////////////////////////////////////////////////		RTL_W8 (CPlusTxPoll, 0x40);		//set polling bit		dev->trans_start = jiffies;		tp->CP_cur_tx++;						//C+ mode only		if ( (tp->CP_cur_tx - NUM_CP_TX_DESC) == tp->CP_dirty_tx )			netif_stop_queue (dev);	}//end of if( (tp->TxDescArray[CP_entry].status & 0x80000000)==0 )	spin_unlock_irq (&tp->lock);	mb();//	if ( (tp->CP_cur_tx - NUM_CP_TX_DESC) == tp->CP_dirty_tx )//		netif_stop_queue (dev);	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 | (TX_DMA_BURST << TxDMAShift));			}			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++;		}		/* Free the original skb. */		if (tp->tx_info[entry].mapping != 0) {			pci_unmap_single(tp->pci_dev,					 tp->tx_info[entry].mapping,					 tp->tx_info[entry].skb->len,					 PCI_DMA_TODEVICE);			tp->tx_info[entry].mapping = 0;		}		dev_kfree_skb_irq (tp->tx_info[entry].skb);		tp->tx_info[entry].skb = NULL;		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;		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;	int tmp_work = 1000;	DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n",	         dev->name, rx_status);	if (rx_status & RxTooLong) {		DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",			 dev->name, rx_status);		/* A.C.: The chip hangs here. */	}	tp->stats.rx_errors++;	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++;	/* Reset the receiver, based on RealTek recommendation. (Bug?) */	tp->cur_rx = 0;	/* disable receive */	tmp8 = RTL_R8 (ChipCmd) & ChipCmdClear;	RTL_W8_F (ChipCmd, tmp8 | CmdTxEnb);	/* A.C.: Reset the multicast list. */	rtl8139_set_rx_mode (dev);	/* XXX potentially temporary hack to	 * restart hung receiver */	while (--tmp_work > 0) {		tmp8 = RTL_R8 (ChipCmd);		if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb))			break;		RTL_W8_F (ChipCmd,			  (tmp8 & ChipCmdClear) | CmdRxEnb | CmdTxEnb);	}	/* G.S.: Re-enable receiver */	/* XXX temporary hack to work around receiver hang */	rtl8139_set_rx_mode (dev);	if (tmp_work <= 0)		printk (KERN_WARNING PFX "tx/rx enable wait too long\n");}/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the   field alignments and semantics. */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;		/* 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		/* E. Gill */		/* Note from BSD driver:		 * Here's a totally undocumented fact for you. When the		 * RealTek chip is in the process of copying a packet into		 * RAM for you, the length will be 0xfff0. If you spot a		 * packet header with this value, you need to stop. The		 * datasheet makes absolutely no mention of this and		 * RealTek should be shot for this.		 */		if (rx_size == 0xfff0)			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

⌨️ 快捷键说明

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