1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2001-2015
3*4882a593Smuzhiyun * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*4882a593Smuzhiyun * Joe Hershberger, National Instruments
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <common.h>
10*4882a593Smuzhiyun #include <dm.h>
11*4882a593Smuzhiyun #include <miiphy.h>
12*4882a593Smuzhiyun #include <net.h>
13*4882a593Smuzhiyun #include "eth_internal.h"
14*4882a593Smuzhiyun
eth_parse_enetaddr(const char * addr,uchar * enetaddr)15*4882a593Smuzhiyun void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun char *end;
18*4882a593Smuzhiyun int i;
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun for (i = 0; i < 6; ++i) {
21*4882a593Smuzhiyun enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
22*4882a593Smuzhiyun if (addr)
23*4882a593Smuzhiyun addr = (*end) ? end + 1 : end;
24*4882a593Smuzhiyun }
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun
eth_env_get_enetaddr(const char * name,uchar * enetaddr)27*4882a593Smuzhiyun int eth_env_get_enetaddr(const char *name, uchar *enetaddr)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun eth_parse_enetaddr(env_get(name), enetaddr);
30*4882a593Smuzhiyun return is_valid_ethaddr(enetaddr);
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun
eth_env_set_enetaddr(const char * name,const uchar * enetaddr)33*4882a593Smuzhiyun int eth_env_set_enetaddr(const char *name, const uchar *enetaddr)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun char buf[ARP_HLEN_ASCII + 1];
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun if (eth_env_get_enetaddr(name, (uchar *)buf))
38*4882a593Smuzhiyun return -EEXIST;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun sprintf(buf, "%pM", enetaddr);
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun return env_set(name, buf);
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
eth_env_get_enetaddr_by_index(const char * base_name,int index,uchar * enetaddr)45*4882a593Smuzhiyun int eth_env_get_enetaddr_by_index(const char *base_name, int index,
46*4882a593Smuzhiyun uchar *enetaddr)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun char enetvar[32];
49*4882a593Smuzhiyun sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
50*4882a593Smuzhiyun return eth_env_get_enetaddr(enetvar, enetaddr);
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun
eth_env_set_enetaddr_by_index(const char * base_name,int index,uchar * enetaddr)53*4882a593Smuzhiyun int eth_env_set_enetaddr_by_index(const char *base_name, int index,
54*4882a593Smuzhiyun uchar *enetaddr)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun char enetvar[32];
57*4882a593Smuzhiyun sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
58*4882a593Smuzhiyun return eth_env_set_enetaddr(enetvar, enetaddr);
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
eth_common_init(void)61*4882a593Smuzhiyun void eth_common_init(void)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
64*4882a593Smuzhiyun #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
65*4882a593Smuzhiyun miiphy_init();
66*4882a593Smuzhiyun #endif
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun #ifdef CONFIG_PHYLIB
69*4882a593Smuzhiyun phy_init();
70*4882a593Smuzhiyun #endif
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
eth_mac_skip(int index)73*4882a593Smuzhiyun int eth_mac_skip(int index)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun char enetvar[15];
76*4882a593Smuzhiyun char *skip_state;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index);
79*4882a593Smuzhiyun skip_state = env_get(enetvar);
80*4882a593Smuzhiyun return skip_state != NULL;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
eth_current_changed(void)83*4882a593Smuzhiyun void eth_current_changed(void)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun char *act = env_get("ethact");
86*4882a593Smuzhiyun char *ethrotate;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun /*
89*4882a593Smuzhiyun * The call to eth_get_dev() below has a side effect of rotating
90*4882a593Smuzhiyun * ethernet device if uc_priv->current == NULL. This is not what
91*4882a593Smuzhiyun * we want when 'ethrotate' variable is 'no'.
92*4882a593Smuzhiyun */
93*4882a593Smuzhiyun ethrotate = env_get("ethrotate");
94*4882a593Smuzhiyun if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
95*4882a593Smuzhiyun return;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /* update current ethernet name */
98*4882a593Smuzhiyun if (eth_get_dev()) {
99*4882a593Smuzhiyun if (act == NULL || strcmp(act, eth_get_name()) != 0)
100*4882a593Smuzhiyun env_set("ethact", eth_get_name());
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun * remove the variable completely if there is no active
104*4882a593Smuzhiyun * interface
105*4882a593Smuzhiyun */
106*4882a593Smuzhiyun else if (act != NULL)
107*4882a593Smuzhiyun env_set("ethact", NULL);
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
eth_try_another(int first_restart)110*4882a593Smuzhiyun void eth_try_another(int first_restart)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun static void *first_failed;
113*4882a593Smuzhiyun char *ethrotate;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /*
116*4882a593Smuzhiyun * Do not rotate between network interfaces when
117*4882a593Smuzhiyun * 'ethrotate' variable is set to 'no'.
118*4882a593Smuzhiyun */
119*4882a593Smuzhiyun ethrotate = env_get("ethrotate");
120*4882a593Smuzhiyun if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
121*4882a593Smuzhiyun return;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun if (!eth_get_dev())
124*4882a593Smuzhiyun return;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun if (first_restart)
127*4882a593Smuzhiyun first_failed = eth_get_dev();
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun eth_set_current_to_next();
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun eth_current_changed();
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun if (first_failed == eth_get_dev())
134*4882a593Smuzhiyun net_restart_wrap = 1;
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
eth_set_current(void)137*4882a593Smuzhiyun void eth_set_current(void)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun static char *act;
140*4882a593Smuzhiyun static int env_changed_id;
141*4882a593Smuzhiyun int env_id;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun env_id = get_env_id();
144*4882a593Smuzhiyun if ((act == NULL) || (env_changed_id != env_id)) {
145*4882a593Smuzhiyun act = env_get("ethact");
146*4882a593Smuzhiyun env_changed_id = env_id;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun if (act == NULL) {
150*4882a593Smuzhiyun char *ethprime = env_get("ethprime");
151*4882a593Smuzhiyun void *dev = NULL;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun if (ethprime)
154*4882a593Smuzhiyun dev = eth_get_dev_by_name(ethprime);
155*4882a593Smuzhiyun if (dev)
156*4882a593Smuzhiyun eth_set_dev(dev);
157*4882a593Smuzhiyun else
158*4882a593Smuzhiyun eth_set_dev(NULL);
159*4882a593Smuzhiyun } else {
160*4882a593Smuzhiyun eth_set_dev(eth_get_dev_by_name(act));
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun eth_current_changed();
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
eth_get_name(void)166*4882a593Smuzhiyun const char *eth_get_name(void)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun return eth_get_dev() ? eth_get_dev()->name : "unknown";
169*4882a593Smuzhiyun }
170