From kettenis@elgar.kettenis.dyndns.org  Thu Mar 14 13:43:37 2002
Return-Path: <kettenis@elgar.kettenis.dyndns.org>
Received: from walton.kettenis.dyndns.org (e115180.upc-e.chello.nl [213.93.115.180])
	by hub.freebsd.org (Postfix) with ESMTP id 6A1E837B404
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 14 Mar 2002 13:43:34 -0800 (PST)
Received: from elgar.kettenis.dyndns.org (elgar.kettenis.dyndns.org [192.168.0.2])
	by walton.kettenis.dyndns.org (8.11.6/8.11.6) with ESMTP id g2ELhbQ00271
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 14 Mar 2002 22:43:38 +0100 (CET)
	(envelope-from kettenis@elgar.kettenis.dyndns.org)
Received: (from kettenis@localhost)
	by elgar.kettenis.dyndns.org (8.11.6/8.11.6) id g2ELhRf00921;
	Thu, 14 Mar 2002 22:43:27 +0100 (CET)
	(envelope-from kettenis)
Message-Id: <200203142143.g2ELhRf00921@elgar.kettenis.dyndns.org>
Date: Thu, 14 Mar 2002 22:43:27 +0100 (CET)
From: Mark Kettenis <kettenis@chello.nl>
To: FreeBSD-gnats-submit@freebsd.org
Subject: Changing RealTek 8139 MAC address fails
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         35900
>Category:       kern
>Synopsis:       Changing RealTek 8139 MAC address fails
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Mar 14 13:50:00 PST 2002
>Closed-Date:    Sun Jun 29 10:36:49 PDT 2003
>Last-Modified:  Sun Jun 29 10:36:49 PDT 2003
>Originator:     Mark Kettenis
>Release:        FreeBSD 4.4-RELEASE i386
>Organization:
>Environment:
System: FreeBSD elgar.kettenis.dyndns.org 4.4-RELEASE FreeBSD 4.4-RELEASE #8: Mon Mar 11 02:20:26 CET 2002 kettenis@elgar.kettenis.dyndns.org:/usr/obj/usr/src/sys/ELGAR i386
>Description:
	Changing the MAC address for my Sitecom PCI ethernet card,
        which is based on the RealTek 8139 chipset, doesn't work.
        Apparently the MAC address isn't actually changed in the
        hardware.  Since the MAC address used by the kernel does get
	changed, outgoing packets are sent with the new MAC address.
        Any reply-packets will therefore be dropped by the hardware,
        and never reach the kernel's networking code unless the
        interface is placed in promiscuous mode.
>How-To-Repeat:
	Enter the command:

	# ifconfig rl0 ether xx:xx:xx:xx:xx:xx

	And try to ping another host that would be reached through the
        rl0 interface.  It won't work unless the interface is placed in
	promiscuous mode.
>Fix:
	Apparently one has to enter "Config register write enable"
        mode to be able to write the MAC address into the appropriate
        hardware registers; the chipset documentation doesn't mention
        this, but the Linux driver does the same thing.

	The attached patch fixes the problem.  This patch is against
	4.4-RELEASE, but should apply fine to 5.0-CURRENT just as
	well.  The patch also changes the write access to the ID
	registers (whih contain the MAC address) from single-byte
	access to 4-byte access (which is what the chipset
	documentation demands).  The way I implemented this is a bit
	of a hack (since ac_enaddr is only 6 bytes long) but there are
	several drivers that use similar code.

	It would be great if this patch, or something similar, would
	be applied and end up in -STABLE someday.

--- /usr/src/sys/pci/if_rl.c.orig	Thu Jul 19 20:33:07 2001
+++ /usr/src/sys/pci/if_rl.c	Thu Mar 14 21:53:25 2002
@@ -1414,7 +1414,7 @@
 	struct rl_softc		*sc = xsc;
 	struct ifnet		*ifp = &sc->arpcom.ac_if;
 	struct mii_data		*mii;
-	int			s, i;
+	int			s;
 	u_int32_t		rxcfg = 0;
 
 	s = splimp();
@@ -1426,10 +1426,15 @@
 	 */
 	rl_stop(sc);
 
-	/* Init our MAC address */
-	for (i = 0; i < ETHER_ADDR_LEN; i++) {
-		CSR_WRITE_1(sc, RL_IDR0 + i, sc->arpcom.ac_enaddr[i]);
-	}
+	/*
+	 * Init our MAC address.  Even though the chipset
+	 * documentation doesn't mention it, we need to enter "Config
+	 * register write enable" mode to modify the ID registers.
+	 */
+	CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_WRITECFG);
+	CSR_WRITE_4(sc, RL_IDR0, *(u_int32_t *)(&sc->arpcom.ac_enaddr[0]));
+	CSR_WRITE_4(sc, RL_IDR4, *(u_int32_t *)(&sc->arpcom.ac_enaddr[4]));
+	CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
 
 	/* Init the RX buffer pointer register. */
 	CSR_WRITE_4(sc, RL_RXADDR, vtophys(sc->rl_cdata.rl_rx_buf));

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: wpaul 
State-Changed-When: Sun Jun 29 10:35:41 PDT 2003 
State-Changed-Why:  
Patch tested good with 8139B cardbus NIC, applied to -current. 
-Bill 

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