Look for MAC address in FDT tree nodes that are usb network devices and

have either "mac-address" or "local-mac-addrress" property.
This commit is contained in:
Oleksandr Tymoshenko 2012-11-23 03:34:12 +00:00
parent ab11b7079a
commit 82b036b9c6

View File

@ -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 */