Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Jan 2003 22:59:28 -0600 (CST)
From:      Mike Silbersack <silby@silby.com>
To:        stable@freebsd.org
Cc:        Gert-Jan Vons <vons@netcourrier.com>, Greg Lewis <glewis@eyesbeyond.com>, Thomas Nystrom <thn@saeab.se>
Subject:   Via Rhine owners, please test!
Message-ID:  <20030131201821.A5899-200000@patrocles.silby.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]

At the request of Thomas Nystrom, I have now committed his patches to fix
the hanging problems of some rhine chipsets and his fixes to allow 6105
(Rhine III) chips to work properly to -current.  Naturally, I'm going to
wait at least a week before MFCing this change to 4-stable.  In the
meantime, I'd like to request those who have had problems with Via Rhine
cards (either hangs, or unsupported 6105 cards) to try out this patch and
tell me how it works out.  This patch contains all of the changes
described above, and should apply cleanly to any relatively recent
4.7-stable machine.

Thanks,

Mike "Silby" Silbersack
[-- Attachment #2 --]
Index: if_vr.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_vr.c,v
retrieving revision 1.26.2.11
diff -u -r1.26.2.11 if_vr.c
--- if_vr.c	28 Nov 2002 03:00:59 -0000	1.26.2.11
+++ if_vr.c	1 Feb 2003 01:41:21 -0000
@@ -103,6 +103,8 @@
   "$FreeBSD: src/sys/pci/if_vr.c,v 1.26.2.11 2002/11/28 03:00:59 silby Exp $";
 #endif
 
+#undef VR_USESWSHIFT
+
 /*
  * Various supported device vendors/types and their names.
  */
@@ -113,6 +115,10 @@
 		"VIA VT86C100A Rhine II 10/100BaseTX" },
 	{ VIA_VENDORID, VIA_DEVICEID_RHINE_II_2,
 		"VIA VT6102 Rhine II 10/100BaseTX" },
+	{ VIA_VENDORID, VIA_DEVICEID_RHINE_III,
+		"VIA VT6105 Rhine III 10/100BaseTX" },
+	{ VIA_VENDORID, VIA_DEVICEID_RHINE_III_M,
+		"VIA VT6105M Rhine III 10/100BaseTX" },
 	{ DELTA_VENDORID, DELTA_DEVICEID_RHINE_II,
 		"Delta Electronics Rhine II 10/100BaseTX" },
 	{ ADDTRON_VENDORID, ADDTRON_DEVICEID_RHINE_II,
@@ -145,8 +151,10 @@
 static int vr_ifmedia_upd	__P((struct ifnet *));
 static void vr_ifmedia_sts	__P((struct ifnet *, struct ifmediareq *));
 
+#ifdef VR_USESWSHIFT
 static void vr_mii_sync		__P((struct vr_softc *));
 static void vr_mii_send		__P((struct vr_softc *, u_int32_t, int));
+#endif
 static int vr_mii_readreg	__P((struct vr_softc *, struct vr_mii_frame *));
 static int vr_mii_writereg	__P((struct vr_softc *, struct vr_mii_frame *));
 static int vr_miibus_readreg	__P((device_t, int, int));
@@ -230,6 +238,7 @@
 	CSR_WRITE_1(sc, VR_MIICMD,			\
 		CSR_READ_1(sc, VR_MIICMD) & ~x)
 
+#ifdef VR_USESWSHIFT
 /*
  * Sync the PHYs by setting data bit and strobing the clock 32 times.
  */
@@ -274,6 +283,7 @@
 		SIO_SET(VR_MIICMD_CLK);
 	}
 }
