]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - net/eth.c
72ce91c9d0bbb546c7d8b50098b161ca8cf124ea
[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 flags;
408         int ret;
409         int i;
410
411         current = eth_get_dev();
412         if (!current)
413                 return -ENODEV;
414
415         if (!device_active(current))
416                 return -EINVAL;
417
418         /* Process up to 32 packets at one time */
419         flags = ETH_RECV_CHECK_DEVICE;
420         for (i = 0; i < 32; i++) {
421                 ret = eth_get_ops(current)->recv(current, flags, &packet);
422                 flags = 0;
423                 if (ret > 0)
424                         net_process_received_packet(packet, ret);
425                 if (ret >= 0 && eth_get_ops(current)->free_pkt)
426                         eth_get_ops(current)->free_pkt(current, packet, ret);
427                 if (ret <= 0)
428                         break;
429         }
430         if (ret == -EAGAIN)
431                 ret = 0;
432         if (ret < 0) {
433                 /* We cannot completely return the error at present */
434                 debug("%s: recv() returned error %d\n", __func__, ret);
435         }
436         return ret;
437 }
438
439 int eth_initialize(void)
440 {
441         int num_devices = 0;
442         struct udevice *dev;
443
444         eth_common_init();
445
446         /*
447          * Devices need to write the hwaddr even if not started so that Linux
448          * will have access to the hwaddr that u-boot stored for the device.
449          * This is accomplished by attempting to probe each device and calling
450          * their write_hwaddr() operation.
451          */
452         uclass_first_device(UCLASS_ETH, &dev);
453         if (!dev) {
454                 printf("No ethernet found.\n");
455                 bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
456         } else {
457                 char *ethprime = getenv("ethprime");
458                 struct udevice *prime_dev = NULL;
459
460                 if (ethprime)
461                         prime_dev = eth_get_dev_by_name(ethprime);
462                 if (prime_dev) {
463                         eth_set_dev(prime_dev);
464                         eth_current_changed();
465                 } else {
466                         eth_set_dev(NULL);
467                 }
468
469                 bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
470                 do {
471                         if (num_devices)
472                                 printf(", ");
473
474                         printf("eth%d: %s", dev->seq, dev->name);
475
476                         if (ethprime && dev == prime_dev)
477                                 printf(" [PRIME]");
478
479                         eth_write_hwaddr(dev);
480
481                         uclass_next_device(&dev);
482                         num_devices++;
483                 } while (dev);
484
485                 putc('\n');
486         }
487
488         return num_devices;
489 }
490
491 static int eth_post_bind(struct udevice *dev)
492 {
493         if (strchr(dev->name, ' ')) {
494                 printf("\nError: eth device name \"%s\" has a space!\n",
495                        dev->name);
496                 return -EINVAL;
497         }
498
499         return 0;
500 }
501
502 static int eth_pre_unbind(struct udevice *dev)
503 {
504         /* Don't hang onto a pointer that is going away */
505         if (dev == eth_get_uclass_priv()->current)
506                 eth_set_dev(NULL);
507
508         return 0;
509 }
510
511 static int eth_post_probe(struct udevice *dev)
512 {
513         struct eth_device_priv *priv = dev->uclass_priv;
514         struct eth_pdata *pdata = dev->platdata;
515         unsigned char env_enetaddr[6];
516
517         priv->state = ETH_STATE_INIT;
518
519         /* Check if the device has a MAC address in ROM */
520         if (eth_get_ops(dev)->read_rom_hwaddr)
521                 eth_get_ops(dev)->read_rom_hwaddr(dev);
522
523         eth_getenv_enetaddr_by_index("eth", dev->seq, env_enetaddr);
524         if (!is_zero_ethaddr(env_enetaddr)) {
525                 if (!is_zero_ethaddr(pdata->enetaddr) &&
526                     memcmp(pdata->enetaddr, env_enetaddr, 6)) {
527                         printf("\nWarning: %s MAC addresses don't match:\n",
528                                dev->name);
529                         printf("Address in SROM is         %pM\n",
530                                pdata->enetaddr);
531                         printf("Address in environment is  %pM\n",
532                                env_enetaddr);
533                 }
534
535                 /* Override the ROM MAC address */
536                 memcpy(pdata->enetaddr, env_enetaddr, 6);
537         } else if (is_valid_ethaddr(pdata->enetaddr)) {
538                 eth_setenv_enetaddr_by_index("eth", dev->seq, pdata->enetaddr);
539                 printf("\nWarning: %s using MAC address from ROM\n",
540                        dev->name);
541         } else if (is_zero_ethaddr(pdata->enetaddr)) {
542 #ifdef CONFIG_NET_RANDOM_ETHADDR
543                 net_random_ethaddr(pdata->enetaddr);
544                 printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
545                        dev->name, dev->seq, pdata->enetaddr);
546 #else
547                 printf("\nError: %s address not set.\n",
548                        dev->name);
549                 return -EINVAL;
550 #endif
551         }
552
553         return 0;
554 }
555
556 static int eth_pre_remove(struct udevice *dev)
557 {
558         eth_get_ops(dev)->stop(dev);
559
560         return 0;
561 }
562
563 UCLASS_DRIVER(eth) = {
564         .name           = "eth",
565         .id             = UCLASS_ETH,
566         .post_bind      = eth_post_bind,
567         .pre_unbind     = eth_pre_unbind,
568         .post_probe     = eth_post_probe,
569         .pre_remove     = eth_pre_remove,
570         .priv_auto_alloc_size = sizeof(struct eth_uclass_priv),
571         .per_device_auto_alloc_size = sizeof(struct eth_device_priv),
572         .flags          = DM_UC_FLAG_SEQ_ALIAS,
573 };
574 #endif
575
576 #ifndef CONFIG_DM_ETH
577
578 #ifdef CONFIG_API
579 static struct {
580         uchar data[PKTSIZE];
581         int length;
582 } eth_rcv_bufs[PKTBUFSRX];
583
584 static unsigned int eth_rcv_current, eth_rcv_last;
585 #endif
586
587 static struct eth_device *eth_devices;
588 struct eth_device *eth_current;
589
590 static void eth_set_current_to_next(void)
591 {
592         eth_current = eth_current->next;
593 }
594
595 static void eth_set_dev(struct eth_device *dev)
596 {
597         eth_current = dev;
598 }
599
600 struct eth_device *eth_get_dev_by_name(const char *devname)
601 {
602         struct eth_device *dev, *target_dev;
603
604         BUG_ON(devname == NULL);
605
606         if (!eth_devices)
607                 return NULL;
608
609         dev = eth_devices;
610         target_dev = NULL;
611         do {
612                 if (strcmp(devname, dev->name) == 0) {
613                         target_dev = dev;
614                         break;
615                 }
616                 dev = dev->next;
617         } while (dev != eth_devices);
618
619         return target_dev;
620 }
621
622 struct eth_device *eth_get_dev_by_index(int index)
623 {
624         struct eth_device *dev, *target_dev;
625
626         if (!eth_devices)
627                 return NULL;
628
629         dev = eth_devices;
630         target_dev = NULL;
631         do {
632                 if (dev->index == index) {
633                         target_dev = dev;
634                         break;
635                 }
636                 dev = dev->next;
637         } while (dev != eth_devices);
638
639         return target_dev;
640 }
641
642 int eth_get_dev_index(void)
643 {
644         if (!eth_current)
645                 return -1;
646
647         return eth_current->index;
648 }
649
650 static int on_ethaddr(const char *name, const char *value, enum env_op op,
651         int flags)
652 {
653         int index;
654         struct eth_device *dev;
655
656         if (!eth_devices)
657                 return 0;
658
659         /* look for an index after "eth" */
660         index = simple_strtoul(name + 3, NULL, 10);
661
662         dev = eth_devices;
663         do {
664                 if (dev->index == index) {
665                         switch (op) {
666                         case env_op_create:
667                         case env_op_overwrite:
668                                 eth_parse_enetaddr(value, dev->enetaddr);
669                                 break;
670                         case env_op_delete:
671                                 memset(dev->enetaddr, 0, 6);
672                         }
673                 }
674         } while (dev != eth_devices);
675
676         return 0;
677 }
678 U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr);
679
680 int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
681                    int eth_number)
682 {
683         unsigned char env_enetaddr[6];
684         int ret = 0;
685
686         eth_getenv_enetaddr_by_index(base_name, eth_number, env_enetaddr);
687
688         if (!is_zero_ethaddr(env_enetaddr)) {
689                 if (!is_zero_ethaddr(dev->enetaddr) &&
690                     memcmp(dev->enetaddr, env_enetaddr, 6)) {
691                         printf("\nWarning: %s MAC addresses don't match:\n",
692                                dev->name);
693                         printf("Address in SROM is         %pM\n",
694                                dev->enetaddr);
695                         printf("Address in environment is  %pM\n",
696                                env_enetaddr);
697                 }
698
699                 memcpy(dev->enetaddr, env_enetaddr, 6);
700         } else if (is_valid_ethaddr(dev->enetaddr)) {
701                 eth_setenv_enetaddr_by_index(base_name, eth_number,
702                                              dev->enetaddr);
703                 printf("\nWarning: %s using MAC address from net device\n",
704                        dev->name);
705         } else if (is_zero_ethaddr(dev->enetaddr)) {
706 #ifdef CONFIG_NET_RANDOM_ETHADDR
707                 net_random_ethaddr(dev->enetaddr);
708                 printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
709                        dev->name, eth_number, dev->enetaddr);
710 #else
711                 printf("\nError: %s address not set.\n",
712                        dev->name);
713                 return -EINVAL;
714 #endif
715         }
716
717         if (dev->write_hwaddr && !eth_mac_skip(eth_number)) {
718                 if (!is_valid_ethaddr(dev->enetaddr)) {
719                         printf("\nError: %s address %pM illegal value\n",
720                                dev->name, dev->enetaddr);
721                         return -EINVAL;
722                 }
723
724                 ret = dev->write_hwaddr(dev);
725                 if (ret)
726                         printf("\nWarning: %s failed to set MAC address\n",
727                                dev->name);
728         }
729
730         return ret;
731 }
732
733 int eth_register(struct eth_device *dev)
734 {
735         struct eth_device *d;
736         static int index;
737
738         assert(strlen(dev->name) < sizeof(dev->name));
739
740         if (!eth_devices) {
741                 eth_devices = dev;
742                 eth_current = dev;
743                 eth_current_changed();
744         } else {
745                 for (d = eth_devices; d->next != eth_devices; d = d->next)
746                         ;
747                 d->next = dev;
748         }
749
750         dev->state = ETH_STATE_INIT;
751         dev->next  = eth_devices;
752         dev->index = index++;
753
754         return 0;
755 }
756
757 int eth_unregister(struct eth_device *dev)
758 {
759         struct eth_device *cur;
760
761         /* No device */
762         if (!eth_devices)
763                 return -ENODEV;
764
765         for (cur = eth_devices; cur->next != eth_devices && cur->next != dev;
766              cur = cur->next)
767                 ;
768
769         /* Device not found */
770         if (cur->next != dev)
771                 return -ENODEV;
772
773         cur->next = dev->next;
774
775         if (eth_devices == dev)
776                 eth_devices = dev->next == eth_devices ? NULL : dev->next;
777
778         if (eth_current == dev) {
779                 eth_current = eth_devices;
780                 eth_current_changed();
781         }
782
783         return 0;
784 }
785
786 int eth_initialize(void)
787 {
788         int num_devices = 0;
789
790         eth_devices = NULL;
791         eth_current = NULL;
792         eth_common_init();
793
794         if (!eth_devices) {
795                 puts("No ethernet found.\n");
796                 bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
797         } else {
798                 struct eth_device *dev = eth_devices;
799                 char *ethprime = getenv("ethprime");
800
801                 bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
802                 do {
803                         if (dev->index)
804                                 puts(", ");
805
806                         printf("%s", dev->name);
807
808                         if (ethprime && strcmp(dev->name, ethprime) == 0) {
809                                 eth_current = dev;
810                                 puts(" [PRIME]");
811                         }
812
813                         if (strchr(dev->name, ' '))
814                                 puts("\nWarning: eth device name has a space!"
815                                         "\n");
816
817                         eth_write_hwaddr(dev, "eth", dev->index);
818
819                         dev = dev->next;
820                         num_devices++;
821                 } while (dev != eth_devices);
822
823                 eth_current_changed();
824                 putc('\n');
825         }
826
827         return num_devices;
828 }
829
830 #ifdef CONFIG_MCAST_TFTP
831 /* Multicast.
832  * mcast_addr: multicast ipaddr from which multicast Mac is made
833  * join: 1=join, 0=leave.
834  */
835 int eth_mcast_join(struct in_addr mcast_ip, int join)
836 {
837         u8 mcast_mac[6];
838         if (!eth_current || !eth_current->mcast)
839                 return -1;
840         mcast_mac[5] = htonl(mcast_ip.s_addr) & 0xff;
841         mcast_mac[4] = (htonl(mcast_ip.s_addr)>>8) & 0xff;
842         mcast_mac[3] = (htonl(mcast_ip.s_addr)>>16) & 0x7f;
843         mcast_mac[2] = 0x5e;
844         mcast_mac[1] = 0x0;
845         mcast_mac[0] = 0x1;
846         return eth_current->mcast(eth_current, mcast_mac, join);
847 }
848
849 /* the 'way' for ethernet-CRC-32. Spliced in from Linux lib/crc32.c
850  * and this is the ethernet-crc method needed for TSEC -- and perhaps
851  * some other adapter -- hash tables
852  */
853 #define CRCPOLY_LE 0xedb88320
854 u32 ether_crc(size_t len, unsigned char const *p)
855 {
856         int i;
857         u32 crc;
858         crc = ~0;
859         while (len--) {
860                 crc ^= *p++;
861                 for (i = 0; i < 8; i++)
862                         crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
863         }
864         /* an reverse the bits, cuz of way they arrive -- last-first */
865         crc = (crc >> 16) | (crc << 16);
866         crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00);
867         crc = (crc >> 4 & 0x0f0f0f0f) | (crc << 4 & 0xf0f0f0f0);
868         crc = (crc >> 2 & 0x33333333) | (crc << 2 & 0xcccccccc);
869         crc = (crc >> 1 & 0x55555555) | (crc << 1 & 0xaaaaaaaa);
870         return crc;
871 }
872
873 #endif
874
875
876 int eth_init(void)
877 {
878         struct eth_device *old_current;
879
880         if (!eth_current) {
881                 puts("No ethernet found.\n");
882                 return -ENODEV;
883         }
884
885         old_current = eth_current;
886         do {
887                 debug("Trying %s\n", eth_current->name);
888
889                 if (eth_current->init(eth_current, gd->bd) >= 0) {
890                         eth_current->state = ETH_STATE_ACTIVE;
891
892                         return 0;
893                 }
894                 debug("FAIL\n");
895
896                 eth_try_another(0);
897         } while (old_current != eth_current);
898
899         return -ETIMEDOUT;
900 }
901
902 void eth_halt(void)
903 {
904         if (!eth_current)
905                 return;
906
907         eth_current->halt(eth_current);
908
909         eth_current->state = ETH_STATE_PASSIVE;
910 }
911
912 int eth_send(void *packet, int length)
913 {
914         if (!eth_current)
915                 return -ENODEV;
916
917         return eth_current->send(eth_current, packet, length);
918 }
919
920 int eth_rx(void)
921 {
922         if (!eth_current)
923                 return -ENODEV;
924
925         return eth_current->recv(eth_current);
926 }
927 #endif /* ifndef CONFIG_DM_ETH */
928
929 #ifdef CONFIG_API
930 static void eth_save_packet(void *packet, int length)
931 {
932         char *p = packet;
933         int i;
934
935         if ((eth_rcv_last+1) % PKTBUFSRX == eth_rcv_current)
936                 return;
937
938         if (PKTSIZE < length)
939                 return;
940
941         for (i = 0; i < length; i++)
942                 eth_rcv_bufs[eth_rcv_last].data[i] = p[i];
943
944         eth_rcv_bufs[eth_rcv_last].length = length;
945         eth_rcv_last = (eth_rcv_last + 1) % PKTBUFSRX;
946 }
947
948 int eth_receive(void *packet, int length)
949 {
950         char *p = packet;
951         void *pp = push_packet;
952         int i;
953
954         if (eth_rcv_current == eth_rcv_last) {
955                 push_packet = eth_save_packet;
956                 eth_rx();
957                 push_packet = pp;
958
959                 if (eth_rcv_current == eth_rcv_last)
960                         return -1;
961         }
962
963         length = min(eth_rcv_bufs[eth_rcv_current].length, length);
964
965         for (i = 0; i < length; i++)
966                 p[i] = eth_rcv_bufs[eth_rcv_current].data[i];
967
968         eth_rcv_current = (eth_rcv_current + 1) % PKTBUFSRX;
969         return length;
970 }
971 #endif /* CONFIG_API */
972
973 static void eth_current_changed(void)
974 {
975         char *act = getenv("ethact");
976         /* update current ethernet name */
977         if (eth_get_dev()) {
978                 if (act == NULL || strcmp(act, eth_get_name()) != 0)
979                         setenv("ethact", eth_get_name());
980         }
981         /*
982          * remove the variable completely if there is no active
983          * interface
984          */
985         else if (act != NULL)
986                 setenv("ethact", NULL);
987 }
988
989 void eth_try_another(int first_restart)
990 {
991         static void *first_failed;
992         char *ethrotate;
993
994         /*
995          * Do not rotate between network interfaces when
996          * 'ethrotate' variable is set to 'no'.
997          */
998         ethrotate = getenv("ethrotate");
999         if ((ethrotate != NULL) && (strcmp(ethrotate, "no") == 0))
1000                 return;
1001
1002         if (!eth_get_dev())
1003                 return;
1004
1005         if (first_restart)
1006                 first_failed = eth_get_dev();
1007
1008         eth_set_current_to_next();
1009
1010         eth_current_changed();
1011
1012         if (first_failed == eth_get_dev())
1013                 net_restart_wrap = 1;
1014 }
1015
1016 void eth_set_current(void)
1017 {
1018         static char *act;
1019         static int  env_changed_id;
1020         int     env_id;
1021
1022         env_id = get_env_id();
1023         if ((act == NULL) || (env_changed_id != env_id)) {
1024                 act = getenv("ethact");
1025                 env_changed_id = env_id;
1026         }
1027
1028         if (act == NULL) {
1029                 char *ethprime = getenv("ethprime");
1030                 void *dev = NULL;
1031
1032                 if (ethprime)
1033                         dev = eth_get_dev_by_name(ethprime);
1034                 if (dev)
1035                         eth_set_dev(dev);
1036                 else
1037                         eth_set_dev(NULL);
1038         } else {
1039                 eth_set_dev(eth_get_dev_by_name(act));
1040         }
1041
1042         eth_current_changed();
1043 }
1044
1045 const char *eth_get_name(void)
1046 {
1047         return eth_get_dev() ? eth_get_dev()->name : "unknown";
1048 }