Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Nov 2012 03:34:13 +0000 (UTC)
From:      Oleksandr Tymoshenko <gonzo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r243421 - head/sys/dev/usb/net
Message-ID:  <201211230334.qAN3YDdR028015@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gonzo
Date: Fri Nov 23 03:34:12 2012
New Revision: 243421
URL: http://svnweb.freebsd.org/changeset/base/243421

Log:
  Look for MAC address in FDT tree nodes that are usb network devices and
  have either "mac-address" or "local-mac-addrress" property.

Modified:
  head/sys/dev/usb/net/if_smsc.c

Modified: head/sys/dev/usb/net/if_smsc.c
==============================================================================
--- head/sys/dev/usb/net/if_smsc.c	Fri Nov 23 03:24:52 2012	(r243420)
+++ head/sys/dev/usb/net/if_smsc.c	Fri Nov 23 03:34:12 2012	(r243421)
@@ -82,6 +82,14 @@ __FBSDID("$FreeBSD$");
 #include <sys/priv.h>
 #include <sys/random.h>
 
+#include "opt_platform.h"
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
@@ -1516,6 +1524,64 @@ smsc_ioctl(struct ifnet *ifp, u_long cmd
 	return (rc);
 }
 
+#ifdef FDT
+/**
+ * Get MAC address from FDT blob. Firmware or loader should fill
+ * mac-address or local-mac-address property Returns 0 if MAC address
+ * obtained, error code otherwise
+ */
+static int
+smsc_fdt_find_mac(unsigned char *mac)
+{
+	phandle_t child, parent, root;
+	int len;
+
+	root = OF_finddevice("/");
+	len = 0;
+	parent = root;
+
+	/* Traverse through entire tree to find nodes usb ethernet nodes */
+	for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
+
+		/* Find a 'leaf'. Start the search from this node. */
+		while (OF_child(child)) {
+			parent = child;
+			child = OF_child(child);
+		}
+
+		if (fdt_is_compatible(child, "net,ethernet") &&
+		    fdt_is_compatible(child, "usb,device")) {
+
+			/* Check if there is property */
+			if ((len = OF_getproplen(child, "local-mac-address")) > 0) {
+				if (len != ETHER_ADDR_LEN)
+					return (EINVAL);
+
+				OF_getprop(child, "local-mac-address", mac,
+				    ETHER_ADDR_LEN);
+				return (0);
+			}
+
+			if ((len = OF_getproplen(child, "mac-address")) > 0) {
+				if (len != ETHER_ADDR_LEN)
+					return (EINVAL);
+
+				OF_getprop(child, "mac-address", mac,
+				    ETHER_ADDR_LEN);
+				return (0);
+			}
+		}
+
+		if (OF_peer(child) == 0) {
+			/* No more siblings. */
+			child = parent;
+			parent = OF_parent(child);
+		}
+	}
+
+	return (ENXIO);
+}
+#endif
 
 /**
  *	smsc_attach_post - Called after the driver attached to the USB interface
@@ -1563,8 +1629,11 @@ smsc_attach_post(struct usb_ether *ue)
 	if (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr)) {
 
 		err = smsc_eeprom_read(sc, 0x01, sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN);
+#ifdef FDT
+		if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr)))
+			err = smsc_fdt_find_mac(sc->sc_ue.ue_eaddr);
+#endif
 		if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr))) {
-		
 			read_random(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN);
 			sc->sc_ue.ue_eaddr[0] &= ~0x01;     /* unicast */
 			sc->sc_ue.ue_eaddr[0] |=  0x02;     /* locally administered */



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