+#endif
 
 /*
  * Read an PHY register through the MII.
@@ -282,6 +292,7 @@
 	struct vr_softc		*sc;
 	struct vr_mii_frame	*frame;
 	
+#ifdef VR_USESWSHIFT	
 {
 	int			i, ack, s;
 
@@ -368,6 +379,34 @@
 		return(1);
 	return(0);
 }
+#else
+{
+	int			s, i;
+
+	s = splimp();
+
+  	/* Set the PHY-adress */
+	CSR_WRITE_1(sc, VR_PHYADDR, (CSR_READ_1(sc, VR_PHYADDR)& 0xe0)|
+	    frame->mii_phyaddr);
+
+  	/* Set the register-adress */
+	CSR_WRITE_1(sc, VR_MIIADDR, frame->mii_regaddr);
+	VR_SETBIT(sc, VR_MIICMD, VR_MIICMD_READ_ENB);
+	
+	for (i = 0; i < 10000; i++) {
+		if ((CSR_READ_1(sc, VR_MIICMD) & VR_MIICMD_READ_ENB) == 0)
+			break;
+		DELAY(1);
+	}
+
+	frame->mii_data = CSR_READ_2(sc, VR_MIIDATA);
+
+	(void)splx(s);
+
+	return(0);
+}
+#endif
+
 
 /*
  * Write to a PHY register through the MII.
@@ -376,6 +415,7 @@
 	struct vr_softc		*sc;
 	struct vr_mii_frame	*frame;
 	
+#ifdef VR_USESWSHIFT	
 {
 	int			s;
 
@@ -421,6 +461,33 @@
 
 	return(0);
 }
+#else
+{
+	int			s, i;
+
+	s = splimp();
+
+  	/* Set the PHY-adress */
+	CSR_WRITE_1(sc, VR_PHYADDR, (CSR_READ_1(sc, VR_PHYADDR)& 0xe0)|
+		    frame->mii_phyaddr);
+
+  	/* Set the register-adress and data to write */
+	CSR_WRITE_1(sc, VR_MIIADDR, frame->mii_regaddr);
+	CSR_WRITE_2(sc, VR_MIIDATA, frame->mii_data);
+
+	VR_SETBIT(sc, VR_MIICMD, VR_MIICMD_WRITE_ENB);
+
+	for (i = 0; i < 10000; i++) {
+		if ((CSR_READ_1(sc, VR_MIICMD) & VR_MIICMD_WRITE_ENB) == 0)
+			break;
+		DELAY(1);
+	}
+
+	(void)splx(s);
+
+	return(0);
+}
+#endif
 
 static int vr_miibus_readreg(dev, phy, reg)
 	device_t		dev;
@@ -430,6 +497,15 @@
 	struct vr_mii_frame	frame;
 
 	sc = device_get_softc(dev);
+
+	switch (sc->vr_revid) {
+		case REV_ID_VT6102_APOLLO:
+			if (phy != 1)
+				return 0;
+		default:
+			break;
+		}
+
 	bzero((char *)&frame, sizeof(frame));
 
 	frame.mii_phyaddr = phy;
@@ -447,6 +523,15 @@
 	struct vr_mii_frame	frame;
 
 	sc = device_get_softc(dev);
+
+	switch (sc->vr_revid) {
+		case REV_ID_VT6102_APOLLO:
+			if (phy != 1)
+				return 0;
+		default:
+			break;
+		}
+
 	bzero((char *)&frame, sizeof(frame));
 
 	frame.mii_phyaddr = phy;
@@ -747,6 +832,14 @@
 	/* Reset the adapter. */
 	vr_reset(sc);
 
+        /*
+	 * Turn on bit2 (MIION) in PCI configuration register 0x53 during
+	 * initialization and disable AUTOPOLL.
+	 */
+        pci_write_config(dev, VR_PCI_MODE,
+	    pci_read_config(dev, VR_PCI_MODE, 4) | (VR_MODE3_MIION << 24), 4);
+	VR_CLRBIT(sc, VR_MIICMD, VR_MIICMD_AUTOPOLL);
+
 	/*
 	 * Get station address. The way the Rhine chips work,
 	 * you're not allowed to directly access the EEPROM once
@@ -991,33 +1084,23 @@
 		 */
 		if (rxstat & VR_RXSTAT_RXERR) {
 			ifp->if_ierrors++;
-			printf("vr%d: rx error: ", sc->vr_unit);
-			switch(rxstat & 0x000000FF) {
-			case VR_RXSTAT_CRCERR:
-				printf("crc error\n");
-				break;
-			case VR_RXSTAT_FRAMEALIGNERR:
-				printf("frame alignment error\n");
-				break;
-			case VR_RXSTAT_FIFOOFLOW:
-				printf("FIFO overflow\n");
-				break;
-			case VR_RXSTAT_GIANT:
-				printf("received giant packet\n");
-				break;
-			case VR_RXSTAT_RUNT:
-				printf("received runt packet\n");
-				break;
-			case VR_RXSTAT_BUSERR:
-				printf("system bus error\n");
-				break;
-			case VR_RXSTAT_BUFFERR:
-				printf("rx buffer error\n");
-				break;
-			default:
-				printf("unknown rx error\n");
-				break;
-			}
+			printf("vr%d: rx error (%02x):",
+			       sc->vr_unit, rxstat & 0x000000ff);
+			if (rxstat & VR_RXSTAT_CRCERR)
+				printf(" crc error");
+			if (rxstat & VR_RXSTAT_FRAMEALIGNERR)
+				printf(" frame alignment error\n");
+			if (rxstat & VR_RXSTAT_FIFOOFLOW)
+				printf(" FIFO overflow");
+			if (rxstat & VR_RXSTAT_GIANT)
+				printf(" received giant packet");
+			if (rxstat & VR_RXSTAT_RUNT)
+				printf(" received runt packet");
+			if (rxstat & VR_RXSTAT_BUSERR)
+				printf(" system bus error");
+			if (rxstat & VR_RXSTAT_BUFFERR)
+				printf("rx buffer error");
+			printf("\n");
 			vr_newbuf(sc, cur_rx, m);
 			continue;
 		}
