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