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