@@ -1058,9 +1141,29 @@
 void vr_rxeoc(sc)
 	struct vr_softc		*sc;
 {
+	struct ifnet		*ifp;
+	int			i;
+
+	ifp = &sc->arpcom.ac_if;
+
+	ifp->if_ierrors++;
+
+	VR_CLRBIT16(sc, VR_COMMAND, VR_CMD_RX_ON);	
+        DELAY(10000);
+
+	for (i = 0x400;
+	     i && (CSR_READ_2(sc, VR_COMMAND) & VR_CMD_RX_ON);
+	     i--)
+		;	/* Wait for receiver to stop */
+
+	if (!i) {
+		printf("vr%d: rx shutdown error!\n", sc->vr_unit);
+		sc->vr_flags |= VR_F_RESTART;
+		return;
+		}
 
 	vr_rxeof(sc);
-	VR_CLRBIT16(sc, VR_COMMAND, VR_CMD_RX_ON);
+
 	CSR_WRITE_4(sc, VR_RXADDR, vtophys(sc->vr_cdata.vr_rx_head->vr_ptr));
 	VR_SETBIT16(sc, VR_COMMAND, VR_CMD_RX_ON);
 	VR_SETBIT16(sc, VR_COMMAND, VR_CMD_RX_GO);
@@ -1094,14 +1197,22 @@
 	 */
 	while(sc->vr_cdata.vr_tx_head->vr_mbuf != NULL) {
 		u_int32_t		txstat;
+		int			i;
 
 		cur_tx = sc->vr_cdata.vr_tx_head;
 		txstat = cur_tx->vr_ptr->vr_status;
 
 		if ((txstat & VR_TXSTAT_ABRT) ||
 		    (txstat & VR_TXSTAT_UDF)) {
-			while (CSR_READ_2(sc, VR_COMMAND) & VR_CMD_TX_ON)
+			for (i = 0x400;
+			     i && (CSR_READ_2(sc, VR_COMMAND) & VR_CMD_TX_ON);
+			     i--)
 				;	/* Wait for chip to shutdown */
+			if (!i) {
+				printf("vr%d: tx shutdown timeout\n", sc->vr_unit);
+				sc->vr_flags |= VR_F_RESTART;
+				break;
+			}
 			VR_TXOWN(cur_tx) = VR_TXSTAT_OWN;
 			CSR_WRITE_4(sc, VR_TXADDR, vtophys(cur_tx->vr_ptr));
 			break;
@@ -1167,6 +1278,14 @@
 	s = splimp();
 
 	sc = xsc;
+	if (sc->vr_flags & VR_F_RESTART) {
+		printf("vr%d: restarting\n", sc->vr_unit);
+		vr_stop(sc);
+		vr_reset(sc);
+		vr_init(sc);
+		sc->vr_flags &= ~VR_F_RESTART;
+	}
+
 	mii = device_get_softc(sc->vr_miibus);
 	mii_tick(mii);
 
@@ -1208,10 +1327,22 @@
 		if (status & VR_ISR_RX_OK)
 			vr_rxeof(sc);
 
+		if (status & VR_ISR_RX_DROPPED) {
+			printf("vr%d: rx packet lost\n", sc->vr_unit);
+			ifp->if_ierrors++;
+			}
+
 		if ((status & VR_ISR_RX_ERR) || (status & VR_ISR_RX_NOBUF) ||
-		    (status & VR_ISR_RX_NOBUF) || (status & VR_ISR_RX_OFLOW) ||
-		    (status & VR_ISR_RX_DROPPED)) {
-			vr_rxeof(sc);
+		    (status & VR_ISR_RX_NOBUF) || (status & VR_ISR_RX_OFLOW)) {
+			printf("vr%d: receive error (%04x)",
+			       sc->vr_unit, status);
+			if (status & VR_ISR_RX_NOBUF)
+				printf(" no buffers");
+			if (status & VR_ISR_RX_OFLOW)
+				printf(" overflow");
+			if (status & VR_ISR_RX_DROPPED)
+				printf(" packet lost");
+			printf("\n");
 			vr_rxeoc(sc);
 		}
 
@@ -1430,13 +1561,13 @@
 	 * so we must set both.
 	 */
 	VR_CLRBIT(sc, VR_BCR0, VR_BCR0_RX_THRESH);
-	VR_SETBIT(sc, VR_BCR0, VR_BCR0_RXTHRESHSTORENFWD);
+	VR_SETBIT(sc, VR_BCR0, VR_BCR0_RXTHRESH128BYTES);
 
 	VR_CLRBIT(sc, VR_BCR1, VR_BCR1_TX_THRESH);
 	VR_SETBIT(sc, VR_BCR1, VR_BCR1_TXTHRESHSTORENFWD);
 
 	VR_CLRBIT(sc, VR_RXCFG, VR_RXCFG_RX_THRESH);
-	VR_SETBIT(sc, VR_RXCFG, VR_RXTHRESH_STORENFWD);
+	VR_SETBIT(sc, VR_RXCFG, VR_RXTHRESH_128BYTES);
 
 	VR_CLRBIT(sc, VR_TXCFG, VR_TXCFG_TX_THRESH);
 	VR_SETBIT(sc, VR_TXCFG, VR_TXTHRESH_STORENFWD);
Index: if_vrreg.h
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_vrreg.h,v
retrieving revision 1.7.2.4
diff -u -r1.7.2.4 if_vrreg.h
--- if_vrreg.h	28 Nov 2002 03:00:59 -0000	1.7.2.4
+++ if_vrreg.h	1 Feb 2003 01:41:21 -0000
@@ -464,11 +464,14 @@
 	u_int8_t		vr_unit;	/* interface number */
 	u_int8_t		vr_type;
 	u_int8_t		vr_revid;	/* Rhine chip revision */
+	u_int8_t		vr_flags;	/* See VR_F_* below */
 	struct vr_list_data	*vr_ldata;
 	struct vr_chain_data	vr_cdata;
 	struct callout_handle	vr_stat_ch;
 };
 
+#define VR_F_RESTART		0x01		/* Restart unit on next tick */
+
 /*
  * register space access macros
  */
@@ -502,6 +505,8 @@
 #define	VIA_DEVICEID_RHINE		0x3043
 #define VIA_DEVICEID_RHINE_II		0x6100
 #define VIA_DEVICEID_RHINE_II_2		0x3065
+#define VIA_DEVICEID_RHINE_III		0x3106
+#define VIA_DEVICEID_RHINE_III_M	0x3053
 
 /*
  * Delta Electronics device ID.
@@ -533,6 +538,7 @@
 #define REV_ID_VT3065_A			0x40
 #define REV_ID_VT3065_B			0x41
 #define REV_ID_VT3065_C			0x42
+#define REV_ID_VT6102_APOLLO		0x74
 #define REV_ID_VT3106			0x80
 #define REV_ID_VT3106_J			0x80    /* 0x80-0x8F */
 #define REV_ID_VT3106_S			0x90    /* 0x90-0xA0 */
@@ -559,6 +565,9 @@
 #define VR_PCI_MINLAT		0x0F
 #define VR_PCI_RESETOPT		0x48
 #define VR_PCI_EEPROM_DATA	0x4C
+#define VR_PCI_MODE		0x50
+
+#define VR_MODE3_MIION		0x04
 
 /* power management registers */
 #define VR_PCI_CAPID		0xDC /* 8 bits */

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030131201821.A5899-200000>