#include <common.h>
#include <command.h>
#include <dm.h>
+#include <environment.h>
#include <net.h>
#include <miiphy.h>
#include <phy.h>
#include <asm/errno.h>
#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
DECLARE_GLOBAL_DATA_PTR;
}
}
-int eth_getenv_enetaddr(char *name, uchar *enetaddr)
+int eth_getenv_enetaddr(const char *name, uchar *enetaddr)
{
eth_parse_enetaddr(getenv(name), enetaddr);
return is_valid_ethaddr(enetaddr);
}
-int eth_setenv_enetaddr(char *name, const uchar *enetaddr)
+int eth_setenv_enetaddr(const char *name, const uchar *enetaddr)
{
char buf[20];
if (cpu_eth_init(gd->bd) < 0)
printf("CPU Net Initialization Failed\n");
} else {
+#ifndef CONFIG_DM_ETH
printf("Net Initialization Skipped\n");
+#endif
}
}
*/
static void eth_set_dev(struct udevice *dev)
{
- if (dev && !device_active(dev))
+ if (dev && !device_active(dev)) {
eth_errno = device_probe(dev);
+ if (eth_errno)
+ dev = NULL;
+ }
+
eth_get_uclass_priv()->current = dev;
}
const char *startp = NULL;
struct udevice *it;
struct uclass *uc;
+ int len = strlen("eth");
/* Must be longer than 3 to be an alias */
- if (strlen(devname) > strlen("eth")) {
- startp = devname + strlen("eth");
+ if (!strncmp(devname, "eth", len) && strlen(devname) > len) {
+ startp = devname + len;
seq = simple_strtoul(startp, &endp, 10);
}
* match an alias or it will match a literal name and we'll pick
* up the error when we try to probe again in eth_set_dev().
*/
- device_probe(it);
- /*
- * Check for the name or the sequence number to match
- */
+ if (device_probe(it))
+ continue;
+ /* Check for the name or the sequence number to match */
if (strcmp(it->name, devname) == 0 ||
(endp > startp && it->seq == seq))
return it;
return -EINVAL;
}
+ /*
+ * Drivers are allowed to decide not to implement this at
+ * run-time. E.g. Some devices may use it and some may not.
+ */
ret = eth_get_ops(dev)->write_hwaddr(dev);
+ if (ret == -ENOSYS)
+ ret = 0;
if (ret)
printf("\nWarning: %s failed to set MAC address\n",
dev->name);
return ret;
}
+static int on_ethaddr(const char *name, const char *value, enum env_op op,
+ int flags)
+{
+ int index;
+ int retval;
+ struct udevice *dev;
+
+ /* look for an index after "eth" */
+ index = simple_strtoul(name + 3, NULL, 10);
+
+ retval = uclass_find_device_by_seq(UCLASS_ETH, index, false, &dev);
+ if (!retval) {
+ struct eth_pdata *pdata = dev->platdata;
+ switch (op) {
+ case env_op_create:
+ case env_op_overwrite:
+ eth_parse_enetaddr(value, pdata->enetaddr);
+ break;
+ case env_op_delete:
+ memset(pdata->enetaddr, 0, 6);
+ }
+ }
+
+ return 0;
+}
+U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr);
+
int eth_init(void)
{
struct udevice *current;
old_current = current;
do {
- debug("Trying %s\n", current->name);
-
- if (device_active(current)) {
- uchar env_enetaddr[6];
- struct eth_pdata *pdata = current->platdata;
- int enetaddr_changed = 0;
-
- /* Sync environment with network device */
- if (eth_getenv_enetaddr_by_index("eth", current->seq,
- env_enetaddr)) {
- enetaddr_changed = memcmp(pdata->enetaddr,
- env_enetaddr, 6);
- memcpy(pdata->enetaddr, env_enetaddr, 6);
+ if (current) {
+ debug("Trying %s\n", current->name);
+
+ if (device_active(current)) {
+ ret = eth_get_ops(current)->start(current);
+ if (ret >= 0) {
+ struct eth_device_priv *priv =
+ current->uclass_priv;
+
+ priv->state = ETH_STATE_ACTIVE;
+ return 0;
+ }
} else {
- memset(env_enetaddr, 0, 6);
- enetaddr_changed = memcmp(pdata->enetaddr,
- env_enetaddr, 6);
- memset(pdata->enetaddr, 0, 6);
+ ret = eth_errno;
}
- if (enetaddr_changed)
- eth_write_hwaddr(current);
-
- ret = eth_get_ops(current)->start(current);
- if (ret >= 0) {
- struct eth_device_priv *priv =
- current->uclass_priv;
- priv->state = ETH_STATE_ACTIVE;
- return 0;
- }
+ debug("FAIL\n");
} else {
- ret = eth_errno;
+ debug("PROBE FAIL\n");
}
- debug("FAIL\n");
-
/*
* If ethrotate is enabled, this will change "current",
* otherwise we will drop out of this while loop immediately
priv->state = ETH_STATE_PASSIVE;
}
+int eth_is_active(struct udevice *dev)
+{
+ struct eth_device_priv *priv;
+
+ if (!dev || !device_active(dev))
+ return 0;
+
+ priv = dev_get_uclass_priv(dev);
+ return priv->state == ETH_STATE_ACTIVE;
+}
+
int eth_send(void *packet, int length)
{
struct udevice *current;
{
struct udevice *current;
uchar *packet;
+ int flags;
int ret;
int i;
return -EINVAL;
/* Process up to 32 packets at one time */
+ flags = ETH_RECV_CHECK_DEVICE;
for (i = 0; i < 32; i++) {
- ret = eth_get_ops(current)->recv(current, &packet);
+ ret = eth_get_ops(current)->recv(current, flags, &packet);
+ flags = 0;
if (ret > 0)
net_process_received_packet(packet, ret);
if (ret >= 0 && eth_get_ops(current)->free_pkt)
static int eth_pre_remove(struct udevice *dev)
{
+ struct eth_pdata *pdata = dev->platdata;
+
eth_get_ops(dev)->stop(dev);
+ /* clear the MAC address */
+ memset(pdata->enetaddr, 0, 6);
+
return 0;
}
.per_device_auto_alloc_size = sizeof(struct eth_device_priv),
.flags = DM_UC_FLAG_SEQ_ALIAS,
};
-#endif
+#endif /* #ifdef CONFIG_DM_ETH */
#ifndef CONFIG_DM_ETH
return eth_current->index;
}
+static int on_ethaddr(const char *name, const char *value, enum env_op op,
+ int flags)
+{
+ int index;
+ struct eth_device *dev;
+
+ if (!eth_devices)
+ return 0;
+
+ /* look for an index after "eth" */
+ index = simple_strtoul(name + 3, NULL, 10);
+
+ dev = eth_devices;
+ do {
+ if (dev->index == index) {
+ switch (op) {
+ case env_op_create:
+ case env_op_overwrite:
+ eth_parse_enetaddr(value, dev->enetaddr);
+ break;
+ case env_op_delete:
+ memset(dev->enetaddr, 0, 6);
+ }
+ }
+ dev = dev->next;
+ } while (dev != eth_devices);
+
+ return 0;
+}
+U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr);
+
int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
int eth_number)
{
int eth_init(void)
{
- struct eth_device *old_current, *dev;
+ struct eth_device *old_current;
if (!eth_current) {
puts("No ethernet found.\n");
return -ENODEV;
}
- /* Sync environment with network devices */
- dev = eth_devices;
- do {
- uchar env_enetaddr[6];
- int enetaddr_changed = 0;
-
- if (eth_getenv_enetaddr_by_index("eth", dev->index,
- env_enetaddr)) {
- enetaddr_changed = memcmp(dev->enetaddr,
- env_enetaddr, 6);
- memcpy(dev->enetaddr, env_enetaddr, 6);
- } else {
- memset(env_enetaddr, 0, 6);
- enetaddr_changed = memcmp(dev->enetaddr,
- env_enetaddr, 6);
- memset(dev->enetaddr, 0, 6);
- }
- if (enetaddr_changed)
- eth_write_hwaddr(dev, "eth", dev->index);
-
- dev = dev->next;
- } while (dev != eth_devices);
-
old_current = eth_current;
do {
debug("Trying %s\n", eth_current->name);
eth_current->state = ETH_STATE_PASSIVE;
}
+int eth_is_active(struct eth_device *dev)
+{
+ return dev && dev->state == ETH_STATE_ACTIVE;
+}
+
int eth_send(void *packet, int length)
{
if (!eth_current)