From owner-freebsd-bugs@FreeBSD.ORG Fri Jun 6 05:10:13 2003 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 4063E37B401 for ; Fri, 6 Jun 2003 05:10:13 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1C92143FBD for ; Fri, 6 Jun 2003 05:10:12 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.9/8.12.9) with ESMTP id h56CABUp082668 for ; Fri, 6 Jun 2003 05:10:11 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.9/8.12.9/Submit) id h56CABRS082667; Fri, 6 Jun 2003 05:10:11 -0700 (PDT) Resent-Date: Fri, 6 Jun 2003 05:10:11 -0700 (PDT) Resent-Message-Id: <200306061210.h56CABRS082667@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Andrew Gordon Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1119837B401 for ; Fri, 6 Jun 2003 05:04:15 -0700 (PDT) Received: from arg1.demon.co.uk (arg1.demon.co.uk [62.49.12.213]) by mx1.FreeBSD.org (Postfix) with ESMTP id 007B643F75 for ; Fri, 6 Jun 2003 05:04:14 -0700 (PDT) (envelope-from arg@arg1.demon.co.uk) Received: by arg1.demon.co.uk (Postfix, from userid 300) id 05ADD9B25; Fri, 6 Jun 2003 13:04:10 +0100 (BST) Message-Id: <20030606120410.05ADD9B25@arg1.demon.co.uk> Date: Fri, 6 Jun 2003 13:04:10 +0100 (BST) From: Andrew Gordon To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: kern/52988: [patch] if_dc with ADMTek AN983B corrupts MAC address X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Andrew Gordon List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 Jun 2003 12:10:13 -0000 >Number: 52988 >Category: kern >Synopsis: [patch] if_dc with ADMTek AN983B corrupts MAC address >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Jun 06 05:10:09 PDT 2003 >Closed-Date: >Last-Modified: >Originator: Andrew Gordon >Release: FreeBSD 4.8-STABLE i386 >Organization: >Environment: System: FreeBSD server.arg.sj.co.uk 4.8-STABLE FreeBSD 4.8-STABLE #7: Thu May 1 19:02:35 BST 2003 arg@server.arg.sj.co.uk:/usr/src/sys/compile/SERVER i386 This is a long-standing problem in 4.x - not version specific. >Description: if_dc driver fails to read MAC address from AN983B (on-board ethernet on MSI motherboard in this case). Not only does it get the wrong value of MAC address, but it permanently trashes the EEPROM contents, so that it is necessary to use the manufacturer's utility to re-set the MAC address in the EEPROM before it will work again in Windows. if_dc only claims to support the AN985B, not the AN983B, though they appear from the datasheet to be the equivalent and have the same device ID ('985 is cardbus, '983 is ordinary PCI). If the EEPROM reading code in the driver is commented out, the driver works OK and the EEPROM is not corrupted. >How-To-Repeat: Simply boot a kernel containing if_dc on a machine with this hardware. dc0: will be probed (and works OK for sending packets), but the MAC address is bogus (usually 07:07:07:07:07) and if the machine is later re-booted with Windows or the BIOS's PXE boot the MAC address is no longer correct there either. The machines showing the problem had MSI motherboards where this was the on-motherboard ethernet; however so far as I can tell the motherboard contains a completely standard implementation of the AN983B just as if it were on a PCI card (eg. the AN983B appears to have its own dedicated EEPROM for the MAC address). >Fix: For this device, the only thing that the driver attempts to read from the EEPROM is the MAC address. However, according to the datasheet (and confirmed by testing) the MAC address is automatically loaded into the PAR0/PAR1 registers after reset, so we can simply read it from those registers directly rather than doing the bit twiddling to access the EEPROM by brute force. The enclosed patch does this, and works well for me (I have made this as the minimum possible change to the driver, so it ends up reading the MAC address from PAR0/PAR1 and then writing back into PAR0/PAR1 again later). I'm working in RELENG_4, but there have been no relevant changes to the driver and the patch applies unchanged to -current too. I only have this one type of motherboard for testing; I don't have any AN985B cards to see if my patch upsets them. Also, the driver treats the "Accton EN2242" as equivalent to the AN985B - I'm guessing that this is just a card built from the AN983B but using different vendor/device Ids for branding purposes, so I've made my patch apply to these too, but again I can't test. The code that I've replaced looks a bit odd: it seems to read the MAC address from a copy of the EEPROM in the softc that it recorded earlier, then immediately over-writes that by reading it directly from the EEPROM again. Did this ever work? --- if_dc.patch begins here --- Index: if_dc.c =================================================================== RCS file: /usr/cvsbase/repository/src/sys/pci/if_dc.c,v retrieving revision 1.9.2.41 diff -u -r1.9.2.41 if_dc.c --- if_dc.c 5 Mar 2003 18:42:33 -0000 1.9.2.41 +++ if_dc.c 1 Jun 2003 23:35:14 -0000 @@ -1871,7 +1871,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); + /* Don't read SROM for - auto-loaded on reset */ break; case DC_DEVICEID_98713: case DC_DEVICEID_98713_CP: @@ -1994,9 +1994,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); + *(u_int32_t *)(&eaddr[0]) = CSR_READ_4(sc, DC_AL_PAR0); + *(u_int16_t *)(&eaddr[4]) = CSR_READ_4(sc, DC_AL_PAR1); break; case DC_TYPE_CONEXANT: bcopy(sc->dc_srom + DC_CONEXANT_EE_NODEADDR, &eaddr, 6); --- if_dc.patch ends here --- >Release-Note: >Audit-Trail: >Unformatted: