patch-2.4.20 linux-2.4.20/drivers/net/sis900.c

Next file: linux-2.4.20/drivers/net/sis900.h
Previous file: linux-2.4.20/drivers/net/sgiseeq.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/drivers/net/sis900.c linux-2.4.20/drivers/net/sis900.c
@@ -1,6 +1,6 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:	1.08.04	Apr. 25 2002
+   Revision:	1.08.06 Sep. 24 2002
    
    Modified from the driver which is originally written by Donald Becker.
    
@@ -18,6 +18,8 @@
    preliminary Rev. 1.0 Jan. 18, 1998
    http://www.sis.com.tw/support/databook.htm
 
+   Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
+   Rev 1.08.05 Jun. 6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary 
    Rev 1.08.04 Apr. 25 2002 Mufasa Yang <mufasa@sis.com.tw> added SiS962 support
    Rev 1.08.03 Feb. 1 2002 Matt Domsch <Matt_Domsch@dell.com> update to use library crc32 function
    Rev 1.08.02 Nov. 30 2001 Hui-Fen Hsu workaround for EDB & bug fix for dhcp problem
@@ -72,7 +74,7 @@
 #include "sis900.h"
 
 #define SIS900_MODULE_NAME "sis900"
-#define SIS900_DRV_VERSION "v1.08.04 4/25/2002"
+#define SIS900_DRV_VERSION "v1.08.06 9/24/2002"
 
 static char version[] __devinitdata =
 KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -309,31 +311,38 @@
 }
 
 /**
- *	sis962_get_mac_addr: - Get MAC address for SiS962 model
+ *	sis96x_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
  *	@pci_dev: the sis900 pci device
  *	@net_dev: the net device to get address for 
  *
- *	SiS962 model, use EEPROM to store MAC address. And EEPROM is shared by
+ *	SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM 
+ *	is shared by
  *	LAN and 1394. When access EEPROM, send EEREQ signal to hardware first 
  *	and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access 
  *	by LAN, otherwise is not. After MAC address is read from EEPROM, send
  *	EEDONE signal to refuse EEPROM access by LAN. 
+ *	The EEPROM map of SiS962 or SiS963 is different to SiS900. 
+ *	The signature field in SiS962 or SiS963 spec is meaningless. 
  *	MAC address is read into @net_dev->dev_addr.
  */
 
-static int __devinit sis962_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
+static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
 {
 	long ioaddr = net_dev->base_addr;
 	long ee_addr = ioaddr + mear;
 	u32 waittime = 0;
-	int ret = 0;
+	int i;
 	
 	outl(EEREQ, ee_addr);
 	while(waittime < 2000) {
 		if(inl(ee_addr) & EEGNT) {
-			ret = sis900_get_mac_addr(pci_dev, net_dev);
+
+			/* get MAC address from EEPROM */
+			for (i = 0; i < 3; i++)
+			        ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
+
 			outl(EEDONE, ee_addr);
-			return(ret);
+			return 1;
 		} else {
 			udelay(1);	
 			waittime ++;
@@ -443,8 +452,8 @@
 		ret = sis630e_get_mac_addr(pci_dev, net_dev);
 	else if ((revision > 0x81) && (revision <= 0x90) )
 		ret = sis635_get_mac_addr(pci_dev, net_dev);
-	else if (revision == SIS962_900_REV)
-		ret = sis962_get_mac_addr(pci_dev, net_dev);
+	else if (revision == SIS96x_900_REV)
+		ret = sis96x_get_mac_addr(pci_dev, net_dev);
 	else
 		ret = sis900_get_mac_addr(pci_dev, net_dev);
 
@@ -702,7 +711,7 @@
 
 	outl(0, ee_addr);
 	eeprom_delay();
-	outl(EECLK, ee_addr);
+	outl(EECS, ee_addr);
 	eeprom_delay();
 
 	/* Shift the read command (9) bits out. */
@@ -713,7 +722,7 @@
 		outl(dataval | EECLK, ee_addr);
 		eeprom_delay();
 	}
-	outb(EECS, ee_addr);
+	outl(EECS, ee_addr);
 	eeprom_delay();
 
 	/* read the 16-bits data in */
@@ -729,7 +738,6 @@
 	/* Terminate the EEPROM access. */
 	outl(0, ee_addr);
 	eeprom_delay();
-	outl(EECLK, ee_addr);
 
 	return (retval);
 }
@@ -1432,8 +1440,8 @@
 
 	net_dev->trans_start = jiffies;
 
-	/* FIXME: Should we restart the transmission thread here  ?? */
-	outl(TxENA | inl(ioaddr + cr), ioaddr + cr);
+	/* load Transmit Descriptor Register */
+	outl(sis_priv->tx_ring_dma, ioaddr + txdp);
 
 	/* Enable all known interrupts by setting the interrupt mask. */
 	outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
@@ -1457,6 +1465,8 @@
 	long ioaddr = net_dev->base_addr;
 	unsigned int  entry;
 	unsigned long flags;
+	unsigned int  index_cur_tx, index_dirty_tx;
+	unsigned int  count_dirty_tx;
 
 	/* Don't transmit data before the complete of auto-negotiation */
 	if(!sis_priv->autong_complete){
@@ -1476,7 +1486,18 @@
 	sis_priv->tx_ring[entry].cmdsts = (OWN | skb->len);
 	outl(TxENA | inl(ioaddr + cr), ioaddr + cr);
 
-	if (++sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC) {
+	sis_priv->cur_tx ++;
+	index_cur_tx = sis_priv->cur_tx;
+	index_dirty_tx = sis_priv->dirty_tx;
+
+	for (count_dirty_tx = 0; index_cur_tx != index_dirty_tx; index_dirty_tx++)
+		count_dirty_tx ++;
+
+	if (index_cur_tx == index_dirty_tx) {
+		/* dirty_tx is met in the cycle of cur_tx, buffer full */
+		sis_priv->tx_full = 1;
+		netif_stop_queue(net_dev);
+	} else if (count_dirty_tx < NUM_TX_DESC) { 
 		/* Typical path, tell upper layer that more transmission is possible */
 		netif_start_queue(net_dev);
 	} else {
@@ -1709,7 +1730,7 @@
 {
 	struct sis900_private *sis_priv = net_dev->priv;
 
-	for (; sis_priv->dirty_tx < sis_priv->cur_tx; sis_priv->dirty_tx++) {
+	for (; sis_priv->dirty_tx != sis_priv->cur_tx; sis_priv->dirty_tx++) {
 		struct sk_buff *skb;
 		unsigned int entry;
 		u32 tx_status;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)