xref: /openbmc/u-boot/net/eth_legacy.c (revision 68489ed037530ec29fc0bc452ad6e4b0c5db02ec)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2c4998f96SSimon Glass /*
3c4998f96SSimon Glass  * (C) Copyright 2001-2015
4c4998f96SSimon Glass  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5c4998f96SSimon Glass  * Joe Hershberger, National Instruments
6c4998f96SSimon Glass  */
7c4998f96SSimon Glass 
8c4998f96SSimon Glass #include <common.h>
9c4998f96SSimon Glass #include <command.h>
10c4998f96SSimon Glass #include <environment.h>
11c4998f96SSimon Glass #include <net.h>
12c4998f96SSimon Glass #include <phy.h>
131221ce45SMasahiro Yamada #include <linux/errno.h>
14c4998f96SSimon Glass #include "eth_internal.h"
15c4998f96SSimon Glass 
16c4998f96SSimon Glass DECLARE_GLOBAL_DATA_PTR;
17c4998f96SSimon Glass 
18c4998f96SSimon Glass /*
19c4998f96SSimon Glass  * CPU and board-specific Ethernet initializations.  Aliased function
20c4998f96SSimon Glass  * signals caller to move on
21c4998f96SSimon Glass  */
__def_eth_init(bd_t * bis)22c4998f96SSimon Glass static int __def_eth_init(bd_t *bis)
23c4998f96SSimon Glass {
24c4998f96SSimon Glass 	return -1;
25c4998f96SSimon Glass }
26c4998f96SSimon Glass int cpu_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
27c4998f96SSimon Glass int board_eth_init(bd_t *bis) __attribute__((weak, alias("__def_eth_init")));
28c4998f96SSimon Glass 
29c4998f96SSimon Glass #ifdef CONFIG_API
30c4998f96SSimon Glass static struct {
31c4998f96SSimon Glass 	uchar data[PKTSIZE];
32c4998f96SSimon Glass 	int length;
33c4998f96SSimon Glass } eth_rcv_bufs[PKTBUFSRX];
34c4998f96SSimon Glass 
35c4998f96SSimon Glass static unsigned int eth_rcv_current, eth_rcv_last;
36c4998f96SSimon Glass #endif
37c4998f96SSimon Glass 
38c4998f96SSimon Glass static struct eth_device *eth_devices;
39c4998f96SSimon Glass struct eth_device *eth_current;
40c4998f96SSimon Glass 
eth_set_current_to_next(void)41c4998f96SSimon Glass void eth_set_current_to_next(void)
42c4998f96SSimon Glass {
43c4998f96SSimon Glass 	eth_current = eth_current->next;
44c4998f96SSimon Glass }
45c4998f96SSimon Glass 
eth_set_dev(struct eth_device * dev)46c4998f96SSimon Glass void eth_set_dev(struct eth_device *dev)
47c4998f96SSimon Glass {
48c4998f96SSimon Glass 	eth_current = dev;
49c4998f96SSimon Glass }
50c4998f96SSimon Glass 
eth_get_dev_by_name(const char * devname)51c4998f96SSimon Glass struct eth_device *eth_get_dev_by_name(const char *devname)
52c4998f96SSimon Glass {
53c4998f96SSimon Glass 	struct eth_device *dev, *target_dev;
54c4998f96SSimon Glass 
55c4998f96SSimon Glass 	BUG_ON(devname == NULL);
56c4998f96SSimon Glass 
57c4998f96SSimon Glass 	if (!eth_devices)
58c4998f96SSimon Glass 		return NULL;
59c4998f96SSimon Glass 
60c4998f96SSimon Glass 	dev = eth_devices;
61c4998f96SSimon Glass 	target_dev = NULL;
62c4998f96SSimon Glass 	do {
63c4998f96SSimon Glass 		if (strcmp(devname, dev->name) == 0) {
64c4998f96SSimon Glass 			target_dev = dev;
65c4998f96SSimon Glass 			break;
66c4998f96SSimon Glass 		}
67c4998f96SSimon Glass 		dev = dev->next;
68c4998f96SSimon Glass 	} while (dev != eth_devices);
69c4998f96SSimon Glass 
70c4998f96SSimon Glass 	return target_dev;
71c4998f96SSimon Glass }
72c4998f96SSimon Glass 
eth_get_dev_by_index(int index)73c4998f96SSimon Glass struct eth_device *eth_get_dev_by_index(int index)
74c4998f96SSimon Glass {
75c4998f96SSimon Glass 	struct eth_device *dev, *target_dev;
76c4998f96SSimon Glass 
77c4998f96SSimon Glass 	if (!eth_devices)
78c4998f96SSimon Glass 		return NULL;
79c4998f96SSimon Glass 
80c4998f96SSimon Glass 	dev = eth_devices;
81c4998f96SSimon Glass 	target_dev = NULL;
82c4998f96SSimon Glass 	do {
83c4998f96SSimon Glass 		if (dev->index == index) {
84c4998f96SSimon Glass 			target_dev = dev;
85c4998f96SSimon Glass 			break;
86c4998f96SSimon Glass 		}
87c4998f96SSimon Glass 		dev = dev->next;
88c4998f96SSimon Glass 	} while (dev != eth_devices);
89c4998f96SSimon Glass 
90c4998f96SSimon Glass 	return target_dev;
91c4998f96SSimon Glass }
92c4998f96SSimon Glass 
eth_get_dev_index(void)93c4998f96SSimon Glass int eth_get_dev_index(void)
94c4998f96SSimon Glass {
95c4998f96SSimon Glass 	if (!eth_current)
96c4998f96SSimon Glass 		return -1;
97c4998f96SSimon Glass 
98c4998f96SSimon Glass 	return eth_current->index;
99c4998f96SSimon Glass }
100c4998f96SSimon Glass 
on_ethaddr(const char * name,const char * value,enum env_op op,int flags)101c4998f96SSimon Glass static int on_ethaddr(const char *name, const char *value, enum env_op op,
102c4998f96SSimon Glass 	int flags)
103c4998f96SSimon Glass {
104c4998f96SSimon Glass 	int index;
105c4998f96SSimon Glass 	struct eth_device *dev;
106c4998f96SSimon Glass 
107c4998f96SSimon Glass 	if (!eth_devices)
108c4998f96SSimon Glass 		return 0;
109c4998f96SSimon Glass 
110c4998f96SSimon Glass 	/* look for an index after "eth" */
111c4998f96SSimon Glass 	index = simple_strtoul(name + 3, NULL, 10);
112c4998f96SSimon Glass 
113c4998f96SSimon Glass 	dev = eth_devices;
114c4998f96SSimon Glass 	do {
115c4998f96SSimon Glass 		if (dev->index == index) {
116c4998f96SSimon Glass 			switch (op) {
117c4998f96SSimon Glass 			case env_op_create:
118c4998f96SSimon Glass 			case env_op_overwrite:
119c4998f96SSimon Glass 				eth_parse_enetaddr(value, dev->enetaddr);
12073d570a7SMarek Vasut 				eth_write_hwaddr(dev, "eth", dev->index);
121c4998f96SSimon Glass 				break;
122c4998f96SSimon Glass 			case env_op_delete:
123a40db6d5Soliver@schinagl.nl 				memset(dev->enetaddr, 0, ARP_HLEN);
124c4998f96SSimon Glass 			}
125c4998f96SSimon Glass 		}
126c4998f96SSimon Glass 		dev = dev->next;
127c4998f96SSimon Glass 	} while (dev != eth_devices);
128c4998f96SSimon Glass 
129c4998f96SSimon Glass 	return 0;
130c4998f96SSimon Glass }
131c4998f96SSimon Glass U_BOOT_ENV_CALLBACK(ethaddr, on_ethaddr);
132c4998f96SSimon Glass 
eth_write_hwaddr(struct eth_device * dev,const char * base_name,int eth_number)133c4998f96SSimon Glass int eth_write_hwaddr(struct eth_device *dev, const char *base_name,
134c4998f96SSimon Glass 		   int eth_number)
135c4998f96SSimon Glass {
136a40db6d5Soliver@schinagl.nl 	unsigned char env_enetaddr[ARP_HLEN];
137c4998f96SSimon Glass 	int ret = 0;
138c4998f96SSimon Glass 
13935affd7aSSimon Glass 	eth_env_get_enetaddr_by_index(base_name, eth_number, env_enetaddr);
140c4998f96SSimon Glass 
141c4998f96SSimon Glass 	if (!is_zero_ethaddr(env_enetaddr)) {
142c4998f96SSimon Glass 		if (!is_zero_ethaddr(dev->enetaddr) &&
143a40db6d5Soliver@schinagl.nl 		    memcmp(dev->enetaddr, env_enetaddr, ARP_HLEN)) {
144c4998f96SSimon Glass 			printf("\nWarning: %s MAC addresses don't match:\n",
145c4998f96SSimon Glass 			       dev->name);
146c4998f96SSimon Glass 			printf("Address in SROM is         %pM\n",
147c4998f96SSimon Glass 			       dev->enetaddr);
148c4998f96SSimon Glass 			printf("Address in environment is  %pM\n",
149c4998f96SSimon Glass 			       env_enetaddr);
150c4998f96SSimon Glass 		}
151c4998f96SSimon Glass 
152a40db6d5Soliver@schinagl.nl 		memcpy(dev->enetaddr, env_enetaddr, ARP_HLEN);
153c4998f96SSimon Glass 	} else if (is_valid_ethaddr(dev->enetaddr)) {
154fd1e959eSSimon Glass 		eth_env_set_enetaddr_by_index(base_name, eth_number,
155c4998f96SSimon Glass 					      dev->enetaddr);
156c4998f96SSimon Glass 	} else if (is_zero_ethaddr(dev->enetaddr)) {
157c4998f96SSimon Glass #ifdef CONFIG_NET_RANDOM_ETHADDR
158c4998f96SSimon Glass 		net_random_ethaddr(dev->enetaddr);
159c4998f96SSimon Glass 		printf("\nWarning: %s (eth%d) using random MAC address - %pM\n",
160c4998f96SSimon Glass 		       dev->name, eth_number, dev->enetaddr);
161c4998f96SSimon Glass #else
162c4998f96SSimon Glass 		printf("\nError: %s address not set.\n",
163c4998f96SSimon Glass 		       dev->name);
164c4998f96SSimon Glass 		return -EINVAL;
165c4998f96SSimon Glass #endif
166c4998f96SSimon Glass 	}
167c4998f96SSimon Glass 
168c4998f96SSimon Glass 	if (dev->write_hwaddr && !eth_mac_skip(eth_number)) {
169c4998f96SSimon Glass 		if (!is_valid_ethaddr(dev->enetaddr)) {
170c4998f96SSimon Glass 			printf("\nError: %s address %pM illegal value\n",
171c4998f96SSimon Glass 			       dev->name, dev->enetaddr);
172c4998f96SSimon Glass 			return -EINVAL;
173c4998f96SSimon Glass 		}
174c4998f96SSimon Glass 
175c4998f96SSimon Glass 		ret = dev->write_hwaddr(dev);
176c4998f96SSimon Glass 		if (ret)
177c4998f96SSimon Glass 			printf("\nWarning: %s failed to set MAC address\n",
178c4998f96SSimon Glass 			       dev->name);
179c4998f96SSimon Glass 	}
180c4998f96SSimon Glass 
181c4998f96SSimon Glass 	return ret;
182c4998f96SSimon Glass }
183c4998f96SSimon Glass 
eth_register(struct eth_device * dev)184c4998f96SSimon Glass int eth_register(struct eth_device *dev)
185c4998f96SSimon Glass {
186c4998f96SSimon Glass 	struct eth_device *d;
187c4998f96SSimon Glass 	static int index;
188c4998f96SSimon Glass 
189c4998f96SSimon Glass 	assert(strlen(dev->name) < sizeof(dev->name));
190c4998f96SSimon Glass 
191c4998f96SSimon Glass 	if (!eth_devices) {
192c4998f96SSimon Glass 		eth_devices = dev;
193c4998f96SSimon Glass 		eth_current = dev;
194c4998f96SSimon Glass 		eth_current_changed();
195c4998f96SSimon Glass 	} else {
196c4998f96SSimon Glass 		for (d = eth_devices; d->next != eth_devices; d = d->next)
197c4998f96SSimon Glass 			;
198c4998f96SSimon Glass 		d->next = dev;
199c4998f96SSimon Glass 	}
200c4998f96SSimon Glass 
201c4998f96SSimon Glass 	dev->state = ETH_STATE_INIT;
202c4998f96SSimon Glass 	dev->next  = eth_devices;
203c4998f96SSimon Glass 	dev->index = index++;
204c4998f96SSimon Glass 
205c4998f96SSimon Glass 	return 0;
206c4998f96SSimon Glass }
207c4998f96SSimon Glass 
eth_unregister(struct eth_device * dev)208c4998f96SSimon Glass int eth_unregister(struct eth_device *dev)
209c4998f96SSimon Glass {
210c4998f96SSimon Glass 	struct eth_device *cur;
211c4998f96SSimon Glass 
212c4998f96SSimon Glass 	/* No device */
213c4998f96SSimon Glass 	if (!eth_devices)
214c4998f96SSimon Glass 		return -ENODEV;
215c4998f96SSimon Glass 
216c4998f96SSimon Glass 	for (cur = eth_devices; cur->next != eth_devices && cur->next != dev;
217c4998f96SSimon Glass 	     cur = cur->next)
218c4998f96SSimon Glass 		;
219c4998f96SSimon Glass 
220c4998f96SSimon Glass 	/* Device not found */
221c4998f96SSimon Glass 	if (cur->next != dev)
222c4998f96SSimon Glass 		return -ENODEV;
223c4998f96SSimon Glass 
224c4998f96SSimon Glass 	cur->next = dev->next;
225c4998f96SSimon Glass 
226c4998f96SSimon Glass 	if (eth_devices == dev)
227c4998f96SSimon Glass 		eth_devices = dev->next == eth_devices ? NULL : dev->next;
228c4998f96SSimon Glass 
229c4998f96SSimon Glass 	if (eth_current == dev) {
230c4998f96SSimon Glass 		eth_current = eth_devices;
231c4998f96SSimon Glass 		eth_current_changed();
232c4998f96SSimon Glass 	}
233c4998f96SSimon Glass 
234c4998f96SSimon Glass 	return 0;
235c4998f96SSimon Glass }
236c4998f96SSimon Glass 
eth_initialize(void)237c4998f96SSimon Glass int eth_initialize(void)
238c4998f96SSimon Glass {
239c4998f96SSimon Glass 	int num_devices = 0;
240c4998f96SSimon Glass 
241c4998f96SSimon Glass 	eth_devices = NULL;
242c4998f96SSimon Glass 	eth_current = NULL;
243c4998f96SSimon Glass 	eth_common_init();
244c4998f96SSimon Glass 	/*
245c4998f96SSimon Glass 	 * If board-specific initialization exists, call it.
246c4998f96SSimon Glass 	 * If not, call a CPU-specific one
247c4998f96SSimon Glass 	 */
248c4998f96SSimon Glass 	if (board_eth_init != __def_eth_init) {
249c4998f96SSimon Glass 		if (board_eth_init(gd->bd) < 0)
250c4998f96SSimon Glass 			printf("Board Net Initialization Failed\n");
251c4998f96SSimon Glass 	} else if (cpu_eth_init != __def_eth_init) {
252c4998f96SSimon Glass 		if (cpu_eth_init(gd->bd) < 0)
253c4998f96SSimon Glass 			printf("CPU Net Initialization Failed\n");
254c4998f96SSimon Glass 	} else {
255c4998f96SSimon Glass 		printf("Net Initialization Skipped\n");
256c4998f96SSimon Glass 	}
257c4998f96SSimon Glass 
258c4998f96SSimon Glass 	if (!eth_devices) {
259c4998f96SSimon Glass 		puts("No ethernet found.\n");
260c4998f96SSimon Glass 		bootstage_error(BOOTSTAGE_ID_NET_ETH_START);
261c4998f96SSimon Glass 	} else {
262c4998f96SSimon Glass 		struct eth_device *dev = eth_devices;
26300caae6dSSimon Glass 		char *ethprime = env_get("ethprime");
264c4998f96SSimon Glass 
265c4998f96SSimon Glass 		bootstage_mark(BOOTSTAGE_ID_NET_ETH_INIT);
266c4998f96SSimon Glass 		do {
267c4998f96SSimon Glass 			if (dev->index)
268c4998f96SSimon Glass 				puts(", ");
269c4998f96SSimon Glass 
270c4998f96SSimon Glass 			printf("%s", dev->name);
271c4998f96SSimon Glass 
272c4998f96SSimon Glass 			if (ethprime && strcmp(dev->name, ethprime) == 0) {
273c4998f96SSimon Glass 				eth_current = dev;
274c4998f96SSimon Glass 				puts(" [PRIME]");
275c4998f96SSimon Glass 			}
276c4998f96SSimon Glass 
277c4998f96SSimon Glass 			if (strchr(dev->name, ' '))
278c4998f96SSimon Glass 				puts("\nWarning: eth device name has a space!"
279c4998f96SSimon Glass 					"\n");
280c4998f96SSimon Glass 
281c4998f96SSimon Glass 			eth_write_hwaddr(dev, "eth", dev->index);
282c4998f96SSimon Glass 
283c4998f96SSimon Glass 			dev = dev->next;
284c4998f96SSimon Glass 			num_devices++;
285c4998f96SSimon Glass 		} while (dev != eth_devices);
286c4998f96SSimon Glass 
287c4998f96SSimon Glass 		eth_current_changed();
288c4998f96SSimon Glass 		putc('\n');
289c4998f96SSimon Glass 	}
290c4998f96SSimon Glass 
291c4998f96SSimon Glass 	return num_devices;
292c4998f96SSimon Glass }
293c4998f96SSimon Glass 
294c4998f96SSimon Glass /* Multicast.
295c4998f96SSimon Glass  * mcast_addr: multicast ipaddr from which multicast Mac is made
296c4998f96SSimon Glass  * join: 1=join, 0=leave.
297c4998f96SSimon Glass  */
eth_mcast_join(struct in_addr mcast_ip,int join)298c4998f96SSimon Glass int eth_mcast_join(struct in_addr mcast_ip, int join)
299c4998f96SSimon Glass {
300a40db6d5Soliver@schinagl.nl 	u8 mcast_mac[ARP_HLEN];
301c4998f96SSimon Glass 	if (!eth_current || !eth_current->mcast)
302c4998f96SSimon Glass 		return -1;
303c4998f96SSimon Glass 	mcast_mac[5] = htonl(mcast_ip.s_addr) & 0xff;
304c4998f96SSimon Glass 	mcast_mac[4] = (htonl(mcast_ip.s_addr)>>8) & 0xff;
305c4998f96SSimon Glass 	mcast_mac[3] = (htonl(mcast_ip.s_addr)>>16) & 0x7f;
306c4998f96SSimon Glass 	mcast_mac[2] = 0x5e;
307c4998f96SSimon Glass 	mcast_mac[1] = 0x0;
308c4998f96SSimon Glass 	mcast_mac[0] = 0x1;
309c4998f96SSimon Glass 	return eth_current->mcast(eth_current, mcast_mac, join);
310c4998f96SSimon Glass }
311c4998f96SSimon Glass 
eth_init(void)312c4998f96SSimon Glass int eth_init(void)
313c4998f96SSimon Glass {
314c4998f96SSimon Glass 	struct eth_device *old_current;
315c4998f96SSimon Glass 
316c4998f96SSimon Glass 	if (!eth_current) {
317c4998f96SSimon Glass 		puts("No ethernet found.\n");
318c4998f96SSimon Glass 		return -ENODEV;
319c4998f96SSimon Glass 	}
320c4998f96SSimon Glass 
321c4998f96SSimon Glass 	old_current = eth_current;
322c4998f96SSimon Glass 	do {
323c4998f96SSimon Glass 		debug("Trying %s\n", eth_current->name);
324c4998f96SSimon Glass 
325c4998f96SSimon Glass 		if (eth_current->init(eth_current, gd->bd) >= 0) {
326c4998f96SSimon Glass 			eth_current->state = ETH_STATE_ACTIVE;
327c4998f96SSimon Glass 
328c4998f96SSimon Glass 			return 0;
329c4998f96SSimon Glass 		}
330c4998f96SSimon Glass 		debug("FAIL\n");
331c4998f96SSimon Glass 
332c4998f96SSimon Glass 		eth_try_another(0);
333c4998f96SSimon Glass 	} while (old_current != eth_current);
334c4998f96SSimon Glass 
335c4998f96SSimon Glass 	return -ETIMEDOUT;
336c4998f96SSimon Glass }
337c4998f96SSimon Glass 
eth_halt(void)338c4998f96SSimon Glass void eth_halt(void)
339c4998f96SSimon Glass {
340c4998f96SSimon Glass 	if (!eth_current)
341c4998f96SSimon Glass 		return;
342c4998f96SSimon Glass 
343c4998f96SSimon Glass 	eth_current->halt(eth_current);
344c4998f96SSimon Glass 
345c4998f96SSimon Glass 	eth_current->state = ETH_STATE_PASSIVE;
346c4998f96SSimon Glass }
347c4998f96SSimon Glass 
eth_is_active(struct eth_device * dev)348c4998f96SSimon Glass int eth_is_active(struct eth_device *dev)
349c4998f96SSimon Glass {
350c4998f96SSimon Glass 	return dev && dev->state == ETH_STATE_ACTIVE;
351c4998f96SSimon Glass }
352c4998f96SSimon Glass 
eth_send(void * packet,int length)353c4998f96SSimon Glass int eth_send(void *packet, int length)
354c4998f96SSimon Glass {
355c4998f96SSimon Glass 	if (!eth_current)
356c4998f96SSimon Glass 		return -ENODEV;
357c4998f96SSimon Glass 
358c4998f96SSimon Glass 	return eth_current->send(eth_current, packet, length);
359c4998f96SSimon Glass }
360c4998f96SSimon Glass 
eth_rx(void)361c4998f96SSimon Glass int eth_rx(void)
362c4998f96SSimon Glass {
363c4998f96SSimon Glass 	if (!eth_current)
364c4998f96SSimon Glass 		return -ENODEV;
365c4998f96SSimon Glass 
366c4998f96SSimon Glass 	return eth_current->recv(eth_current);
367c4998f96SSimon Glass }
368c4998f96SSimon Glass 
369c4998f96SSimon Glass #ifdef CONFIG_API
eth_save_packet(void * packet,int length)370c4998f96SSimon Glass static void eth_save_packet(void *packet, int length)
371c4998f96SSimon Glass {
372c4998f96SSimon Glass 	char *p = packet;
373c4998f96SSimon Glass 	int i;
374c4998f96SSimon Glass 
375c4998f96SSimon Glass 	if ((eth_rcv_last+1) % PKTBUFSRX == eth_rcv_current)
376c4998f96SSimon Glass 		return;
377c4998f96SSimon Glass 
378c4998f96SSimon Glass 	if (PKTSIZE < length)
379c4998f96SSimon Glass 		return;
380c4998f96SSimon Glass 
381c4998f96SSimon Glass 	for (i = 0; i < length; i++)
382c4998f96SSimon Glass 		eth_rcv_bufs[eth_rcv_last].data[i] = p[i];
383c4998f96SSimon Glass 
384c4998f96SSimon Glass 	eth_rcv_bufs[eth_rcv_last].length = length;
385c4998f96SSimon Glass 	eth_rcv_last = (eth_rcv_last + 1) % PKTBUFSRX;
386c4998f96SSimon Glass }
387c4998f96SSimon Glass 
eth_receive(void * packet,int length)388c4998f96SSimon Glass int eth_receive(void *packet, int length)
389c4998f96SSimon Glass {
390c4998f96SSimon Glass 	char *p = packet;
391c4998f96SSimon Glass 	void *pp = push_packet;
392c4998f96SSimon Glass 	int i;
393c4998f96SSimon Glass 
394c4998f96SSimon Glass 	if (eth_rcv_current == eth_rcv_last) {
395c4998f96SSimon Glass 		push_packet = eth_save_packet;
396c4998f96SSimon Glass 		eth_rx();
397c4998f96SSimon Glass 		push_packet = pp;
398c4998f96SSimon Glass 
399c4998f96SSimon Glass 		if (eth_rcv_current == eth_rcv_last)
400c4998f96SSimon Glass 			return -1;
401c4998f96SSimon Glass 	}
402c4998f96SSimon Glass 
403c4998f96SSimon Glass 	length = min(eth_rcv_bufs[eth_rcv_current].length, length);
404c4998f96SSimon Glass 
405c4998f96SSimon Glass 	for (i = 0; i < length; i++)
406c4998f96SSimon Glass 		p[i] = eth_rcv_bufs[eth_rcv_current].data[i];
407c4998f96SSimon Glass 
408c4998f96SSimon Glass 	eth_rcv_current = (eth_rcv_current + 1) % PKTBUFSRX;
409c4998f96SSimon Glass 	return length;
410c4998f96SSimon Glass }
411c4998f96SSimon Glass #endif /* CONFIG_API */
412