static int eth_write_hwaddr(struct udevice *dev) { struct eth_pdata *pdata = dev->platdata; int ret = 0; if (!dev || !device_active(dev)) return -EINVAL; /* seq is valid since the device is active */ if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) { if (!is_valid_ethaddr(pdata->enetaddr)) { printf("\nError: %s address %pM illegal value\n", dev->name, pdata->enetaddr); 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; }
int eth_rx(void) { struct udevice *current; uchar *packet; int flags; int ret; int i; current = eth_get_dev(); if (!current) return -ENODEV; if (!device_active(current)) 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, flags, &packet); flags = 0; if (ret > 0) net_process_received_packet(packet, ret); if (ret >= 0 && eth_get_ops(current)->free_pkt) eth_get_ops(current)->free_pkt(current, packet, ret); if (ret <= 0) break; } if (ret == -EAGAIN) ret = 0; if (ret < 0) { /* We cannot completely return the error at present */ debug("%s: recv() returned error %d\n", __func__, ret); } return ret; }
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, ARP_HLEN); return 0; }
void eth_halt(void) { struct udevice *current; struct eth_device_priv *priv; current = eth_get_dev(); if (!current || !device_active(current)) return; eth_get_ops(current)->stop(current); priv = current->uclass_priv; priv->state = ETH_STATE_PASSIVE; }
int eth_send(void *packet, int length) { struct udevice *current; int ret; current = eth_get_dev(); if (!current) return -ENODEV; if (!device_active(current)) return -EINVAL; ret = eth_get_ops(current)->send(current, packet, length); if (ret < 0) { /* We cannot completely return the error at present */ debug("%s: send() returned error %d\n", __func__, ret); } return ret; }
static int eth_post_probe(struct udevice *dev) { struct eth_device_priv *priv = dev->uclass_priv; struct eth_pdata *pdata = dev->platdata; unsigned char env_enetaddr[ARP_HLEN]; #if defined(CONFIG_NEEDS_MANUAL_RELOC) struct eth_ops *ops = eth_get_ops(dev); static int reloc_done; if (!reloc_done) { if (ops->start) ops->start += gd->reloc_off; if (ops->send) ops->send += gd->reloc_off; if (ops->recv) ops->recv += gd->reloc_off; if (ops->free_pkt) ops->free_pkt += gd->reloc_off; if (ops->stop) ops->stop += gd->reloc_off; #ifdef CONFIG_MCAST_TFTP if (ops->mcast) ops->mcast += gd->reloc_off; #endif if (ops->write_hwaddr) ops->write_hwaddr += gd->reloc_off; if (ops->read_rom_hwaddr) ops->read_rom_hwaddr += gd->reloc_off; reloc_done++; } #endif priv->state = ETH_STATE_INIT; /* Check if the device has a MAC address in ROM */ if (eth_get_ops(dev)->read_rom_hwaddr) eth_get_ops(dev)->read_rom_hwaddr(dev); eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr); if (!is_zero_ethaddr(env_enetaddr)) { if (!is_zero_ethaddr(pdata->enetaddr) && memcmp(pdata->enetaddr, env_enetaddr, ARP_HLEN)) { printf("\nWarning: %s MAC addresses don't match:\n", dev->name); printf("Address in ROM is %pM\n", pdata->enetaddr); printf("Address in environment is %pM\n", env_enetaddr); } /* Override the ROM MAC address */ memcpy(pdata->enetaddr, env_enetaddr, ARP_HLEN); } else if (is_valid_ethaddr(pdata->enetaddr)) { eth_setenv_enetaddr_by_index("eth", dev->seq, pdata->enetaddr); printf("\nWarning: %s using MAC address from ROM\n", dev->name); } else if (is_zero_ethaddr(pdata->enetaddr) || !is_valid_ethaddr(pdata->enetaddr)) { #ifdef CONFIG_NET_RANDOM_ETHADDR net_random_ethaddr(pdata->enetaddr); printf("\nWarning: %s (eth%d) using random MAC address - %pM\n", dev->name, dev->seq, pdata->enetaddr); #else printf("\nError: %s address not set.\n", dev->name); return -EINVAL; #endif } return 0; }
int eth_init(void) { char *ethact = getenv("ethact"); char *ethrotate = getenv("ethrotate"); struct udevice *current = NULL; struct udevice *old_current; int ret = -ENODEV; /* * When 'ethrotate' variable is set to 'no' and 'ethact' variable * is already set to an ethernet device, we should stick to 'ethact'. */ if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) { if (ethact) { current = eth_get_dev_by_name(ethact); if (!current) return -EINVAL; } } if (!current) { current = eth_get_dev(); if (!current) { printf("No ethernet found.\n"); return -ENODEV; } } old_current = current; do { 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 { ret = eth_errno; } debug("FAIL\n"); } else { debug("PROBE FAIL\n"); } /* * If ethrotate is enabled, this will change "current", * otherwise we will drop out of this while loop immediately */ eth_try_another(0); /* This will ensure the new "current" attempted to probe */ current = eth_get_dev(); } while (old_current != current); return ret; }