blob: 99386e3e63172442f7210f7b4a7aa29e5af7877b [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
Detlev Zundeld46bcd32010-03-31 17:56:08 +02002 * (C) Copyright 2001-2010
wdenkc6097192002-11-03 00:24:07 +00003 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenkc6097192002-11-03 00:24:07 +00006 */
7
8#include <common.h>
9#include <command.h>
10#include <net.h>
Marian Balakowiczcbdd1c82005-11-30 18:06:04 +010011#include <miiphy.h>
Andy Flemingaecf6fc2011-04-08 02:10:27 -050012#include <phy.h>
wdenkc6097192002-11-03 00:24:07 +000013
Mike Frysingerc34319c2009-01-29 19:43:44 -050014void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
15{
16 char *end;
17 int i;
18
19 for (i = 0; i < 6; ++i) {
20 enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
21 if (addr)
22 addr = (*end) ? end + 1 : end;
23 }
24}
25
26int eth_getenv_enetaddr(char *name, uchar *enetaddr)
27{
28 eth_parse_enetaddr(getenv(name), enetaddr);
29 return is_valid_ether_addr(enetaddr);
30}
31
32int eth_setenv_enetaddr(char *name, const uchar *enetaddr)
33{
34 char buf[20];
35
36 sprintf(buf, "%pM", enetaddr);
37
38 return setenv(name, buf);
39}
Mike Frysingere129d562009-07-15 21:31:28 -040040
Simon Glass62b36c92011-06-13 16:13:10 -070041int eth_getenv_enetaddr_by_index(const char *base_name, int index,
42 uchar *enetaddr)
Mike Frysingere129d562009-07-15 21:31:28 -040043{
44 char enetvar[32];
Simon Glass62b36c92011-06-13 16:13:10 -070045 sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
Mike Frysingere129d562009-07-15 21:31:28 -040046 return eth_getenv_enetaddr(enetvar, enetaddr);
47}
Mike Frysingerc34319c2009-01-29 19:43:44 -050048
Joe Hershberger6c6fe5f2012-07-10 16:23:22 -050049static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index,
Rob Herringc2938c02012-04-14 18:06:49 +000050 uchar *enetaddr)
51{
52 char enetvar[32];
53 sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
54 return eth_setenv_enetaddr(enetvar, enetaddr);
55}
56
57
Ben Warren6db991a2010-04-26 11:11:46 -070058static int eth_mac_skip(int index)
59{
60 char enetvar[15];
61 char *skip_state;
62 sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index);
63 return ((skip_state = getenv(enetvar)) != NULL);
64}
65
Ben Warrend448a492008-06-23 22:57:27 -070066/*
67 * CPU and board-specific Ethernet initializations. Aliased function
68 * signals caller to move on
69 */
70static int __def_eth_init(bd_t *bis)
71{
72 return -1;
73}
Peter Tyser21d2cd22009-04-20 11:08:46 -050074int cpu_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
75int board_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
Ben Warrend448a492008-06-23 22:57:27 -070076
Rafal Jaworowski1f2c9a42007-12-27 18:19:02 +010077#ifdef CONFIG_API
Rafal Jaworowski1f2c9a42007-12-27 18:19:02 +010078static struct {
79 uchar data[PKTSIZE];
80 int length;
81} eth_rcv_bufs[PKTBUFSRX];
82
Joe Hershberger5956ded2012-05-15 08:59:07 +000083static unsigned int eth_rcv_current, eth_rcv_last;
Rafal Jaworowski1f2c9a42007-12-27 18:19:02 +010084#endif
85
Joe Hershberger9f374062012-08-03 10:59:08 +000086static struct eth_device *eth_devices;
87struct eth_device *eth_current;
wdenkc6097192002-11-03 00:24:07 +000088
Ben Warren97824d62010-07-29 12:56:11 -070089struct eth_device *eth_get_dev_by_name(const char *devname)
Marian Balakowiczaab8c492005-10-28 22:30:33 +020090{
91 struct eth_device *dev, *target_dev;
92
Helmut Raiger153bf3a2011-08-22 00:17:17 +000093 BUG_ON(devname == NULL);
94
Marian Balakowiczaab8c492005-10-28 22:30:33 +020095 if (!eth_devices)
96 return NULL;
97
98 dev = eth_devices;
99 target_dev = NULL;
100 do {
101 if (strcmp(devname, dev->name) == 0) {
102 target_dev = dev;
103 break;
104 }
105 dev = dev->next;
106 } while (dev != eth_devices);
107
108 return target_dev;
109}
110
Andy Fleminge7fd34b2009-02-11 15:07:24 -0600111struct eth_device *eth_get_dev_by_index(int index)
112{
113 struct eth_device *dev, *target_dev;
Andy Fleminge7fd34b2009-02-11 15:07:24 -0600114
115 if (!eth_devices)
116 return NULL;
117
118 dev = eth_devices;
119 target_dev = NULL;
120 do {
Michael Walle391da4c2011-10-27 11:31:35 +0000121 if (dev->index == index) {
Andy Fleminge7fd34b2009-02-11 15:07:24 -0600122 target_dev = dev;
123 break;
124 }
125 dev = dev->next;
Andy Fleminge7fd34b2009-02-11 15:07:24 -0600126 } while (dev != eth_devices);
127
128 return target_dev;
129}
130
Joe Hershberger5956ded2012-05-15 08:59:07 +0000131int eth_get_dev_index(void)
wdenkc6097192002-11-03 00:24:07 +0000132{
Joe Hershberger5956ded2012-05-15 08:59:07 +0000133 if (!eth_current)
Michael Walle391da4c2011-10-27 11:31:35 +0000134 return -1;
wdenkc6097192002-11-03 00:24:07 +0000135
Michael Walle391da4c2011-10-27 11:31:35 +0000136 return eth_current->index;
wdenkc6097192002-11-03 00:24:07 +0000137}
138
Simon Glass1e9961d2011-02-16 11:14:33 -0800139static void eth_current_changed(void)
wdenkc6097192002-11-03 00:24:07 +0000140{
Mike Frysingera23230c2011-10-02 10:01:27 +0000141 char *act = getenv("ethact");
142 /* update current ethernet name */
143 if (eth_current) {
144 if (act == NULL || strcmp(act, eth_current->name) != 0)
145 setenv("ethact", eth_current->name);
Simon Glass1e9961d2011-02-16 11:14:33 -0800146 }
Mike Frysingera23230c2011-10-02 10:01:27 +0000147 /*
148 * remove the variable completely if there is no active
149 * interface
150 */
151 else if (act != NULL)
152 setenv("ethact", NULL);
Simon Glass1e9961d2011-02-16 11:14:33 -0800153}
154
Simon Glass62b36c92011-06-13 16:13:10 -0700155int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
156 int eth_number)
157{
158 unsigned char env_enetaddr[6];
159 int ret = 0;
160
Eric Miaoae97ef62012-01-18 22:56:33 +0000161 eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
Simon Glass62b36c92011-06-13 16:13:10 -0700162
163 if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6)) {
164 if (memcmp(dev->enetaddr, "\0\0\0\0\0\0", 6) &&
Joe Hershberger5956ded2012-05-15 08:59:07 +0000165 memcmp(dev->enetaddr, env_enetaddr, 6)) {
Simon Glass62b36c92011-06-13 16:13:10 -0700166 printf("\nWarning: %s MAC addresses don't match:\n",
167 dev->name);
168 printf("Address in SROM is %pM\n",
169 dev->enetaddr);
170 printf("Address in environment is %pM\n",
171 env_enetaddr);
172 }
173
174 memcpy(dev->enetaddr, env_enetaddr, 6);
Rob Herringc2938c02012-04-14 18:06:49 +0000175 } else if (is_valid_ether_addr(dev->enetaddr)) {
176 eth_setenv_enetaddr_by_index(base_name, eth_number,
177 dev->enetaddr);
178 printf("\nWarning: %s using MAC address from net device\n",
179 dev->name);
Simon Glass62b36c92011-06-13 16:13:10 -0700180 }
181
182 if (dev->write_hwaddr &&
Benoît Thébaudeau050219e2012-08-10 07:56:21 +0000183 !eth_mac_skip(eth_number)) {
184 if (!is_valid_ether_addr(dev->enetaddr))
185 return -1;
186
Simon Glass62b36c92011-06-13 16:13:10 -0700187 ret = dev->write_hwaddr(dev);
Benoît Thébaudeau050219e2012-08-10 07:56:21 +0000188 }
Simon Glass62b36c92011-06-13 16:13:10 -0700189
190 return ret;
191}
192
Simon Glass1e9961d2011-02-16 11:14:33 -0800193int eth_register(struct eth_device *dev)
194{
195 struct eth_device *d;
Joe Hershberger5956ded2012-05-15 08:59:07 +0000196 static int index;
Michal Simek5b4945b2011-08-29 23:30:13 +0000197
Mike Frysinger6b300dc2011-11-10 14:11:04 +0000198 assert(strlen(dev->name) < sizeof(dev->name));
Michal Simek5b4945b2011-08-29 23:30:13 +0000199
Simon Glass1e9961d2011-02-16 11:14:33 -0800200 if (!eth_devices) {
201 eth_current = eth_devices = dev;
202 eth_current_changed();
wdenkc6097192002-11-03 00:24:07 +0000203 } else {
Joe Hershberger5956ded2012-05-15 08:59:07 +0000204 for (d = eth_devices; d->next != eth_devices; d = d->next)
Detlev Zundeld46bcd32010-03-31 17:56:08 +0200205 ;
wdenkc6097192002-11-03 00:24:07 +0000206 d->next = dev;
207 }
208
209 dev->state = ETH_STATE_INIT;
210 dev->next = eth_devices;
Michael Walle391da4c2011-10-27 11:31:35 +0000211 dev->index = index++;
wdenkc6097192002-11-03 00:24:07 +0000212
213 return 0;
214}
215
Vincent Palatin451be502012-01-09 08:32:36 +0000216int eth_unregister(struct eth_device *dev)
217{
218 struct eth_device *cur;
219
220 /* No device */
221 if (!eth_devices)
222 return -1;
223
224 for (cur = eth_devices; cur->next != eth_devices && cur->next != dev;
225 cur = cur->next)
226 ;
227
228 /* Device not found */
229 if (cur->next != dev)
230 return -1;
231
232 cur->next = dev->next;
233
234 if (eth_devices == dev)
235 eth_devices = dev->next == eth_devices ? NULL : dev->next;
236
237 if (eth_current == dev) {
238 eth_current = eth_devices;
239 eth_current_changed();
240 }
241
242 return 0;
243}
244
Mike Frysinger36fe7db2012-04-04 18:53:41 +0000245static void eth_env_init(bd_t *bis)
246{
247 const char *s;
248
249 if ((s = getenv("bootfile")) != NULL)
250 copy_filename(BootFile, s, sizeof(BootFile));
251}
252
wdenkc6097192002-11-03 00:24:07 +0000253int eth_initialize(bd_t *bis)
254{
Michael Walle391da4c2011-10-27 11:31:35 +0000255 int num_devices = 0;
wdenkc6097192002-11-03 00:24:07 +0000256 eth_devices = NULL;
257 eth_current = NULL;
258
Simon Glass0169e6b2012-02-13 13:51:18 +0000259 bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
Alexey Brodkin37ecfa12014-01-10 19:58:11 +0400260#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB)
Marian Balakowiczcbdd1c82005-11-30 18:06:04 +0100261 miiphy_init();
262#endif
Andy Flemingaecf6fc2011-04-08 02:10:27 -0500263
264#ifdef CONFIG_PHYLIB
265 phy_init();
266#endif
267
Mike Frysinger36fe7db2012-04-04 18:53:41 +0000268 eth_env_init(bis);
269
Ben Warrencfdc8e02010-08-31 23:05:04 -0700270 /*
271 * If board-specific initialization exists, call it.
272 * If not, call a CPU-specific one
273 */
274 if (board_eth_init != __def_eth_init) {
275 if (board_eth_init(bis) < 0)
276 printf("Board Net Initialization Failed\n");
277 } else if (cpu_eth_init != __def_eth_init) {
278 if (cpu_eth_init(bis) < 0)
279 printf("CPU Net Initialization Failed\n");
280 } else
281 printf("Net Initialization Skipped\n");
Marian Balakowiczcbdd1c82005-11-30 18:06:04 +0100282
wdenkc6097192002-11-03 00:24:07 +0000283 if (!eth_devices) {
Joe Hershberger5956ded2012-05-15 08:59:07 +0000284 puts("No ethernet found.\n");
Simon Glass0169e6b2012-02-13 13:51:18 +0000285 bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
wdenkc6097192002-11-03 00:24:07 +0000286 } else {
287 struct eth_device *dev = eth_devices;
Joe Hershberger5956ded2012-05-15 08:59:07 +0000288 char *ethprime = getenv("ethprime");
wdenkc6097192002-11-03 00:24:07 +0000289
Simon Glass0169e6b2012-02-13 13:51:18 +0000290 bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
wdenkc6097192002-11-03 00:24:07 +0000291 do {
Michael Walle391da4c2011-10-27 11:31:35 +0000292 if (dev->index)
Joe Hershberger5956ded2012-05-15 08:59:07 +0000293 puts(", ");
wdenkc6097192002-11-03 00:24:07 +0000294
295 printf("%s", dev->name);
296
Joe Hershberger5956ded2012-05-15 08:59:07 +0000297 if (ethprime && strcmp(dev->name, ethprime) == 0) {
wdenkc6097192002-11-03 00:24:07 +0000298 eth_current = dev;
Joe Hershberger5956ded2012-05-15 08:59:07 +0000299 puts(" [PRIME]");
wdenkc6097192002-11-03 00:24:07 +0000300 }
301
Mike Frysinger2843ed92010-06-09 22:10:48 -0400302 if (strchr(dev->name, ' '))
Joe Hershberger5956ded2012-05-15 08:59:07 +0000303 puts("\nWarning: eth device name has a space!"
304 "\n");
Mike Frysinger2843ed92010-06-09 22:10:48 -0400305
Michael Walle391da4c2011-10-27 11:31:35 +0000306 if (eth_write_hwaddr(dev, "eth", dev->index))
Philip Balisterdde025c2011-09-07 01:57:48 +0000307 puts("\nWarning: failed to set MAC address\n");
wdenkc6097192002-11-03 00:24:07 +0000308
wdenkc6097192002-11-03 00:24:07 +0000309 dev = dev->next;
Michael Walle391da4c2011-10-27 11:31:35 +0000310 num_devices++;
Joe Hershberger5956ded2012-05-15 08:59:07 +0000311 } while (dev != eth_devices);
wdenkc6097192002-11-03 00:24:07 +0000312
Simon Glass1e9961d2011-02-16 11:14:33 -0800313 eth_current_changed();
Joe Hershberger5956ded2012-05-15 08:59:07 +0000314 putc('\n');
wdenkc6097192002-11-03 00:24:07 +0000315 }
316
Michael Walle391da4c2011-10-27 11:31:35 +0000317 return num_devices;
wdenkc6097192002-11-03 00:24:07 +0000318}
319
David Updegraff7280da72007-06-11 10:41:07 -0500320#ifdef CONFIG_MCAST_TFTP
321/* Multicast.
322 * mcast_addr: multicast ipaddr from which multicast Mac is made
Wolfgang Denk627f5c32007-08-14 09:47:27 +0200323 * join: 1=join, 0=leave.
David Updegraff7280da72007-06-11 10:41:07 -0500324 */
Joe Hershberger5956ded2012-05-15 08:59:07 +0000325int eth_mcast_join(IPaddr_t mcast_ip, u8 join)
David Updegraff7280da72007-06-11 10:41:07 -0500326{
Joe Hershberger5956ded2012-05-15 08:59:07 +0000327 u8 mcast_mac[6];
Wolfgang Denk627f5c32007-08-14 09:47:27 +0200328 if (!eth_current || !eth_current->mcast)
David Updegraff7280da72007-06-11 10:41:07 -0500329 return -1;
330 mcast_mac[5] = htonl(mcast_ip) & 0xff;
331 mcast_mac[4] = (htonl(mcast_ip)>>8) & 0xff;
332 mcast_mac[3] = (htonl(mcast_ip)>>16) & 0x7f;
333 mcast_mac[2] = 0x5e;
334 mcast_mac[1] = 0x0;
335 mcast_mac[0] = 0x1;
336 return eth_current->mcast(eth_current, mcast_mac, join);
337}
338
Wolfgang Denk627f5c32007-08-14 09:47:27 +0200339/* the 'way' for ethernet-CRC-32. Spliced in from Linux lib/crc32.c
340 * and this is the ethernet-crc method needed for TSEC -- and perhaps
David Updegraff7280da72007-06-11 10:41:07 -0500341 * some other adapter -- hash tables
342 */
343#define CRCPOLY_LE 0xedb88320
Joe Hershberger5956ded2012-05-15 08:59:07 +0000344u32 ether_crc(size_t len, unsigned char const *p)
David Updegraff7280da72007-06-11 10:41:07 -0500345{
346 int i;
347 u32 crc;
348 crc = ~0;
349 while (len--) {
350 crc ^= *p++;
351 for (i = 0; i < 8; i++)
352 crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
353 }
354 /* an reverse the bits, cuz of way they arrive -- last-first */
355 crc = (crc >> 16) | (crc << 16);
356 crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
357 crc = (crc >> 4 & 0x0f0f0f0f) | (crc << 4 & 0xf0f0f0f0);
358 crc = (crc >> 2 & 0x33333333) | (crc << 2 & 0xcccccccc);
359 crc = (crc >> 1 & 0x55555555) | (crc << 1 & 0xaaaaaaaa);
360 return crc;
361}
wdenkc6097192002-11-03 00:24:07 +0000362
David Updegraff7280da72007-06-11 10:41:07 -0500363#endif
364
wdenkc6097192002-11-03 00:24:07 +0000365
366int eth_init(bd_t *bis)
367{
Mike Frysingere129d562009-07-15 21:31:28 -0400368 struct eth_device *old_current, *dev;
wdenkc6097192002-11-03 00:24:07 +0000369
Stefan Roese11da2be2008-03-04 17:40:41 +0100370 if (!eth_current) {
Joe Hershberger5956ded2012-05-15 08:59:07 +0000371 puts("No ethernet found.\n");
Upakul Barkakatyaed33582007-11-29 12:16:13 +0530372 return -1;
Stefan Roese11da2be2008-03-04 17:40:41 +0100373 }
wdenkc6097192002-11-03 00:24:07 +0000374
Mike Frysingere129d562009-07-15 21:31:28 -0400375 /* Sync environment with network devices */
Mike Frysingere129d562009-07-15 21:31:28 -0400376 dev = eth_devices;
377 do {
378 uchar env_enetaddr[6];
379
Michael Walle391da4c2011-10-27 11:31:35 +0000380 if (eth_getenv_enetaddr_by_index("eth", dev->index,
Simon Glass62b36c92011-06-13 16:13:10 -0700381 env_enetaddr))
Mike Frysingere129d562009-07-15 21:31:28 -0400382 memcpy(dev->enetaddr, env_enetaddr, 6);
383
Mike Frysingere129d562009-07-15 21:31:28 -0400384 dev = dev->next;
385 } while (dev != eth_devices);
386
wdenkc6097192002-11-03 00:24:07 +0000387 old_current = eth_current;
388 do {
Robin Getz9e0a4d62009-07-23 03:01:03 -0400389 debug("Trying %s\n", eth_current->name);
wdenkc6097192002-11-03 00:24:07 +0000390
Joe Hershberger5956ded2012-05-15 08:59:07 +0000391 if (eth_current->init(eth_current, bis) >= 0) {
wdenkc6097192002-11-03 00:24:07 +0000392 eth_current->state = ETH_STATE_ACTIVE;
393
Upakul Barkakatyaed33582007-11-29 12:16:13 +0530394 return 0;
wdenkc6097192002-11-03 00:24:07 +0000395 }
Robin Getz9e0a4d62009-07-23 03:01:03 -0400396 debug("FAIL\n");
wdenkc6097192002-11-03 00:24:07 +0000397
398 eth_try_another(0);
399 } while (old_current != eth_current);
400
Upakul Barkakatyaed33582007-11-29 12:16:13 +0530401 return -1;
wdenkc6097192002-11-03 00:24:07 +0000402}
403
404void eth_halt(void)
405{
406 if (!eth_current)
407 return;
408
409 eth_current->halt(eth_current);
410
411 eth_current->state = ETH_STATE_PASSIVE;
412}
413
Joe Hershberger4b7747e2012-05-15 08:59:04 +0000414int eth_send(void *packet, int length)
wdenkc6097192002-11-03 00:24:07 +0000415{
416 if (!eth_current)
417 return -1;
418
419 return eth_current->send(eth_current, packet, length);
420}
421
422int eth_rx(void)
423{
424 if (!eth_current)
425 return -1;
426
427 return eth_current->recv(eth_current);
428}
Rafal Jaworowski1f2c9a42007-12-27 18:19:02 +0100429
430#ifdef CONFIG_API
Joe Hershberger4b7747e2012-05-15 08:59:04 +0000431static void eth_save_packet(void *packet, int length)
Rafal Jaworowski1f2c9a42007-12-27 18:19:02 +0100432{
Joe Hershberger4b7747e2012-05-15 08:59:04 +0000433 char *p = packet;
Rafal Jaworowski1f2c9a42007-12-27 18:19:02 +0100434 int i;
435
436 if ((eth_rcv_last+1) % PKTBUFSRX == eth_rcv_current)
437 return;
438
439 if (PKTSIZE < length)
440 return;
441
442 for (i = 0; i < length; i++)
443 eth_rcv_bufs[eth_rcv_last].data[i] = p[i];
444
445 eth_rcv_bufs[eth_rcv_last].length = length;
446 eth_rcv_last = (eth_rcv_last + 1) % PKTBUFSRX;
447}
448
Joe Hershberger4b7747e2012-05-15 08:59:04 +0000449int eth_receive(void *packet, int length)
Rafal Jaworowski1f2c9a42007-12-27 18:19:02 +0100450{
Joe Hershberger4b7747e2012-05-15 08:59:04 +0000451 char *p = packet;
Rafal Jaworowski1f2c9a42007-12-27 18:19:02 +0100452 void *pp = push_packet;
453 int i;
454
455 if (eth_rcv_current == eth_rcv_last) {
456 push_packet = eth_save_packet;
457 eth_rx();
458 push_packet = pp;
459
460 if (eth_rcv_current == eth_rcv_last)
461 return -1;
462 }
463
Michael Walledf7c98a2012-06-22 11:24:28 +0000464 length = min(eth_rcv_bufs[eth_rcv_current].length, length);
Rafal Jaworowski1f2c9a42007-12-27 18:19:02 +0100465
466 for (i = 0; i < length; i++)
467 p[i] = eth_rcv_bufs[eth_rcv_current].data[i];
468
469 eth_rcv_current = (eth_rcv_current + 1) % PKTBUFSRX;
470 return length;
471}
472#endif /* CONFIG_API */
wdenkc6097192002-11-03 00:24:07 +0000473
474void eth_try_another(int first_restart)
475{
Joe Hershberger5956ded2012-05-15 08:59:07 +0000476 static struct eth_device *first_failed;
Remy Bohmer0fce5152011-02-19 20:15:14 +0100477 char *ethrotate;
Matthias Fuchs204f0ec2008-01-17 07:45:05 +0100478
479 /*
480 * Do not rotate between network interfaces when
481 * 'ethrotate' variable is set to 'no'.
482 */
Joe Hershberger5956ded2012-05-15 08:59:07 +0000483 ethrotate = getenv("ethrotate");
484 if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
Matthias Fuchs204f0ec2008-01-17 07:45:05 +0100485 return;
wdenkc6097192002-11-03 00:24:07 +0000486
487 if (!eth_current)
488 return;
489
Joe Hershberger5956ded2012-05-15 08:59:07 +0000490 if (first_restart)
wdenkc6097192002-11-03 00:24:07 +0000491 first_failed = eth_current;
wdenkc6097192002-11-03 00:24:07 +0000492
493 eth_current = eth_current->next;
494
Simon Glass1e9961d2011-02-16 11:14:33 -0800495 eth_current_changed();
wdenk145d2c12004-04-15 21:48:45 +0000496
Joe Hershberger5956ded2012-05-15 08:59:07 +0000497 if (first_failed == eth_current)
wdenkc6097192002-11-03 00:24:07 +0000498 NetRestartWrap = 1;
wdenkc6097192002-11-03 00:24:07 +0000499}
500
wdenk145d2c12004-04-15 21:48:45 +0000501void eth_set_current(void)
502{
Joe Hershberger5956ded2012-05-15 08:59:07 +0000503 static char *act;
504 static int env_changed_id;
505 struct eth_device *old_current;
Heiko Schocher0c303fa2009-02-10 09:38:52 +0100506 int env_id;
wdenk145d2c12004-04-15 21:48:45 +0000507
508 if (!eth_current) /* XXX no current */
509 return;
510
Heiko Schocher0c303fa2009-02-10 09:38:52 +0100511 env_id = get_env_id();
512 if ((act == NULL) || (env_changed_id != env_id)) {
513 act = getenv("ethact");
514 env_changed_id = env_id;
515 }
wdenk145d2c12004-04-15 21:48:45 +0000516 if (act != NULL) {
517 old_current = eth_current;
518 do {
519 if (strcmp(eth_current->name, act) == 0)
520 return;
521 eth_current = eth_current->next;
522 } while (old_current != eth_current);
523 }
524
Simon Glass1e9961d2011-02-16 11:14:33 -0800525 eth_current_changed();
wdenk145d2c12004-04-15 21:48:45 +0000526}
wdenk145d2c12004-04-15 21:48:45 +0000527
Joe Hershberger5956ded2012-05-15 08:59:07 +0000528char *eth_get_name(void)
wdenkc6abb7e2003-11-17 21:14:37 +0000529{
Joe Hershberger5956ded2012-05-15 08:59:07 +0000530 return eth_current ? eth_current->name : "unknown";
wdenkc6abb7e2003-11-17 21:14:37 +0000531}