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