Index: sys/dev/usb/net/if_muge.c =================================================================== --- sys/dev/usb/net/if_muge.c +++ sys/dev/usb/net/if_muge.c @@ -95,6 +95,12 @@ #include "opt_platform.h" +#ifdef FDT +#include +#include +#include +#endif + #include #include #include @@ -1427,7 +1433,80 @@ } } +#ifdef FDT +/* + * This is FreeBSD-specific compatibility strings for RPi/RPi2 + */ +static phandle_t +muge_fdt_find_eth_node(phandle_t start, const char *compatible) +{ + phandle_t child, node; + + /* Traverse through entire tree to find usb ethernet nodes. */ + for (node = OF_child(start); node != 0; node = OF_peer(node)) { + if (ofw_bus_node_is_compatible(node, compatible)) + return (node); + child = muge_fdt_find_eth_node(node, compatible); + if (child != -1) + return (child); + } + + return (-1); +} + +/* + * Look through known names that can contain mac address + * return 0 if valid MAC address has been found + */ +static int +muge_fdt_read_mac_property(phandle_t node, unsigned char *mac) +{ + int len; + + /* Check if there is property */ + if ((len = OF_getproplen(node, "local-mac-address")) > 0) { + if (len != ETHER_ADDR_LEN) + return (EINVAL); + + OF_getprop(node, "local-mac-address", mac, + ETHER_ADDR_LEN); + return (0); + } + + if ((len = OF_getproplen(node, "mac-address")) > 0) { + if (len != ETHER_ADDR_LEN) + return (EINVAL); + + OF_getprop(node, "mac-address", mac, + ETHER_ADDR_LEN); + return (0); + } + + return (ENXIO); +} + /** + * 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 +muge_fdt_find_mac(const char *compatible, unsigned char *mac) +{ + phandle_t node, root; + + root = OF_finddevice("/"); + node = muge_fdt_find_eth_node(root, compatible); + if (node != -1) { + if (muge_fdt_read_mac_property(node, mac) == 0) + return (0); + } + + return (ENXIO); +} +#endif + +/** * muge_attach_post - Called after the driver attached to the USB interface * @ue: the USB ethernet device * @@ -1441,6 +1520,11 @@ { struct muge_softc *sc = uether_getsc(ue); uint32_t mac_h, mac_l; +#ifdef FDT + char compatible[16]; + struct usb_attach_arg *uaa = device_get_ivars(ue->ue_dev); +#endif + muge_dbg_printf(sc, "Calling muge_attach_post.\n"); /* Setup some of the basics */ @@ -1468,7 +1552,9 @@ } /* If RX_ADDRx did not provide a valid MAC address, try EEPROM. */ - if (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr)) { + if (ETHER_IS_VALID(sc->sc_ue.ue_eaddr)) { + muge_dbg_printf(sc, "MAC assigned from registers\n"); + } else { if ((lan78xx_eeprom_present(sc) && lan78xx_eeprom_read_raw(sc, ETH_E2P_MAC_OFFSET, sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN) == 0) || @@ -1482,14 +1568,24 @@ sc->sc_ue.ue_eaddr[0] &= ~0x01; /* unicast */ sc->sc_ue.ue_eaddr[0] |= 0x02;/* locally administered */ } - } else { - muge_dbg_printf(sc, "MAC assigned randomly\n"); - arc4rand(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN, 0); - sc->sc_ue.ue_eaddr[0] &= ~0x01; /* unicast */ - sc->sc_ue.ue_eaddr[0] |= 0x02; /* locally administered */ } - } else { - muge_dbg_printf(sc, "MAC assigned from registers\n"); + } + +#ifdef FDT + if (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr)) { + muge_dbg_printf(sc, "MAC assigned from FDT blob\n"); + snprintf(compatible, sizeof(compatible), "usb%x,%x", + uaa->info.idVendor, uaa->info.idProduct); + muge_fdt_find_mac(compatible, sc->sc_ue.ue_eaddr); + } +#endif + + if (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr)) + { + muge_dbg_printf(sc, "MAC assigned randomly\n"); + arc4rand(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN, 0); + sc->sc_ue.ue_eaddr[0] &= ~0x01; /* unicast */ + sc->sc_ue.ue_eaddr[0] |= 0x02; /* locally administered */ } /* Initialise the chip for the first time */