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 */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to