Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 14 Oct 2010 17:22:38 +0000 (UTC)
From:      Pyun YongHyeon <yongari@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r213841 - head/sys/dev/dc
Message-ID:  <201010141722.o9EHMcZO031099@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Thu Oct 14 17:22:38 2010
New Revision: 213841
URL: http://svn.freebsd.org/changeset/base/213841

Log:
  It seems some multi-port dc(4) controllers shares SROM of the first
  port such that reading station address from second port always
  returned 0xFF:0xFF:0xFF:0xFF:0xFF:0xFF Unfortunately it seems there
  is no easy way to know whether SROM is shared or not. Workaround
  the issue by traversing dc(4) device list and see whether we're
  using second port and use station address of controller 0 as base
  station address of second port.
  
  PR:		kern/79262
  MFC after:	2 weeks

Modified:
  head/sys/dev/dc/if_dc.c
  head/sys/dev/dc/if_dcreg.h

Modified: head/sys/dev/dc/if_dc.c
==============================================================================
--- head/sys/dev/dc/if_dc.c	Thu Oct 14 16:44:44 2010	(r213840)
+++ head/sys/dev/dc/if_dc.c	Thu Oct 14 17:22:38 2010	(r213841)
@@ -293,6 +293,7 @@ static void dc_decode_leaf_sia(struct dc
 static void dc_decode_leaf_mii(struct dc_softc *, struct dc_eblock_mii *);
 static void dc_decode_leaf_sym(struct dc_softc *, struct dc_eblock_sym *);
 static void dc_apply_fixup(struct dc_softc *, int);
+static int dc_check_multiport(struct dc_softc *);
 
 #ifdef DC_USEIOSPACE
 #define DC_RES			SYS_RES_IOPORT
@@ -2088,6 +2089,20 @@ dc_attach(device_t dev)
 		break;
 	}
 
+	bcopy(eaddr, sc->dc_eaddr, sizeof(eaddr));
+	/*
+	 * If we still have invalid station address, see whether we can
+	 * find station address for chip 0.  Some multi-port controllers
+	 * just store station address for chip 0 if they have a shared
+	 * SROM.
+	 */
+	if ((sc->dc_eaddr[0] == 0 && (sc->dc_eaddr[1] & ~0xffff) == 0) ||
+	    (sc->dc_eaddr[0] == 0xffffffff &&
+	    (sc->dc_eaddr[1] & 0xffff) == 0xffff)) {
+		if (dc_check_multiport(sc) == 0)
+			bcopy(sc->dc_eaddr, eaddr, sizeof(eaddr));
+	}
+
 	/* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */
 	error = bus_dma_tag_create(bus_get_dma_tag(dev), PAGE_SIZE, 0,
 	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
@@ -3808,3 +3823,34 @@ dc_shutdown(device_t dev)
 
 	return (0);
 }
+
+static int
+dc_check_multiport(struct dc_softc *sc)
+{
+	struct dc_softc *dsc;
+	devclass_t dc;
+	device_t child;
+	uint8_t *eaddr;
+	int unit;
+
+	dc = devclass_find("dc");
+	for (unit = 0; unit < devclass_get_maxunit(dc); unit++) {
+		child = devclass_get_device(dc, unit);
+		if (child == NULL)
+			continue;
+		if (child == sc->dc_dev)
+			continue;
+		if (device_get_parent(child) != device_get_parent(sc->dc_dev))
+			continue;
+		if (unit > device_get_unit(sc->dc_dev))
+			continue;
+		dsc = device_get_softc(child);
+		device_printf(sc->dc_dev, "Using station address of %s as base",
+		    device_get_nameunit(child));
+		bcopy(dsc->dc_eaddr, sc->dc_eaddr, ETHER_ADDR_LEN);
+		eaddr = (uint8_t *)sc->dc_eaddr;
+		eaddr[5]++;
+		return (0);
+	}
+	return (ENOENT);
+}

Modified: head/sys/dev/dc/if_dcreg.h
==============================================================================
--- head/sys/dev/dc/if_dcreg.h	Thu Oct 14 16:44:44 2010	(r213840)
+++ head/sys/dev/dc/if_dcreg.h	Thu Oct 14 17:22:38 2010	(r213841)
@@ -745,6 +745,7 @@ struct dc_softc {
 	int			dc_if_media;
 	u_int32_t		dc_flags;
 	u_int32_t		dc_txthresh;
+	u_int32_t		dc_eaddr[2];
 	u_int8_t		*dc_srom;
 	struct dc_mediainfo	*dc_mi;
 	struct dc_list_data	*dc_ldata;



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