summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/net/if_smsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/net/if_smsc.c')
-rw-r--r--sys/dev/usb/net/if_smsc.c71
1 files changed, 70 insertions, 1 deletions
diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c
index 2e2b4ef..5ce45bc 100644
--- a/sys/dev/usb/net/if_smsc.c
+++ b/sys/dev/usb/net/if_smsc.c
@@ -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, caddr_t data)
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 */
OpenPOWER on IntegriCloud