]> git.ipfire.org Git - people/ms/u-boot.git/blame - net/eth.c
net: Move common init into a new eth_common.c file
[people/ms/u-boot.git] / net / eth.c
CommitLineData
c609719b 1/*
05c3e68f 2 * (C) Copyright 2001-2015
c609719b 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
05c3e68f 4 * Joe Hershberger, National Instruments
c609719b 5 *
1a459660 6 * SPDX-License-Identifier: GPL-2.0+
c609719b
WD
7 */
8
9#include <common.h>
10#include <command.h>
05c3e68f 11#include <dm.h>
6e0d26c0 12#include <environment.h>
c609719b 13#include <net.h>
d9785c14 14#include <miiphy.h>
5f184715 15#include <phy.h>
75d9a45c 16#include <asm/errno.h>
05c3e68f 17#include <dm/device-internal.h>
6e0d26c0 18#include <dm/uclass-internal.h>
818f91eb 19#include "eth_internal.h"
c609719b 20
d2eaec60
JH
21DECLARE_GLOBAL_DATA_PTR;
22
3f6e6993
MF
23void eth_parse_enetaddr(const char *addr, uchar *enetaddr)
24{
25 char *end;
26 int i;
27
28 for (i = 0; i < 6; ++i) {
29 enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
30 if (addr)
31 addr = (*end) ? end + 1 : end;
32 }
33}
34
219cc94a 35int eth_getenv_enetaddr(const char *name, uchar *enetaddr)
3f6e6993
MF
36{
37 eth_parse_enetaddr(getenv(name), enetaddr);
0adb5b76 38 return is_valid_ethaddr(enetaddr);
3f6e6993
MF
39}
40
219cc94a 41int eth_setenv_enetaddr(const char *name, const uchar *enetaddr)
3f6e6993
MF
42{
43 char buf[20];
44
45 sprintf(buf, "%pM", enetaddr);
46
47 return setenv(name, buf);
48}
86848a74 49
7616e785
SG
50int eth_getenv_enetaddr_by_index(const char *base_name, int index,
51 uchar *enetaddr)
86848a74
MF
52{
53 char enetvar[32];
7616e785 54 sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
86848a74
MF
55 return eth_getenv_enetaddr(enetvar, enetaddr);
56}
3f6e6993 57
154177e1 58static inline int eth_setenv_enetaddr_by_index(const char *base_name, int index,
c88ef3c1
RH
59 uchar *enetaddr)
60{
61 char enetvar[32];
62 sprintf(enetvar, index ? "%s%daddr" : "%saddr", base_name, index);
63 return eth_setenv_enetaddr(enetvar, enetaddr);
64}
65
ecee9324
BW
66static int eth_mac_skip(int index)
67{
68 char enetvar[15];
69 char *skip_state;
ff819a3a 70
ecee9324 71 sprintf(enetvar, index ? "eth%dmacskip" : "ethmacskip", index);
ff819a3a
JH
72 skip_state = getenv(enetvar);
73 return skip_state != NULL;
ecee9324
BW
74}
75
84eb1fba
JH
76static void eth_current_changed(void);
77
3bc42700
SG
78/*
79 * CPU and board-specific Ethernet initializations. Aliased function
80 * signals caller to move on
81 */
82static int __def_eth_init(bd_t *bis)
83{
84 return -1;
85}
86int cpu_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
87int board_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
88
05c3e68f
JH
89#ifdef CONFIG_DM_ETH
90/**
91 * struct eth_device_priv - private structure for each Ethernet device
92 *
93 * @state: The state of the Ethernet MAC driver (defined by enum eth_state_t)
94 */
95struct eth_device_priv {
96 enum eth_state_t state;
97};
98
99/**
100 * struct eth_uclass_priv - The structure attached to the uclass itself
101 *
102 * @current: The Ethernet device that the network functions are using
103 */
104struct eth_uclass_priv {
105 struct udevice *current;
106};
107
60304592
JH
108/* eth_errno - This stores the most recent failure code from DM functions */
109static int eth_errno;
110
05c3e68f
JH
111static struct eth_uclass_priv *eth_get_uclass_priv(void)
112{
113 struct uclass *uc;
114
115 uclass_get(UCLASS_ETH, &uc);
116 assert(uc);
117 return uc->priv;
118}
119
120static void eth_set_current_to_next(void)
121{
122 struct eth_uclass_priv *uc_priv;
123
124 uc_priv = eth_get_uclass_priv();
125 if (uc_priv->current)
126 uclass_next_device(&uc_priv->current);
127 if (!uc_priv->current)
128 uclass_first_device(UCLASS_ETH, &uc_priv->current);
129}
130
60304592
JH
131/*
132 * Typically this will simply return the active device.
133 * In the case where the most recent active device was unset, this will attempt
134 * to return the first device. If that device doesn't exist or fails to probe,
135 * this function will return NULL.
136 */
05c3e68f
JH
137struct udevice *eth_get_dev(void)
138{
139 struct eth_uclass_priv *uc_priv;
140
141 uc_priv = eth_get_uclass_priv();
142 if (!uc_priv->current)
60304592 143 eth_errno = uclass_first_device(UCLASS_ETH,
05c3e68f
JH
144 &uc_priv->current);
145 return uc_priv->current;
146}
147
60304592
JH
148/*
149 * Typically this will just store a device pointer.
150 * In case it was not probed, we will attempt to do so.
151 * dev may be NULL to unset the active device.
152 */
05c3e68f
JH
153static void eth_set_dev(struct udevice *dev)
154{
ac1d3138 155 if (dev && !device_active(dev)) {
60304592 156 eth_errno = device_probe(dev);
ac1d3138
BM
157 if (eth_errno)
158 dev = NULL;
159 }
160
05c3e68f
JH
161 eth_get_uclass_priv()->current = dev;
162}
163
e58780dc
JH
164/*
165 * Find the udevice that either has the name passed in as devname or has an
166 * alias named devname.
167 */
168struct udevice *eth_get_dev_by_name(const char *devname)
169{
170 int seq = -1;
171 char *endp = NULL;
172 const char *startp = NULL;
173 struct udevice *it;
174 struct uclass *uc;
e408c421 175 int len = strlen("eth");
e58780dc
JH
176
177 /* Must be longer than 3 to be an alias */
e408c421
BM
178 if (!strncmp(devname, "eth", len) && strlen(devname) > len) {
179 startp = devname + len;
e58780dc
JH
180 seq = simple_strtoul(startp, &endp, 10);
181 }
182
183 uclass_get(UCLASS_ETH, &uc);
184 uclass_foreach_dev(it, uc) {
60304592
JH
185 /*
186 * We need the seq to be valid, so try to probe it.
187 * If the probe fails, the seq will not match since it will be
188 * -1 instead of what we are looking for.
189 * We don't care about errors from probe here. Either they won't
190 * match an alias or it will match a literal name and we'll pick
191 * up the error when we try to probe again in eth_set_dev().
192 */
ac1d3138
BM
193 if (device_probe(it))
194 continue;
195 /* Check for the name or the sequence number to match */
e58780dc
JH
196 if (strcmp(it->name, devname) == 0 ||
197 (endp > startp && it->seq == seq))
198 return it;
199 }
200
201 return NULL;
202}
203
05c3e68f
JH
204unsigned char *eth_get_ethaddr(void)
205{
206 struct eth_pdata *pdata;
207
208 if (eth_get_dev()) {
209 pdata = eth_get_dev()->platdata;
210 return pdata->enetaddr;
211 }
212
213 return NULL;
214}
215
216/* Set active state without calling start on the driver */
217int eth_init_state_only(void)
218{
219 struct udevice *current;
220 struct eth_device_priv *priv;
221
222 current = eth_get_dev();
223 if (!current || !device_active(current))
224 return -EINVAL;
225
226 priv = current->uclass_priv;
227 priv->state = ETH_STATE_ACTIVE;
228
229 return 0;
230}
231
232/* Set passive state without calling stop on the driver */
233void eth_halt_state_only(void)
234{
235 struct udevice *current;
236 struct eth_device_priv *priv;
237
238 current = eth_get_dev();
239 if (!current || !device_active(current))
240 return;
241
242 priv = current->uclass_priv;
243 priv->state = ETH_STATE_PASSIVE;
244}
245
246int eth_get_dev_index(void)
247{
248 if (eth_get_dev())
249 return eth_get_dev()->seq;
250 return -1;
251}
252
f566c994
JH
253static int eth_write_hwaddr(struct udevice *dev)
254{
255 struct eth_pdata *pdata = dev->platdata;
256 int ret = 0;
257
258 if (!dev || !device_active(dev))
259 return -EINVAL;
260
261 /* seq is valid since the device is active */
262 if (eth_get_ops(dev)->write_hwaddr && !eth_mac_skip(dev->seq)) {
263 if (!is_valid_ethaddr(pdata->enetaddr)) {
264 printf("\nError: %s address %pM illegal value\n",
265 dev->name, pdata->enetaddr);
266 return -EINVAL;
267 }
268
b86f795a
SG
269 /*
270 * Drivers are allowed to decide not to implement this at
271 * run-time. E.g. Some devices may use it and some may not.
272 */
f566c994 273 ret = eth_get_ops(dev)->write_hwaddr(dev);
b86f795a
SG
274 if (ret == -ENOSYS)
275 ret = 0;
f566c994
JH
276 if (ret)
277 printf("\nWarning: %s failed to set MAC address\n",
278 dev->name);
279 }
280
281 return ret;
282}
283
6e0d26c0
JH
284static int on_ethaddr(const char *name, const char *value, enum env_op op,
285 int flags)
286{
287 int index;
288 int retval;
289 struct udevice *dev;
290
291 /* look for an index after "eth" */
292 index = simple_strtoul(name + 3, NULL, 10);
293
294 retval = uclass_find_device_by_seq(UCLASS_ETH, index, false, &dev);
295 if (!retval) {
296 struct eth_pdata *pdata = dev->platdata;
297 switch (op) {
298 case env_op_create:
299 case env_op_overwrite:
300 eth_parse_enetaddr(value, pdata->enetaddr);
301 break;
302 case env_op_delete:
303 memset(pdata->enetaddr, 0, 6);
304 }
305 }
306
307 return 0;
308}
309U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr);
310
05c3e68f
JH
311int eth_init(void)
312{
4cdc2c8c
BM
313 char *ethact = getenv("ethact");
314 char *ethrotate = getenv("ethrotate");
315 struct udevice *current = NULL;
05c3e68f 316 struct udevice *old_current;
60304592 317 int ret = -ENODEV;
05c3e68f 318
4cdc2c8c
BM
319 /*
320 * When 'ethrotate' variable is set to 'no' and 'ethact' variable
321 * is already set to an ethernet device, we should stick to 'ethact'.
322 */
323 if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0)) {
324 if (ethact) {
325 current = eth_get_dev_by_name(ethact);
326 if (!current)
327 return -EINVAL;
328 }
329 }
330
05c3e68f 331 if (!current) {
4cdc2c8c
BM
332 current = eth_get_dev();
333 if (!current) {
334 printf("No ethernet found.\n");
335 return -ENODEV;
336 }
05c3e68f
JH
337 }
338
339 old_current = current;
340 do {
ac1d3138
BM
341 if (current) {
342 debug("Trying %s\n", current->name);
343
344 if (device_active(current)) {
345 ret = eth_get_ops(current)->start(current);
346 if (ret >= 0) {
347 struct eth_device_priv *priv =
348 current->uclass_priv;
349
350 priv->state = ETH_STATE_ACTIVE;
351 return 0;
352 }
353 } else {
354 ret = eth_errno;
05c3e68f 355 }
ac1d3138
BM
356
357 debug("FAIL\n");
ff819a3a 358 } else {
ac1d3138 359 debug("PROBE FAIL\n");
ff819a3a 360 }
60304592 361
60304592
JH
362 /*
363 * If ethrotate is enabled, this will change "current",
364 * otherwise we will drop out of this while loop immediately
365 */
05c3e68f 366 eth_try_another(0);
60304592 367 /* This will ensure the new "current" attempted to probe */
05c3e68f
JH
368 current = eth_get_dev();
369 } while (old_current != current);
370
60304592 371 return ret;
05c3e68f
JH
372}
373
374void eth_halt(void)
375{
376 struct udevice *current;
377 struct eth_device_priv *priv;
378
379 current = eth_get_dev();
380 if (!current || !device_active(current))
381 return;
382
383 eth_get_ops(current)->stop(current);
384 priv = current->uclass_priv;
385 priv->state = ETH_STATE_PASSIVE;
386}
387
eaa8a195
BN
388int eth_is_active(struct udevice *dev)
389{
390 struct eth_device_priv *priv;
391
392 if (!dev || !device_active(dev))
393 return 0;
394
395 priv = dev_get_uclass_priv(dev);
396 return priv->state == ETH_STATE_ACTIVE;
397}
398
05c3e68f
JH
399int eth_send(void *packet, int length)
400{
401 struct udevice *current;
60304592 402 int ret;
05c3e68f
JH
403
404 current = eth_get_dev();
405 if (!current)
406 return -ENODEV;
407
408 if (!device_active(current))
409 return -EINVAL;
410
60304592
JH
411 ret = eth_get_ops(current)->send(current, packet, length);
412 if (ret < 0) {
413 /* We cannot completely return the error at present */
414 debug("%s: send() returned error %d\n", __func__, ret);
415 }
416 return ret;
05c3e68f
JH
417}
418
419int eth_rx(void)
420{
421 struct udevice *current;
17591405 422 uchar *packet;
a1ca92ea 423 int flags;
17591405
JH
424 int ret;
425 int i;
05c3e68f
JH
426
427 current = eth_get_dev();
428 if (!current)
429 return -ENODEV;
430
431 if (!device_active(current))
432 return -EINVAL;
433
17591405 434 /* Process up to 32 packets at one time */
a1ca92ea 435 flags = ETH_RECV_CHECK_DEVICE;
17591405 436 for (i = 0; i < 32; i++) {
a1ca92ea
SG
437 ret = eth_get_ops(current)->recv(current, flags, &packet);
438 flags = 0;
17591405
JH
439 if (ret > 0)
440 net_process_received_packet(packet, ret);
63c9729a
JH
441 if (ret >= 0 && eth_get_ops(current)->free_pkt)
442 eth_get_ops(current)->free_pkt(current, packet, ret);
443 if (ret <= 0)
17591405
JH
444 break;
445 }
446 if (ret == -EAGAIN)
447 ret = 0;
60304592
JH
448 if (ret < 0) {
449 /* We cannot completely return the error at present */
450 debug("%s: recv() returned error %d\n", __func__, ret);
451 }
17591405 452 return ret;
05c3e68f
JH
453}
454
05c3e68f
JH
455int eth_initialize(void)
456{
457 int num_devices = 0;
458 struct udevice *dev;
459
3bc42700 460 eth_common_init();
05c3e68f
JH
461
462 /*
463 * Devices need to write the hwaddr even if not started so that Linux
464 * will have access to the hwaddr that u-boot stored for the device.
465 * This is accomplished by attempting to probe each device and calling
466 * their write_hwaddr() operation.
467 */
468 uclass_first_device(UCLASS_ETH, &dev);
469 if (!dev) {
470 printf("No ethernet found.\n");
471 bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
472 } else {
6536b9bb
JH
473 char *ethprime = getenv("ethprime");
474 struct udevice *prime_dev = NULL;
475
476 if (ethprime)
477 prime_dev = eth_get_dev_by_name(ethprime);
478 if (prime_dev) {
479 eth_set_dev(prime_dev);
480 eth_current_changed();
481 } else {
482 eth_set_dev(NULL);
483 }
484
05c3e68f
JH
485 bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
486 do {
487 if (num_devices)
488 printf(", ");
489
490 printf("eth%d: %s", dev->seq, dev->name);
491
6536b9bb
JH
492 if (ethprime && dev == prime_dev)
493 printf(" [PRIME]");
494
05c3e68f
JH
495 eth_write_hwaddr(dev);
496
497 uclass_next_device(&dev);
498 num_devices++;
499 } while (dev);
500
501 putc('\n');
502 }
503
504 return num_devices;
505}
506
507static int eth_post_bind(struct udevice *dev)
508{
509 if (strchr(dev->name, ' ')) {
510 printf("\nError: eth device name \"%s\" has a space!\n",
511 dev->name);
512 return -EINVAL;
513 }
514
515 return 0;
516}
517
518static int eth_pre_unbind(struct udevice *dev)
519{
520 /* Don't hang onto a pointer that is going away */
521 if (dev == eth_get_uclass_priv()->current)
522 eth_set_dev(NULL);
523
524 return 0;
525}
526
527static int eth_post_probe(struct udevice *dev)
528{
529 struct eth_device_priv *priv = dev->uclass_priv;
530 struct eth_pdata *pdata = dev->platdata;
531 unsigned char env_enetaddr[6];
532
94067580
MS
533#if defined(CONFIG_NEEDS_MANUAL_RELOC)
534 struct eth_ops *ops = eth_get_ops(dev);
535 static int reloc_done;
536
537 if (!reloc_done) {
538 if (ops->start)
539 ops->start += gd->reloc_off;
540 if (ops->send)
541 ops->send += gd->reloc_off;
542 if (ops->recv)
543 ops->recv += gd->reloc_off;
544 if (ops->free_pkt)
545 ops->free_pkt += gd->reloc_off;
546 if (ops->stop)
547 ops->stop += gd->reloc_off;
548#ifdef CONFIG_MCAST_TFTP
549 if (ops->mcast)
550 ops->mcast += gd->reloc_off;
551#endif
552 if (ops->write_hwaddr)
553 ops->write_hwaddr += gd->reloc_off;
554 if (ops->read_rom_hwaddr)
555 ops->read_rom_hwaddr += gd->reloc_off;
556
557 reloc_done++;
558 }
559#endif
560
05c3e68f
JH
561 priv->state = ETH_STATE_INIT;
562
563 /* Check if the device has a MAC address in ROM */
564 if (eth_get_ops(dev)->read_rom_hwaddr)
565 eth_get_ops(dev)->read_rom_hwaddr(dev);
566
567 eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr);
0adb5b76
JH
568 if (!is_zero_ethaddr(env_enetaddr)) {
569 if (!is_zero_ethaddr(pdata->enetaddr) &&
05c3e68f
JH
570 memcmp(pdata->enetaddr, env_enetaddr, 6)) {
571 printf("\nWarning: %s MAC addresses don't match:\n",
572 dev->name);
573 printf("Address in SROM is %pM\n",
574 pdata->enetaddr);
575 printf("Address in environment is %pM\n",
576 env_enetaddr);
577 }
578
579 /* Override the ROM MAC address */
580 memcpy(pdata->enetaddr, env_enetaddr, 6);
0adb5b76 581 } else if (is_valid_ethaddr(pdata->enetaddr)) {
05c3e68f
JH
582 eth_setenv_enetaddr_by_index("eth", dev->seq, pdata->enetaddr);
583 printf("\nWarning: %s using MAC address from ROM\n",
584 dev->name);
0adb5b76 585 } else if (is_zero_ethaddr(pdata->enetaddr)) {
bef1014b
JH
586#ifdef CONFIG_NET_RANDOM_ETHADDR
587 net_random_ethaddr(pdata->enetaddr);
588 printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
589 dev->name, dev->seq, pdata->enetaddr);
590#else
05c3e68f
JH
591 printf("\nError: %s address not set.\n",
592 dev->name);
593 return -EINVAL;
bef1014b 594#endif
05c3e68f
JH
595 }
596
597 return 0;
598}
599
600static int eth_pre_remove(struct udevice *dev)
601{
a16edabe
BM
602 struct eth_pdata *pdata = dev->platdata;
603
05c3e68f
JH
604 eth_get_ops(dev)->stop(dev);
605
a16edabe
BM
606 /* clear the MAC address */
607 memset(pdata->enetaddr, 0, 6);
608
05c3e68f
JH
609 return 0;
610}
611
612UCLASS_DRIVER(eth) = {
613 .name = "eth",
614 .id = UCLASS_ETH,
615 .post_bind = eth_post_bind,
616 .pre_unbind = eth_pre_unbind,
617 .post_probe = eth_post_probe,
618 .pre_remove = eth_pre_remove,
619 .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
620 .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
e58780dc 621 .flags = DM_UC_FLAG_SEQ_ALIAS,
05c3e68f 622};
eaa8a195 623#endif /* #ifdef CONFIG_DM_ETH */
05c3e68f
JH
624
625#ifndef CONFIG_DM_ETH
dd35479a 626
f85b6071 627#ifdef CONFIG_API
f85b6071
RJ
628static struct {
629 uchar data[PKTSIZE];
630 int length;
631} eth_rcv_bufs[PKTBUFSRX];
632
66c7385a 633static unsigned int eth_rcv_current, eth_rcv_last;
f85b6071
RJ
634#endif
635
f8be7d65
JH
636static struct eth_device *eth_devices;
637struct eth_device *eth_current;
c609719b 638
84eb1fba
JH
639static void eth_set_current_to_next(void)
640{
641 eth_current = eth_current->next;
642}
643
e58780dc
JH
644static void eth_set_dev(struct eth_device *dev)
645{
646 eth_current = dev;
647}
648
d7fb9bcf 649struct eth_device *eth_get_dev_by_name(const char *devname)
63ff004c
MB
650{
651 struct eth_device *dev, *target_dev;
652
7e7f903f
HR
653 BUG_ON(devname == NULL);
654
63ff004c
MB
655 if (!eth_devices)
656 return NULL;
657
658 dev = eth_devices;
659 target_dev = NULL;
660 do {
661 if (strcmp(devname, dev->name) == 0) {
662 target_dev = dev;
663 break;
664 }
665 dev = dev->next;
666 } while (dev != eth_devices);
667
668 return target_dev;
669}
670
9e56986a
AF
671struct eth_device *eth_get_dev_by_index(int index)
672{
673 struct eth_device *dev, *target_dev;
9e56986a
AF
674
675 if (!eth_devices)
676 return NULL;
677
678 dev = eth_devices;
679 target_dev = NULL;
680 do {
fea7dcae 681 if (dev->index == index) {
9e56986a
AF
682 target_dev = dev;
683 break;
684 }
685 dev = dev->next;
9e56986a
AF
686 } while (dev != eth_devices);
687
688 return target_dev;
689}
690
66c7385a 691int eth_get_dev_index(void)
c609719b 692{
66c7385a 693 if (!eth_current)
fea7dcae 694 return -1;
c609719b 695
fea7dcae 696 return eth_current->index;
c609719b
WD
697}
698
6e0d26c0
JH
699static int on_ethaddr(const char *name, const char *value, enum env_op op,
700 int flags)
701{
702 int index;
703 struct eth_device *dev;
704
705 if (!eth_devices)
706 return 0;
707
708 /* look for an index after "eth" */
709 index = simple_strtoul(name + 3, NULL, 10);
710
711 dev = eth_devices;
712 do {
713 if (dev->index == index) {
714 switch (op) {
715 case env_op_create:
716 case env_op_overwrite:
717 eth_parse_enetaddr(value, dev->enetaddr);
718 break;
719 case env_op_delete:
720 memset(dev->enetaddr, 0, 6);
721 }
722 }
7aba0f2c 723 dev = dev->next;
6e0d26c0
JH
724 } while (dev != eth_devices);
725
726 return 0;
727}
728U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr);
729
7616e785
SG
730int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
731 int eth_number)
732{
733 unsigned char env_enetaddr[6];
734 int ret = 0;
735
69376644 736 eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
7616e785 737
0adb5b76
JH
738 if (!is_zero_ethaddr(env_enetaddr)) {
739 if (!is_zero_ethaddr(dev->enetaddr) &&
4c7c65af 740 memcmp(dev->enetaddr, env_enetaddr, 6)) {
7616e785 741 printf("\nWarning: %s MAC addresses don't match:\n",
ff819a3a 742 dev->name);
7616e785 743 printf("Address in SROM is %pM\n",
ff819a3a 744 dev->enetaddr);
7616e785 745 printf("Address in environment is %pM\n",
ff819a3a 746 env_enetaddr);
7616e785
SG
747 }
748
749 memcpy(dev->enetaddr, env_enetaddr, 6);
0adb5b76 750 } else if (is_valid_ethaddr(dev->enetaddr)) {
c88ef3c1
RH
751 eth_setenv_enetaddr_by_index(base_name, eth_number,
752 dev->enetaddr);
0adb5b76 753 } else if (is_zero_ethaddr(dev->enetaddr)) {
bef1014b
JH
754#ifdef CONFIG_NET_RANDOM_ETHADDR
755 net_random_ethaddr(dev->enetaddr);
756 printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
757 dev->name, eth_number, dev->enetaddr);
758#else
75d9a45c
PM
759 printf("\nError: %s address not set.\n",
760 dev->name);
761 return -EINVAL;
bef1014b 762#endif
7616e785
SG
763 }
764
75d9a45c 765 if (dev->write_hwaddr && !eth_mac_skip(eth_number)) {
0adb5b76 766 if (!is_valid_ethaddr(dev->enetaddr)) {
75d9a45c 767 printf("\nError: %s address %pM illegal value\n",
ff819a3a 768 dev->name, dev->enetaddr);
75d9a45c
PM
769 return -EINVAL;
770 }
460f949f 771
7616e785 772 ret = dev->write_hwaddr(dev);
75d9a45c 773 if (ret)
ff819a3a
JH
774 printf("\nWarning: %s failed to set MAC address\n",
775 dev->name);
460f949f 776 }
7616e785
SG
777
778 return ret;
779}
780
89d48367
SG
781int eth_register(struct eth_device *dev)
782{
783 struct eth_device *d;
66c7385a 784 static int index;
58c583b6 785
f6add132 786 assert(strlen(dev->name) < sizeof(dev->name));
58c583b6 787
89d48367 788 if (!eth_devices) {
ff819a3a
JH
789 eth_devices = dev;
790 eth_current = dev;
89d48367 791 eth_current_changed();
c609719b 792 } else {
66c7385a 793 for (d = eth_devices; d->next != eth_devices; d = d->next)
aba4b69d 794 ;
c609719b
WD
795 d->next = dev;
796 }
797
798 dev->state = ETH_STATE_INIT;
799 dev->next = eth_devices;
fea7dcae 800 dev->index = index++;
c609719b
WD
801
802 return 0;
803}
804
e7e982d6
VP
805int eth_unregister(struct eth_device *dev)
806{
807 struct eth_device *cur;
808
809 /* No device */
810 if (!eth_devices)
05324a48 811 return -ENODEV;
e7e982d6
VP
812
813 for (cur = eth_devices; cur->next != eth_devices && cur->next != dev;
814 cur = cur->next)
815 ;
816
817 /* Device not found */
818 if (cur->next != dev)
05324a48 819 return -ENODEV;
e7e982d6
VP
820
821 cur->next = dev->next;
822
823 if (eth_devices == dev)
824 eth_devices = dev->next == eth_devices ? NULL : dev->next;
825
826 if (eth_current == dev) {
827 eth_current = eth_devices;
828 eth_current_changed();
829 }
830
831 return 0;
832}
833
d2eaec60 834int eth_initialize(void)
c609719b 835{
fea7dcae 836 int num_devices = 0;
3bc42700 837
c609719b
WD
838 eth_devices = NULL;
839 eth_current = NULL;
3bc42700 840 eth_common_init();
818f91eb
SG
841 /*
842 * If board-specific initialization exists, call it.
843 * If not, call a CPU-specific one
844 */
845 if (board_eth_init != __def_eth_init) {
846 if (board_eth_init(gd->bd) < 0)
847 printf("Board Net Initialization Failed\n");
848 } else if (cpu_eth_init != __def_eth_init) {
849 if (cpu_eth_init(gd->bd) < 0)
850 printf("CPU Net Initialization Failed\n");
851 } else {
852 printf("Net Initialization Skipped\n");
853 }
d9785c14 854
c609719b 855 if (!eth_devices) {
66c7385a 856 puts("No ethernet found.\n");
770605e4 857 bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
c609719b
WD
858 } else {
859 struct eth_device *dev = eth_devices;
66c7385a 860 char *ethprime = getenv("ethprime");
c609719b 861
770605e4 862 bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
c609719b 863 do {
fea7dcae 864 if (dev->index)
66c7385a 865 puts(", ");
c609719b
WD
866
867 printf("%s", dev->name);
868
66c7385a 869 if (ethprime && strcmp(dev->name, ethprime) == 0) {
c609719b 870 eth_current = dev;
66c7385a 871 puts(" [PRIME]");
c609719b
WD
872 }
873
1384f3bb 874 if (strchr(dev->name, ' '))
66c7385a
JH
875 puts("\nWarning: eth device name has a space!"
876 "\n");
1384f3bb 877
75d9a45c 878 eth_write_hwaddr(dev, "eth", dev->index);
c609719b 879
c609719b 880 dev = dev->next;
fea7dcae 881 num_devices++;
66c7385a 882 } while (dev != eth_devices);
c609719b 883
89d48367 884 eth_current_changed();
66c7385a 885 putc('\n');
c609719b
WD
886 }
887
fea7dcae 888 return num_devices;
c609719b
WD
889}
890
53a5c424
DU
891#ifdef CONFIG_MCAST_TFTP
892/* Multicast.
893 * mcast_addr: multicast ipaddr from which multicast Mac is made
85eb5caf 894 * join: 1=join, 0=leave.
53a5c424 895 */
049a95a7 896int eth_mcast_join(struct in_addr mcast_ip, int join)
53a5c424 897{
66c7385a 898 u8 mcast_mac[6];
85eb5caf 899 if (!eth_current || !eth_current->mcast)
53a5c424 900 return -1;
049a95a7
JH
901 mcast_mac[5] = htonl(mcast_ip.s_addr) & 0xff;
902 mcast_mac[4] = (htonl(mcast_ip.s_addr)>>8) & 0xff;
903 mcast_mac[3] = (htonl(mcast_ip.s_addr)>>16) & 0x7f;
53a5c424
DU
904 mcast_mac[2] = 0x5e;
905 mcast_mac[1] = 0x0;
906 mcast_mac[0] = 0x1;
907 return eth_current->mcast(eth_current, mcast_mac, join);
908}
909
85eb5caf
WD
910/* the 'way' for ethernet-CRC-32. Spliced in from Linux lib/crc32.c
911 * and this is the ethernet-crc method needed for TSEC -- and perhaps
53a5c424
DU
912 * some other adapter -- hash tables
913 */
914#define CRCPOLY_LE 0xedb88320
66c7385a 915u32 ether_crc(size_t len, unsigned char const *p)
53a5c424
DU
916{
917 int i;
918 u32 crc;
919 crc = ~0;
920 while (len--) {
921 crc ^= *p++;
922 for (i = 0; i < 8; i++)
923 crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
924 }
925 /* an reverse the bits, cuz of way they arrive -- last-first */
926 crc = (crc >> 16) | (crc << 16);
927 crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
928 crc = (crc >> 4 & 0x0f0f0f0f) | (crc << 4 & 0xf0f0f0f0);
929 crc = (crc >> 2 & 0x33333333) | (crc << 2 & 0xcccccccc);
930 crc = (crc >> 1 & 0x55555555) | (crc << 1 & 0xaaaaaaaa);
931 return crc;
932}
933
934#endif
935
c609719b 936
d2eaec60 937int eth_init(void)
c609719b 938{
6e0d26c0 939 struct eth_device *old_current;
c609719b 940
6bc11388 941 if (!eth_current) {
66c7385a 942 puts("No ethernet found.\n");
05324a48 943 return -ENODEV;
6bc11388 944 }
c609719b
WD
945
946 old_current = eth_current;
947 do {
0ebf04c6 948 debug("Trying %s\n", eth_current->name);
c609719b 949
d2eaec60 950 if (eth_current->init(eth_current, gd->bd) >= 0) {
c609719b
WD
951 eth_current->state = ETH_STATE_ACTIVE;
952
505be87a 953 return 0;
c609719b 954 }
0ebf04c6 955 debug("FAIL\n");
c609719b
WD
956
957 eth_try_another(0);
958 } while (old_current != eth_current);
959
05324a48 960 return -ETIMEDOUT;
c609719b
WD
961}
962
963void eth_halt(void)
964{
965 if (!eth_current)
966 return;
967
968 eth_current->halt(eth_current);
969
970 eth_current->state = ETH_STATE_PASSIVE;
971}
972
eaa8a195
BN
973int eth_is_active(struct eth_device *dev)
974{
975 return dev && dev->state == ETH_STATE_ACTIVE;
976}
977
db288a96 978int eth_send(void *packet, int length)
c609719b
WD
979{
980 if (!eth_current)
05324a48 981 return -ENODEV;
c609719b
WD
982
983 return eth_current->send(eth_current, packet, length);
984}
985
986int eth_rx(void)
987{
988 if (!eth_current)
05324a48 989 return -ENODEV;
c609719b
WD
990
991 return eth_current->recv(eth_current);
992}
05c3e68f 993#endif /* ifndef CONFIG_DM_ETH */
c609719b 994
f85b6071 995#ifdef CONFIG_API
db288a96 996static void eth_save_packet(void *packet, int length)
f85b6071 997{
db288a96 998 char *p = packet;
f85b6071
RJ
999 int i;
1000
1001 if ((eth_rcv_last+1) % PKTBUFSRX == eth_rcv_current)
1002 return;
1003
1004 if (PKTSIZE < length)
1005 return;
1006
1007 for (i = 0; i < length; i++)
1008 eth_rcv_bufs[eth_rcv_last].data[i] = p[i];
1009
1010 eth_rcv_bufs[eth_rcv_last].length = length;
1011 eth_rcv_last = (eth_rcv_last + 1) % PKTBUFSRX;
1012}
1013
db288a96 1014int eth_receive(void *packet, int length)
f85b6071 1015{
db288a96 1016 char *p = packet;
f85b6071
RJ
1017 void *pp = push_packet;
1018 int i;
1019
1020 if (eth_rcv_current == eth_rcv_last) {
1021 push_packet = eth_save_packet;
1022 eth_rx();
1023 push_packet = pp;
1024
1025 if (eth_rcv_current == eth_rcv_last)
1026 return -1;
1027 }
1028
46c07bcf 1029 length = min(eth_rcv_bufs[eth_rcv_current].length, length);
f85b6071
RJ
1030
1031 for (i = 0; i < length; i++)
1032 p[i] = eth_rcv_bufs[eth_rcv_current].data[i];
1033
1034 eth_rcv_current = (eth_rcv_current + 1) % PKTBUFSRX;
1035 return length;
1036}
1037#endif /* CONFIG_API */
1038
84eb1fba
JH
1039static void eth_current_changed(void)
1040{
1041 char *act = getenv("ethact");
a671c4f2
BM
1042 char *ethrotate;
1043
1044 /*
1045 * The call to eth_get_dev() below has a side effect of rotating
1046 * ethernet device if uc_priv->current == NULL. This is not what
1047 * we want when 'ethrotate' variable is 'no'.
1048 */
1049 ethrotate = getenv("ethrotate");
1050 if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
1051 return;
1052
84eb1fba
JH
1053 /* update current ethernet name */
1054 if (eth_get_dev()) {
1055 if (act == NULL || strcmp(act, eth_get_name()) != 0)
1056 setenv("ethact", eth_get_name());
1057 }
1058 /*
1059 * remove the variable completely if there is no active
1060 * interface
1061 */
1062 else if (act != NULL)
1063 setenv("ethact", NULL);
1064}
1065
c609719b
WD
1066void eth_try_another(int first_restart)
1067{
05c3e68f 1068 static void *first_failed;
c650e1be 1069 char *ethrotate;
e1692577
MF
1070
1071 /*
1072 * Do not rotate between network interfaces when
1073 * 'ethrotate' variable is set to 'no'.
1074 */
66c7385a
JH
1075 ethrotate = getenv("ethrotate");
1076 if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
e1692577 1077 return;
c609719b 1078
84eb1fba 1079 if (!eth_get_dev())
c609719b
WD
1080 return;
1081
66c7385a 1082 if (first_restart)
84eb1fba 1083 first_failed = eth_get_dev();
c609719b 1084
84eb1fba 1085 eth_set_current_to_next();
c609719b 1086
89d48367 1087 eth_current_changed();
a3d991bd 1088
84eb1fba 1089 if (first_failed == eth_get_dev())
bc0571fc 1090 net_restart_wrap = 1;
c609719b
WD
1091}
1092
a3d991bd
WD
1093void eth_set_current(void)
1094{
66c7385a
JH
1095 static char *act;
1096 static int env_changed_id;
2f70c49e 1097 int env_id;
a3d991bd 1098
2f70c49e
HS
1099 env_id = get_env_id();
1100 if ((act == NULL) || (env_changed_id != env_id)) {
1101 act = getenv("ethact");
1102 env_changed_id = env_id;
1103 }
6536b9bb
JH
1104
1105 if (act == NULL) {
1106 char *ethprime = getenv("ethprime");
1107 void *dev = NULL;
1108
1109 if (ethprime)
1110 dev = eth_get_dev_by_name(ethprime);
1111 if (dev)
1112 eth_set_dev(dev);
1113 else
1114 eth_set_dev(NULL);
1115 } else {
e58780dc 1116 eth_set_dev(eth_get_dev_by_name(act));
6536b9bb 1117 }
a3d991bd 1118
89d48367 1119 eth_current_changed();
a3d991bd 1120}
a3d991bd 1121
84eb1fba 1122const char *eth_get_name(void)
5bb226e8 1123{
84eb1fba 1124 return eth_get_dev() ? eth_get_dev()->name : "unknown";
5bb226e8 1125}