From fgasper@nh-mealworm.csh.uiuc.edu  Tue Nov 19 07:46:09 2002
Return-Path: <fgasper@nh-mealworm.csh.uiuc.edu>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id E858937B401
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 19 Nov 2002 07:46:09 -0800 (PST)
Received: from nh-mealworm.csh.uiuc.edu (nh-mealworm.csh.uiuc.edu [128.174.168.82])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 4402943E6E
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 19 Nov 2002 07:46:09 -0800 (PST)
	(envelope-from fgasper@nh-mealworm.csh.uiuc.edu)
Received: from nh-mealworm.csh.uiuc.edu (localhost [127.0.0.1])
	by nh-mealworm.csh.uiuc.edu (8.12.6/8.12.6) with ESMTP id gAJFk8st000241
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 19 Nov 2002 09:46:08 -0600 (CST)
	(envelope-from fgasper@nh-mealworm.csh.uiuc.edu)
Received: (from fgasper@localhost)
	by nh-mealworm.csh.uiuc.edu (8.12.6/8.12.6/Submit) id gAJFk8tU000240;
	Tue, 19 Nov 2002 09:46:08 -0600 (CST)
Message-Id: <200211191546.gAJFk8tU000240@nh-mealworm.csh.uiuc.edu>
Date: Tue, 19 Nov 2002 09:46:08 -0600 (CST)
From: Felipe Gasper <fgasper@uiuc.edu>
Reply-To: Felipe Gasper <fgasper@uiuc.edu>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: Invalid MAC reported by new Linksys LNE-100TX (dc)
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         45483
>Category:       kern
>Synopsis:       Invalid MAC reported by new Linksys LNE-100TX (dc)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    mbr
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 19 07:50:01 PST 2002
>Closed-Date:    Wed Feb 12 15:03:47 PST 2003
>Last-Modified:  Wed Feb 12 15:03:47 PST 2003
>Originator:     Felipe
>Release:        FreeBSD 4.7-RELEASE i386
>Organization:
>Environment:
System: FreeBSD nh-mealworm.csh.uiuc.edu 4.7-RELEASE FreeBSD 4.7-RELEASE #0: Fri Oct 11 08:07:02 CDT 2002 root@nh-mealworm.csh.uiuc.edu:/usr/obj/usr/src/sys/CUSTOM-11-10-2002 i386


	
>Description:
	
	I have a Linksys LNE-100TX rev 5.1 that is reporting
	08:00:08:00:08:00 as its MAC address, judging from dmesg:

dc0: <ADMtek AN985 10/100BaseTX> port 0x6100-0x61ff mem 0xe4000000-0xe40003ff ir
q 10 at device 18.0 on pci0
dc0: Ethernet address: 08:00:08:00:08:00
miibus0: <MII bus> on dc0
ukphy0: <Generic IEEE 802.3u media interface> on miibus0
ukphy0:  10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto 

	I moved the card to a newer Windows box, and it reports a valid MAC.
	This problem, perhaps, is a result of this newer card expecting
	PCI 2.2? The hardware that I have is pretty old- about 5 years.
	I know that this issue has been discussed on some mailing lists,
	but I was unable to find an actual bug report dealing with it.

>How-To-Repeat:
	Put in a recent model of Linksys's LNE-100TX NIC (rev. 5.1 is what
	I have). This problem may be hardware-dependent, but I am getting
	an invalid MAC at boot.

>Fix:
	Not sure....could be hardware-related; if so, perhaps there is a
	workaround possible from within the kernel?
	


>Release-Note:
>Audit-Trail:

From: Scott Christopher Dodson <sdodson@eagle4.cc.gasou.edu>
To: <freebsd-gnats-submit@FreeBSD.org>
Cc: <fgasper@uiuc.edu>
Subject: Re: kern/45483: Invalid MAC reported by new Linksys LNE-100TX (dc)
Date: Fri, 3 Jan 2003 03:05:38 -0500 (EST)

 I'm having the same problem with an older revision of this card under
 5-Current.  This is one of the initial revisions of the card I believe.
 
 dc0: <LC82C115 PNIC II 10/100BaseTX> port 0xcc00-0xccff mem
 0xdf000000-0xdf0000ff irq 10 at device 17.0 on pci0
 dc0: Ethernet address: 00:00:00:00:00:00
 miibus0: <MII bus> on dc0
 dcphy0: <Intel 21143 NWAY media interface> on miibus0
 dcphy0:  10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
 
 
 FreeBSD home.sdodson.com 5.0-CURRENT FreeBSD 5.0-CURRENT #17: Sun Dec 29
 22:15:11 EST 2002     sdodson@home.sdodson.com:/usr/obj/usr/src/sys/RAGE2 
 i386
 
 
 
 -----------------------------------------
 This email was sent using SquirrelMail.
 "Georgia Southern University"
 http://www.gasou.edu/
 
 
