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