Subject: if_sip patch for newer SIS900 revisions
To: None <current-users@netbsd.org>
From: Joerg Sonnenberger <joerg@britannica.bec.de>
List: current-users
Date: 08/08/2003 21:20:12
--AhhlLboLdkugWU4S
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi all,
attached is a patch against if_sip.c which adds support for
newer SIS chipset revisions. If `ifconfig sip0` gives you
no media type and no PHY is detected on boot, this patch
might (should) fix it. It has been ported from FreeBSD.
The patch needs some additional cleanup, but hopeful some of
you can test it.

Joerg

--AhhlLboLdkugWU4S
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="sis.patch"

--- if_sip.c.orig	2003-08-08 19:29:17.000000000 +0200
+++ if_sip.c	2003-08-08 20:50:56.000000000 +0200
@@ -439,6 +439,8 @@
 void	SIP_DECL(dp83820_mii_writereg)(struct device *, int, int, int);
 void	SIP_DECL(dp83820_mii_statchg)(struct device *);
 #else
+static void sis900_mii_sync(struct sip_softc *)
+static void sis900_mii_send(struct sip_softc *, u_int32_t, int)
 int	SIP_DECL(sis900_mii_readreg)(struct device *, int, int);
 void	SIP_DECL(sis900_mii_writereg)(struct device *, int, int, int);
 void	SIP_DECL(sis900_mii_statchg)(struct device *);
@@ -3042,11 +3044,64 @@
 	bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_EROMAR, val);
 }
 #else /* ! DP83820 */
+
+#define SIS_EECTL		0x08
+
+#define SIS_MII_CLK		0x00000040
+#define SIS_MII_DIR		0x00000020
+#define SIS_MII_DATA		0x00000010
+
+#define SIS_MII_STARTDELIM	0x01
+#define SIS_MII_READOP		0x02
+#define SIS_MII_WRITEOP		0x01
+#define	SIS_MII_TURNAROUND	0x02
+
+#define SIO_SET(x) bus_space_write_4(sc->sc_st,sc->sc_sh,SIS_EECTL, \
+	bus_space_read_4(sc->sc_st,sc->sc_sh,SIS_EECTL) | (x))
+#define SIO_CLR(x) bus_space_write_4(sc->sc_st,sc->sc_sh,SIS_EECTL, \
+	 bus_space_read_4(sc->sc_st,sc->sc_sh,SIS_EECTL) & ~(x))
+
+static void
+sis900_mii_sync(struct sip_softc *sc)
+{
+	int i;
+
+	SIO_SET(SIS_MII_DIR|SIS_MII_DATA);
+
+	for (i = 0; i < 32; i++) {
+		SIO_SET(SIS_MII_CLK);
+		DELAY(1);
+		SIO_CLR(SIS_MII_CLK);
+		DELAY(1);
+	}
+}
+
+static void
+sis900_mii_send(struct sip_softc *sc, u_int32_t bits, int cnt)
+{
+	int i;
+
+	SIO_CLR(SIS_MII_CLK);
+
+	for (i = (0x1 << (cnt -1)); i; i >>= 1) {
+		if (bits & i) {
+			SIO_SET(SIS_MII_DATA);
+		} else {
+			SIO_CLR(SIS_MII_DATA);
+		}
+		DELAY(1);
+		SIO_CLR(SIS_MII_CLK);
+		DELAY(1);
+		SIO_SET(SIS_MII_CLK);
+	}
+}
+
 /*
  * sip_sis900_mii_readreg:	[mii interface function]
  *
  *	Read a PHY register on the MII.
  */
+
 int
 SIP_DECL(sis900_mii_readreg)(struct device *self, int phy, int reg)
 {
@@ -3058,16 +3113,80 @@
 	 * MII address 0.
 	 */
 	if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 &&
-	    sc->sc_rev < SIS_REV_635 && phy != 0)
-		return (0);
+	    sc->sc_rev < SIS_REV_635) {
+		if (phy != 0)
+			return (0);
 
-	bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
-	    (phy << ENPHY_PHYADDR_SHIFT) | (reg << ENPHY_REGADDR_SHIFT) |
-	    ENPHY_RWCMD | ENPHY_ACCESS);
-	do {
-		enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
-	} while (enphy & ENPHY_ACCESS);
-	return ((enphy & ENPHY_PHYDATA) >> ENPHY_DATA_SHIFT);
+		bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
+	    	(phy << ENPHY_PHYADDR_SHIFT) | (reg << ENPHY_REGADDR_SHIFT) |
+	    	ENPHY_RWCMD | ENPHY_ACCESS);
+		do {
+			enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
+		} while (enphy & ENPHY_ACCESS);
+		return ((enphy & ENPHY_PHYDATA) >> ENPHY_DATA_SHIFT);
+	}
+	else {
+		int i, ack, s;
+		u_int16_t mii_data = 0;
+
+		s = splvm();
+
+		/* Turn on data xmit. */
+		SIO_SET(SIS_MII_DIR);
+		sis900_mii_sync(sc);
+
+		/* Send command/address info */
+		sis900_mii_send(sc,SIS_MII_STARTDELIM,2);
+		sis900_mii_send(sc,SIS_MII_READOP,2);
+		sis900_mii_send(sc,phy,5);
+		sis900_mii_send(sc,reg,5);
+
+		/* Idle bit */
+		SIO_CLR(SIS_MII_CLK|SIS_MII_DATA);
+		DELAY(1);
+		SIO_SET(SIS_MII_CLK);
+		DELAY(1);
+
+		/* Turn off xmit. */
+		SIO_CLR(SIS_MII_DIR);
+
+		/* Check for ack */
+		SIO_CLR(SIS_MII_CLK);
+		DELAY(1);
+		ack = bus_space_read_4(sc->sc_st,sc->sc_sh,SIS_EECTL) & SIS_MII_DATA;
+		SIO_SET(SIS_MII_CLK);
+		DELAY(1);
+
+		/*
+		 * Now try reading data bits. If the ack failed, we still
+		 * need to clock through 16 cycles to keep the PHY(s) in sync.
+		 */
+		if (ack) {
+			for(i = 0; i < 16; i++) {
+				SIO_CLR(SIS_MII_CLK);
+				DELAY(1);
+				SIO_SET(SIS_MII_CLK);
+				DELAY(1);
+			}
+		} else {
+			for (i = 0x8000; i; i >>= 1) {
+				SIO_CLR(SIS_MII_CLK);
+				DELAY(1);
+				if (bus_space_read_4(sc->sc_st,sc->sc_sh,SIS_EECTL) & SIS_MII_DATA)
+					mii_data |= i;
+				SIO_SET(SIS_MII_CLK);
+				DELAY(1);
+			}
+		}
+
+		SIO_CLR(SIS_MII_CLK);
+		DELAY(1);
+		SIO_SET(SIS_MII_CLK);
+		DELAY(1);
+
+		splx(s);
+		return mii_data;
+	}	
 }
 
 /*
@@ -3086,15 +3205,42 @@
 	 * MII address 0.
 	 */
 	if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 &&
-	    sc->sc_rev < SIS_REV_635 && phy != 0)
-		return;
+	    sc->sc_rev < SIS_REV_635 && phy != 0) {
+		if (phy != 0)
+			return;
 
-	bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
-	    (val << ENPHY_DATA_SHIFT) | (phy << ENPHY_PHYADDR_SHIFT) |
-	    (reg << ENPHY_REGADDR_SHIFT) | ENPHY_ACCESS);
-	do {
-		enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
-	} while (enphy & ENPHY_ACCESS);
+		bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
+	 	   (val << ENPHY_DATA_SHIFT) | (phy << ENPHY_PHYADDR_SHIFT) |
+	 	   (reg << ENPHY_REGADDR_SHIFT) | ENPHY_ACCESS);
+		do {
+			enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
+		} while (enphy & ENPHY_ACCESS);
+	} else {
+		int s;
+
+		s = splvm();
+
+		/* Turn on data output. */
+		SIO_SET(SIS_MII_DIR);
+		sis900_mii_sync(sc);
+		sis900_mii_send(sc,SIS_MII_STARTDELIM,2);
+		sis900_mii_send(sc,SIS_MII_WRITEOP,2);
+		sis900_mii_send(sc,phy,5);
+		sis900_mii_send(sc,reg,5);
+		sis900_mii_send(sc,SIS_MII_TURNAROUND,2);
+		sis900_mii_send(sc,val,16);
+
+		/* Idle bit. */
+		SIO_SET(SIS_MII_CLK);
+		DELAY(1);
+		SIO_CLR(SIS_MII_CLK);
+		DELAY(1);
+
+		/* Turn off xmit. */
+		SIO_CLR(SIS_MII_DIR);
+
+		splx(s);
+	}
 }
 
 /*

--AhhlLboLdkugWU4S--