Responsible-Changed-From-To: freebsd-bugs->mbr 
Responsible-Changed-By: mbr 
Responsible-Changed-When: Thu Jan 30 15:48:34 PST 2003 
Responsible-Changed-Why:  
I'll look at this. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=45483 
State-Changed-From-To: open->analyzed 
State-Changed-By: mbr 
State-Changed-When: Fri Feb 7 09:17:49 PST 2003 
State-Changed-Why:  
Hi, 

A fix has been committed to CURRENT. Can you also try 
this patch ? : 

http://people.freebsd.org/~mbr/patches/if_dc.c.diff 

--- sys/pci/if_dc.c.orig	Fri Feb  7 17:43:19 2003 
+++ sys/pci/if_dc.c	Fri Feb  7 17:40:48 2003 
@@ -1958,13 +1958,15 @@ 
sc->dc_info = dc_devtype(dev); 
revision = pci_read_config(dev, DC_PCI_CFRV, 4) & 0x000000FF; 

+	if (! (DC_IS_PNIC(sc) || DC_IS_XIRCOM(sc))) 
+		dc_eeprom_width(sc); 
+ 
switch(sc->dc_info->dc_did) { 
case DC_DEVICEID_21143: 
sc->dc_type = DC_TYPE_21143; 
sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR; 
sc->dc_flags |= DC_REDUCED_MII_POLL; 
/* Save EEPROM contents so we can parse them later. */ 
-		dc_eeprom_width(sc); 
dc_read_srom(sc, sc->dc_romwidth); 
break; 
case DC_DEVICEID_DM9009: 
@@ -1985,7 +1987,6 @@ 
sc->dc_flags |= DC_TX_USE_TX_INTR; 
sc->dc_flags |= DC_TX_ADMTEK_WAR; 
sc->dc_pmode = DC_PMODE_MII; 
-		dc_eeprom_width(sc); 
dc_read_srom(sc, sc->dc_romwidth); 
break; 
case DC_DEVICEID_AN985: 
@@ -1996,7 +1997,6 @@ 
sc->dc_flags |= DC_TX_USE_TX_INTR; 
sc->dc_flags |= DC_TX_ADMTEK_WAR; 
sc->dc_pmode = DC_PMODE_MII; 
-		dc_eeprom_width(sc); 
dc_read_srom(sc, sc->dc_romwidth); 
break; 
case DC_DEVICEID_98713: 
@@ -2067,7 +2067,6 @@ 
sc->dc_flags |= DC_TX_INTR_ALWAYS; 
sc->dc_flags |= DC_REDUCED_MII_POLL; 
sc->dc_pmode = DC_PMODE_MII; 
-		dc_eeprom_width(sc); 
dc_read_srom(sc, sc->dc_romwidth); 
break; 
default: 

Martin 


http://www.freebsd.org/cgi/query-pr.cgi?pr=45483 

From: Martin Blapp <mb@imp.ch>
To: freebsd-gnats-submit@FreeBSD.org
Cc: fgasper@uiuc.edu
Subject: Re: kern/45483: Invalid MAC reported by new Linksys LNE-100TX (dc)
Date: Fri, 7 Feb 2003 20:14:58 +0100 (CET)

 Hi,
 
 I have made a patch for STABLE in the meantime. Can you try it out if
 it fixes your problem ?
 
 http://people.freebsd.org/~mbr/patches/if_dc.c-MFC.diff
 
 ------------------------------------------------------------------
 
 MFC Rev. 1.80, 1.81
 
 Dynamically configure the width of the srom.  This code comes from
 OpenBSD who got the code (or the idea) from the NetBSD tlp driver.
 
 Rev. 1.67
 
 Fix Conexant chips which always reports carrier lost
 on full duplex mode.
 
 Index: if_dc.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/pci/if_dc.c,v
 retrieving revision 1.9.2.38
 diff -u -r1.9.2.38 if_dc.c
 --- if_dc.c	5 Feb 2003 22:10:04 -0000	1.9.2.38
 +++ if_dc.c	7 Feb 2003 19:01:18 -0000
 @@ -223,6 +223,7 @@
  static void dc_eeprom_getword	__P((struct dc_softc *, int, u_int16_t *));
  static void dc_eeprom_getword_pnic
  				__P((struct dc_softc *, int, u_int16_t *));
 +static void dc_eeprom_width	__P((struct dc_softc *));
  static void dc_read_eeprom	__P((struct dc_softc *, caddr_t, int,
  							int, int));
 
 @@ -250,6 +251,7 @@
  static int dc_list_rx_init	__P((struct dc_softc *));
  static int dc_list_tx_init	__P((struct dc_softc *));
 
 +static void dc_read_srom	__P((struct dc_softc *, int));
  static void dc_parse_21143_srom	__P((struct dc_softc *));
  static void dc_decode_leaf_sia	__P((struct dc_softc *,
  				    struct dc_eblock_sia *));
 @@ -324,6 +326,70 @@
  		CSR_READ_4(sc, DC_BUSCTL);
  }
 
 +void dc_eeprom_width(sc)
 +	struct dc_softc		*sc;
 +{
 +	int i;
 +
 +	/* Force EEPROM to idle state. */
 +	dc_eeprom_idle(sc);
 +
 +	/* Enter EEPROM access mode. */
 +	CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
 +	dc_delay(sc);
 +	DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
 +	dc_delay(sc);
 +	DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
 +	dc_delay(sc);
 +	DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
 +	dc_delay(sc);
 +
 +	for (i = 3; i--;) {
 +		if (6 & (1 << i))
 +			DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
 +		else
 +			DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
 +		dc_delay(sc);
 +		DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
 +		dc_delay(sc);
 +		DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
 +		dc_delay(sc);
 +	}
 +
 +	for (i = 1; i <= 12; i++) {
 +		DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
 +		dc_delay(sc);
 +		if (!(CSR_READ_4(sc, DC_SIO) & DC_SIO_EE_DATAOUT)) {
 +			DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
 +			dc_delay(sc);
 +			break;
 +		}
 +		DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
 +		dc_delay(sc);
 +	}
 +
 +	/* Turn off EEPROM access mode. */
 +	dc_eeprom_idle(sc);
 +
 +	if (i < 4 || i > 12)
 +		sc->dc_romwidth = 6;
 +	else
 +		sc->dc_romwidth = i;
 +
 +	/* Enter EEPROM access mode. */
 +	CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
 +	dc_delay(sc);
 +	DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
 +	dc_delay(sc);
 +	DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
 +	dc_delay(sc);
 +	DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
 +	dc_delay(sc);
 +
 +	/* Turn off EEPROM access mode. */
 +	dc_eeprom_idle(sc);
 +}
 +
  static void dc_eeprom_idle(sc)
  	struct dc_softc		*sc;
  {
 @@ -363,21 +429,24 @@
  {
  	register int		d, i;
 
 -	/*
 -	 * The AN985 has a 93C66 EEPROM on it instead of
 -	 * a 93C46. It uses a different bit sequence for
 -	 * specifying the "read" opcode.
 -	 */
 -	if (DC_IS_CENTAUR(sc) || DC_IS_CONEXANT(sc))
 -		d = addr | (DC_EECMD_READ << 2);
 -	else
 -		d = addr | DC_EECMD_READ;
 +	d = DC_EECMD_READ >> 6;
 +	for (i = 3; i--; ) {
 +		if (d & (1 << i))
 +			DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
 +		else
 +			DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
 +		dc_delay(sc);
 +		DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
 +		dc_delay(sc);
 +		DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
 +		dc_delay(sc);
 +	}
 
  	/*
  	 * Feed in each bit and strobe the clock.
  	 */
 -	for (i = 0x400; i; i >>= 1) {
 -		if (d & i) {
 +	for (i = sc->dc_romwidth; i--;) {
 +		if (addr & (1 << i)) {
  			SIO_SET(DC_SIO_EE_DATAIN);
  		} else {
  			SIO_CLR(DC_SIO_EE_DATAIN);
 @@ -1572,6 +1641,7 @@
 
  	m->dc_next = sc->dc_mi;
  	sc->dc_mi = m;
 +	free(sc->dc_srom, M_DEVBUF);
 
  	sc->dc_pmode = DC_PMODE_SIA;
 
 @@ -1630,6 +1700,17 @@
  	return;
  }
 
 +static void dc_read_srom(sc, bits)
 +	struct dc_softc		*sc;
 +	int			bits;
 +{
 +	int size;
 +
 +	size = 2 << bits;
 +	sc->dc_srom = malloc(size, M_DEVBUF, M_NOWAIT);
 +	dc_read_eeprom(sc, (caddr_t)sc->dc_srom, 0, (size / 2), 0);
 +}
 +
  static void dc_parse_21143_srom(sc)
  	struct dc_softc		*sc;
  {
 @@ -1753,13 +1834,17 @@
  	sc->dc_info = dc_devtype(dev);
  	revision = pci_read_config(dev, DC_PCI_CFRV, 4) & 0x000000FF;
 
 +	/* Get the eeprom width, but PNIC has no eeprom */
 +	if (sc->dc_info->dc_did != DC_DEVICEID_82C168)
 +		dc_eeprom_width(sc);
 +
  	switch(sc->dc_info->dc_did) {
  	case DC_DEVICEID_21143:
  		sc->dc_type = DC_TYPE_21143;
  		sc->dc_flags |= DC_TX_POLL|DC_TX_USE_TX_INTR;
  		sc->dc_flags |= DC_REDUCED_MII_POLL;
  		/* Save EEPROM contents so we can parse them later. */
 -		dc_read_eeprom(sc, (caddr_t)&sc->dc_srom, 0, 512, 0);
 +		dc_read_srom(sc, sc->dc_romwidth);
  		break;
  	case DC_DEVICEID_DM9009:
  	case DC_DEVICEID_DM9100:
 @@ -1779,6 +1864,7 @@
  		sc->dc_flags |= DC_TX_USE_TX_INTR;
  		sc->dc_flags |= DC_TX_ADMTEK_WAR;
  		sc->dc_pmode = DC_PMODE_MII;
 +		dc_read_srom(sc, sc->dc_romwidth);
  		break;
  	case DC_DEVICEID_AN985:
  	case DC_DEVICEID_EN2242:
 @@ -1786,6 +1872,7 @@
  		sc->dc_flags |= DC_TX_USE_TX_INTR;
  		sc->dc_flags |= DC_TX_ADMTEK_WAR;
  		sc->dc_pmode = DC_PMODE_MII;
 +		dc_read_srom(sc, sc->dc_romwidth);
  		break;
  	case DC_DEVICEID_98713:
  	case DC_DEVICEID_98713_CP:
 @@ -1844,7 +1931,7 @@
  		sc->dc_flags |= DC_TX_INTR_ALWAYS;
  		sc->dc_flags |= DC_REDUCED_MII_POLL;
  		sc->dc_pmode = DC_PMODE_MII;
 -		dc_read_eeprom(sc, (caddr_t)&sc->dc_srom, 0, 256, 0);
 +		dc_read_srom(sc, sc->dc_romwidth);
  		break;
  	default:
  		printf("dc%d: unknown device: %x\n", sc->dc_unit,
 @@ -1908,6 +1995,8 @@
  		break;
  	case DC_TYPE_AL981:
  	case DC_TYPE_AN985:
 +		bcopy(&sc->dc_srom[DC_AL_EE_NODEADDR], (caddr_t)&eaddr,
 +		    ETHER_ADDR_LEN);
  		dc_read_eeprom(sc, (caddr_t)&eaddr, DC_AL_EE_NODEADDR, 3, 0);
  		break;
  	case DC_TYPE_CONEXANT:
 @@ -2468,13 +2557,13 @@
   * the list buffers.
   */
 
 -static void dc_txeof(sc)
 +static void
 +dc_txeof(sc)
  	struct dc_softc		*sc;
  {
  	struct dc_desc		*cur_tx = NULL;
  	struct ifnet		*ifp;
  	int			idx;
 -	u_int32_t		errmask;
 
  	ifp = &sc->arpcom.ac_if;
 
 @@ -2494,7 +2583,6 @@
 
  		if (!(cur_tx->dc_ctl & DC_TXCTL_LASTFRAG) ||
  		    cur_tx->dc_ctl & DC_TXCTL_SETUP) {
 -			sc->dc_cdata.dc_tx_cnt--;
  			if (cur_tx->dc_ctl & DC_TXCTL_SETUP) {
  				/*
  				 * Yes, the PNIC is so brain damaged
 @@ -2511,21 +2599,29 @@
  				}
  				sc->dc_cdata.dc_tx_chain[idx] = NULL;
  			}
 +			sc->dc_cdata.dc_tx_cnt--;
  			DC_INC(idx, DC_TX_LIST_CNT);
  			continue;
  		}
 
 -		if (sc->dc_pmode == DC_PMODE_MII) {
 -			errmask = DC_TXSTAT_ERRSUM|
 -			    DC_TXSTAT_NOCARRIER|DC_TXSTAT_CARRLOST;
 +		if (DC_IS_CONEXANT(sc)) {
  			/*
 -			 * The Conexant chip always reports carrier lost
 -			 * in full duplex modes.
 +			 * For some reason Conexant chips like
 +			 * setting the CARRLOST flag even when
 +			 * the carrier is there. In CURRENT we
 +			 * have the same problem for Xircom
 +			 * cards !
  			 */
 -			if (DC_IS_CONEXANT(sc) && (sc->dc_if_media & IFM_FDX)) {
 -				errmask &= ~DC_TXSTAT_CARRLOST;
 -			}
 -			if ((txstat & 0xFFFF) & ~errmask)
 +			if (/*sc->dc_type == DC_TYPE_21143 &&*/
 +			    sc->dc_pmode == DC_PMODE_MII &&
 +			    ((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM|
 +			    DC_TXSTAT_NOCARRIER)))
 +				txstat &= ~DC_TXSTAT_ERRSUM;
 +		} else {
 +			if (/*sc->dc_type == DC_TYPE_21143 &&*/
 +			    sc->dc_pmode == DC_PMODE_MII &&
 +			    ((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM|
 +			    DC_TXSTAT_NOCARRIER|DC_TXSTAT_CARRLOST)))
  				txstat &= ~DC_TXSTAT_ERRSUM;
  		}
 
 @@ -2553,11 +2649,13 @@
  		DC_INC(idx, DC_TX_LIST_CNT);
  	}
 
 -        if (idx != sc->dc_cdata.dc_tx_cons) {
 +	if (idx != sc->dc_cdata.dc_tx_cons) {
 +	    	/* some buffers have been freed */
  		sc->dc_cdata.dc_tx_cons = idx;
 -                ifp->if_flags &= ~IFF_OACTIVE;
 -        }
 -        ifp->if_timer = (sc->dc_cdata.dc_tx_cnt == 0) ? 0 : 5;
 +		ifp->if_flags &= ~IFF_OACTIVE;
 +	}
 +	ifp->if_timer = (sc->dc_cdata.dc_tx_cnt == 0) ? 0 : 5;
 +
  	return;
  }
 
 Index: if_dcreg.h
 ===================================================================
 RCS file: /home/ncvs/src/sys/pci/if_dcreg.h,v
 retrieving revision 1.4.2.20
 diff -u -r1.4.2.20 if_dcreg.h
 --- if_dcreg.h	5 Feb 2003 22:10:04 -0000	1.4.2.20
 +++ if_dcreg.h	7 Feb 2003 19:01:18 -0000
 @@ -688,13 +688,14 @@
  	u_int8_t		dc_pmode;
  	u_int8_t		dc_link;
  	u_int8_t		dc_cachesize;
 +	int			dc_romwidth;
  	int			dc_pnic_rx_bug_save;
  	unsigned char		*dc_pnic_rx_buf;
  	int			dc_if_flags;
  	int			dc_if_media;
  	u_int32_t		dc_flags;
  	u_int32_t		dc_txthresh;
 -	u_int8_t		dc_srom[1024];
 +	u_int8_t		*dc_srom;
  	struct dc_mediainfo	*dc_mi;
  	struct dc_list_data	*dc_ldata;
  	struct dc_chain_data	dc_cdata;
 
 Martin
 
 Martin Blapp, <mb@imp.ch> <mbr@FreeBSD.org>
 ------------------------------------------------------------------
 ImproWare AG, UNIXSP & ISP, Zurlindenstrasse 29, 4133 Pratteln, CH
 Phone: +41 61 826 93 00 Fax: +41 61 826 93 01
 PGP: <finger -l mbr@freebsd.org>
 PGP Fingerprint: B434 53FC C87C FE7B 0A18 B84C 8686 EF22 D300 551E
 ------------------------------------------------------------------
State-Changed-From-To: analyzed->closed 
State-Changed-By: mbr 
State-Changed-When: Wed Feb 12 15:03:13 PST 2003 
State-Changed-Why:  
Fixed in both STABLE and CURRENT. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=45483 
>Unformatted:
