xref: /rk3399_rockchip-uboot/net/net.c (revision 0c852a2886fb51222f8fb07e6cde3b72fa4e566d)
1 /*
2  *	Copied from Linux Monitor (LiMon) - Networking.
3  *
4  *	Copyright 1994 - 2000 Neil Russell.
5  *	(See License)
6  *	Copyright 2000 Roland Borde
7  *	Copyright 2000 Paolo Scaffardi
8  *	Copyright 2000-2002 Wolfgang Denk, wd@denx.de
9  */
10 
11 /*
12  * General Desription:
13  *
14  * The user interface supports commands for BOOTP, RARP, and TFTP.
15  * Also, we support ARP internally. Depending on available data,
16  * these interact as follows:
17  *
18  * BOOTP:
19  *
20  *	Prerequisites:	- own ethernet address
21  *	We want:	- own IP address
22  *			- TFTP server IP address
23  *			- name of bootfile
24  *	Next step:	ARP
25  *
26  * RARP:
27  *
28  *	Prerequisites:	- own ethernet address
29  *	We want:	- own IP address
30  *			- TFTP server IP address
31  *	Next step:	ARP
32  *
33  * ARP:
34  *
35  *	Prerequisites:	- own ethernet address
36  *			- own IP address
37  *			- TFTP server IP address
38  *	We want:	- TFTP server ethernet address
39  *	Next step:	TFTP
40  *
41  * DHCP:
42  *
43  *     Prerequisites:   - own ethernet address
44  *     We want:         - IP, Netmask, ServerIP, Gateway IP
45  *                      - bootfilename, lease time
46  *     Next step:       - TFTP
47  *
48  * TFTP:
49  *
50  *	Prerequisites:	- own ethernet address
51  *			- own IP address
52  *			- TFTP server IP address
53  *			- TFTP server ethernet address
54  *			- name of bootfile (if unknown, we use a default name
55  *			  derived from our own IP address)
56  *	We want:	- load the boot file
57  *	Next step:	none
58  *
59  * NFS:
60  *
61  *	Prerequisites:	- own ethernet address
62  *			- own IP address
63  *			- name of bootfile (if unknown, we use a default name
64  *			  derived from our own IP address)
65  *	We want:	- load the boot file
66  *	Next step:	none
67  */
68 
69 
70 #include <common.h>
71 #include <watchdog.h>
72 #include <command.h>
73 #include <net.h>
74 #include "bootp.h"
75 #include "tftp.h"
76 #include "rarp.h"
77 #include "nfs.h"
78 #ifdef CONFIG_STATUS_LED
79 #include <status_led.h>
80 #include <miiphy.h>
81 #endif
82 
83 #if (CONFIG_COMMANDS & CFG_CMD_NET)
84 
85 #define ARP_TIMEOUT		5		/* Seconds before trying ARP again */
86 #ifndef	CONFIG_NET_RETRY_COUNT
87 # define ARP_TIMEOUT_COUNT	5		/* # of timeouts before giving up  */
88 #else
89 # define ARP_TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT)
90 #endif
91 
92 #if 0
93 #define ET_DEBUG
94 #endif
95 
96 /** BOOTP EXTENTIONS **/
97 
98 IPaddr_t	NetOurSubnetMask=0;		/* Our subnet mask (0=unknown)	*/
99 IPaddr_t	NetOurGatewayIP=0;		/* Our gateways IP address	*/
100 IPaddr_t	NetOurDNSIP=0;			/* Our DNS IP address		*/
101 #if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)
102 IPaddr_t	NetOurDNS2IP=0;			/* Our 2nd DNS IP address	*/
103 #endif
104 char		NetOurNISDomain[32]={0,};	/* Our NIS domain		*/
105 char		NetOurHostName[32]={0,};	/* Our hostname			*/
106 char		NetOurRootPath[64]={0,};	/* Our bootpath			*/
107 ushort		NetBootFileSize=0;		/* Our bootfile size in blocks	*/
108 
109 /** END OF BOOTP EXTENTIONS **/
110 
111 ulong		NetBootFileXferSize;	/* The actual transferred size of the bootfile (in bytes) */
112 uchar		NetOurEther[6];		/* Our ethernet address			*/
113 uchar		NetServerEther[6] =	/* Boot server enet address		*/
114 			{ 0, 0, 0, 0, 0, 0 };
115 IPaddr_t	NetOurIP;		/* Our IP addr (0 = unknown)		*/
116 IPaddr_t	NetServerIP;		/* Our IP addr (0 = unknown)		*/
117 volatile uchar *NetRxPkt;		/* Current receive packet		*/
118 int		NetRxPktLen;		/* Current rx packet length		*/
119 unsigned	NetIPID;		/* IP packet ID				*/
120 uchar		NetBcastAddr[6] =	/* Ethernet bcast address		*/
121 			{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
122 uchar		NetEtherNullAddr[6] =
123 			{ 0, 0, 0, 0, 0, 0 };
124 int		NetState;		/* Network loop state			*/
125 #ifdef CONFIG_NET_MULTI
126 int		NetRestartWrap = 0;	/* Tried all network devices		*/
127 static int	NetRestarted = 0;	/* Network loop restarted		*/
128 static int	NetDevExists = 0;	/* At least one device configured	*/
129 #endif
130 
131 char		BootFile[128];		/* Boot File name			*/
132 
133 #if (CONFIG_COMMANDS & CFG_CMD_PING)
134 IPaddr_t	NetPingIP;		/* the ip address to ping 		*/
135 
136 static void PingStart(void);
137 #endif
138 
139 volatile uchar	PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
140 
141 volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets			*/
142 
143 static rxhand_f *packetHandler;		/* Current RX packet handler		*/
144 static thand_f *timeHandler;		/* Current timeout handler		*/
145 static ulong	timeStart;		/* Time base value			*/
146 static ulong	timeDelta;		/* Current timeout value		*/
147 volatile uchar *NetTxPacket = 0;	/* THE transmit packet			*/
148 
149 static int net_check_prereq (proto_t protocol);
150 
151 /**********************************************************************/
152 
153 IPaddr_t	NetArpWaitPacketIP;
154 IPaddr_t	NetArpWaitReplyIP;
155 uchar	       *NetArpWaitPacketMAC;	/* MAC address of waiting packet's destination	*/
156 uchar          *NetArpWaitTxPacket;	/* THE transmit packet			*/
157 int		NetArpWaitTxPacketSize;
158 uchar 		NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
159 ulong		NetArpWaitTimerStart;
160 int		NetArpWaitTry;
161 
162 void ArpRequest(void)
163 {
164 	int i;
165 	volatile uchar *pkt;
166 	ARP_t *	arp;
167 
168 #ifdef ET_DEBUG
169 	printf("ARP broadcast %d\n", NetArpWaitTry);
170 #endif
171 	pkt = NetTxPacket;
172 
173 	NetSetEther(pkt, NetBcastAddr, PROT_ARP);
174 	pkt += ETHER_HDR_SIZE;
175 
176 	arp = (ARP_t *)pkt;
177 
178 	arp->ar_hrd = htons(ARP_ETHER);
179 	arp->ar_pro = htons(PROT_IP);
180 	arp->ar_hln = 6;
181 	arp->ar_pln = 4;
182 	arp->ar_op  = htons(ARPOP_REQUEST);
183 
184 	memcpy (&arp->ar_data[0], NetOurEther, 6);	/* source ET addr	*/
185 	NetWriteIP((uchar*)&arp->ar_data[6], NetOurIP);	/* source IP addr	*/
186 	for (i=10; i<16; ++i) {
187 		arp->ar_data[i] = 0;			/* dest ET addr = 0	*/
188 	}
189 
190 	if((NetArpWaitPacketIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask)) {
191 	    if (NetOurGatewayIP == 0) {
192 		puts ("## Warning: gatewayip needed but not set\n");
193 	    }
194 	    NetArpWaitReplyIP = NetOurGatewayIP;
195 	} else
196 	    NetArpWaitReplyIP = NetArpWaitPacketIP;
197 
198 	NetWriteIP((uchar*)&arp->ar_data[16], NetArpWaitReplyIP);
199 	(void) eth_send(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE);
200 }
201 
202 void ArpTimeoutCheck(void)
203 {
204 	ulong t;
205 
206 	if (!NetArpWaitPacketIP)
207 		return;
208 
209 	t = get_timer(0);
210 
211 	/* check for arp timeout */
212 	if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ) {
213 		NetArpWaitTry++;
214 
215 		if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
216 			puts ("\nARP Retry count exceeded; starting again\n");
217 			NetArpWaitTry = 0;
218 			NetStartAgain();
219 		} else {
220 			NetArpWaitTimerStart = t;
221 			ArpRequest();
222 		}
223 	}
224 }
225 
226 /**********************************************************************/
227 /*
228  *	Main network processing loop.
229  */
230 
231 int
232 NetLoop(proto_t protocol)
233 {
234 	DECLARE_GLOBAL_DATA_PTR;
235 
236 	bd_t *bd = gd->bd;
237 
238 #ifdef CONFIG_NET_MULTI
239 	NetRestarted = 0;
240 	NetDevExists = 0;
241 #endif
242 
243 	/* XXX problem with bss workaround */
244 	NetArpWaitPacketMAC = NULL;
245 	NetArpWaitTxPacket = NULL;
246 	NetArpWaitPacketIP = 0;
247 	NetArpWaitReplyIP = 0;
248 	NetArpWaitTxPacket = NULL;
249 	NetTxPacket = NULL;
250 
251 	if (!NetTxPacket) {
252 		int	i;
253 
254 		/*
255 		 *	Setup packet buffers, aligned correctly.
256 		 */
257 		NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
258 		NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
259 		for (i = 0; i < PKTBUFSRX; i++) {
260 			NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
261 		}
262 
263 	}
264 
265 	if (!NetArpWaitTxPacket) {
266 		NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
267 		NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
268 		NetArpWaitTxPacketSize = 0;
269 	}
270 
271 	eth_halt();
272 	if(eth_init(bd) < 0)
273 	    return(-1);
274 
275 restart:
276 #ifdef CONFIG_NET_MULTI
277 	memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
278 #else
279 	memcpy (NetOurEther, bd->bi_enetaddr, 6);
280 #endif
281 
282 	NetState = NETLOOP_CONTINUE;
283 
284 	/*
285 	 *	Start the ball rolling with the given start function.  From
286 	 *	here on, this code is a state machine driven by received
287 	 *	packets and timer events.
288 	 */
289 
290 	switch (protocol) {
291 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
292 	case NFS:
293 #endif
294 #if (CONFIG_COMMANDS & CFG_CMD_PING)
295 	case PING:
296 #endif
297 	case TFTP:
298 		NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
299 		NetOurGatewayIP = getenv_IPaddr ("gatewayip");
300 		NetOurSubnetMask= getenv_IPaddr ("netmask");
301 
302 		switch (protocol) {
303 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
304 		case NFS:
305 #endif
306 		case TFTP:
307 			NetServerIP = getenv_IPaddr ("serverip");
308 			break;
309 #if (CONFIG_COMMANDS & CFG_CMD_PING)
310 		case PING:
311 			/* nothing */
312 			break;
313 #endif
314 		default:
315 			break;
316 		}
317 
318 		break;
319 	case BOOTP:
320 	case RARP:
321 		/*
322 		 * initialize our IP addr to 0 in order to accept ANY
323 		 * IP addr assigned to us by the BOOTP / RARP server
324 		 */
325 		NetOurIP = 0;
326 		NetServerIP = 0;
327 		break;
328 	default:
329 		break;
330 	}
331 
332 	switch (net_check_prereq (protocol)) {
333 	case 1:
334 		/* network not configured */
335 		return (-1);
336 
337 #ifdef CONFIG_NET_MULTI
338 	case 2:
339 		/* network device not configured */
340 		break;
341 #endif /* CONFIG_NET_MULTI */
342 
343 	case 0:
344 #ifdef CONFIG_NET_MULTI
345 		NetDevExists = 1;
346 #endif
347 		switch (protocol) {
348 		case TFTP:
349 			/* always use ARP to get server ethernet address */
350 			TftpStart();
351 			break;
352 
353 #if (CONFIG_COMMANDS & CFG_CMD_DHCP)
354 		case DHCP:
355 			/* Start with a clean slate... */
356 			NetOurIP = 0;
357 			NetServerIP = 0;
358 			DhcpRequest();		/* Basically same as BOOTP */
359 			break;
360 #endif /* CFG_CMD_DHCP */
361 
362 		case BOOTP:
363 			BootpTry = 0;
364 			BootpRequest ();
365 			break;
366 
367 		case RARP:
368 			RarpTry = 0;
369 			RarpRequest ();
370 			break;
371 #if (CONFIG_COMMANDS & CFG_CMD_PING)
372 		case PING:
373 			PingStart();
374 			break;
375 #endif
376 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
377 		case NFS:
378 			NfsStart();
379 			break;
380 #endif
381 		default:
382 			break;
383 		}
384 
385 		NetBootFileXferSize = 0;
386 		break;
387 	}
388 
389 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
390 #if defined(CFG_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED)
391 	/*
392 	 * Echo the inverted link state to the fault LED.
393 	 */
394 	if(miiphy_link(CFG_FAULT_MII_ADDR)) {
395 		status_led_set (STATUS_LED_RED, STATUS_LED_OFF);
396 	} else {
397 		status_led_set (STATUS_LED_RED, STATUS_LED_ON);
398 	}
399 #endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */
400 #endif /* CONFIG_MII, ... */
401 
402 	/*
403 	 *	Main packet reception loop.  Loop receiving packets until
404 	 *	someone sets `NetQuit'.
405 	 */
406 	for (;;) {
407 		WATCHDOG_RESET();
408 #ifdef CONFIG_SHOW_ACTIVITY
409 		{
410 			extern void show_activity(int arg);
411 			show_activity(1);
412 		}
413 #endif
414 		/*
415 		 *	Check the ethernet for a new packet.  The ethernet
416 		 *	receive routine will process it.
417 		 */
418 			eth_rx();
419 
420 		/*
421 		 *	Abort if ctrl-c was pressed.
422 		 */
423 		if (ctrlc()) {
424 			eth_halt();
425 			printf("\nAbort\n");
426 			return (-1);
427 		}
428 
429 		ArpTimeoutCheck();
430 
431 		/*
432 		 *	Check for a timeout, and run the timeout handler
433 		 *	if we have one.
434 		 */
435 		if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
436 			thand_f *x;
437 
438 #if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
439 #if defined(CFG_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED)
440 			/*
441 			 * Echo the inverted link state to the fault LED.
442 			 */
443 			if(miiphy_link(CFG_FAULT_MII_ADDR)) {
444 				status_led_set (STATUS_LED_RED, STATUS_LED_OFF);
445 			} else {
446 				status_led_set (STATUS_LED_RED, STATUS_LED_ON);
447 			}
448 #endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */
449 #endif /* CONFIG_MII, ... */
450 			x = timeHandler;
451 			timeHandler = (thand_f *)0;
452 			(*x)();
453 		}
454 
455 
456 		switch (NetState) {
457 
458 		case NETLOOP_RESTART:
459 #ifdef CONFIG_NET_MULTI
460 			NetRestarted = 1;
461 #endif
462 			goto restart;
463 
464 		case NETLOOP_SUCCESS:
465 			if (NetBootFileXferSize > 0) {
466 				char buf[10];
467 				printf("Bytes transferred = %ld (%lx hex)\n",
468 					NetBootFileXferSize,
469 					NetBootFileXferSize);
470 				sprintf(buf, "%lx", NetBootFileXferSize);
471 				setenv("filesize", buf);
472 			}
473 			eth_halt();
474 			return NetBootFileXferSize;
475 
476 		case NETLOOP_FAIL:
477 			return (-1);
478 		}
479 	}
480 }
481 
482 /**********************************************************************/
483 
484 static void
485 startAgainTimeout(void)
486 {
487 	NetState = NETLOOP_RESTART;
488 }
489 
490 static void
491 startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
492 {
493 	/* Totally ignore the packet */
494 }
495 
496 void
497 NetStartAgain(void)
498 {
499 #ifndef CONFIG_NET_MULTI
500 	NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
501 	NetSetHandler(startAgainHandler);
502 #else
503 	DECLARE_GLOBAL_DATA_PTR;
504 
505 	eth_halt();
506 	eth_try_another(!NetRestarted);
507 	eth_init(gd->bd);
508 	if (NetRestartWrap)
509 	{
510 		NetRestartWrap = 0;
511 		if (NetDevExists)
512 		{
513 			NetSetTimeout(10 * CFG_HZ, startAgainTimeout);
514 			NetSetHandler(startAgainHandler);
515 		}
516 		else
517 		{
518 			NetState = NETLOOP_FAIL;
519 		}
520 	}
521 	else
522 	{
523 		NetState = NETLOOP_RESTART;
524 	}
525 #endif
526 }
527 
528 /**********************************************************************/
529 /*
530  *	Miscelaneous bits.
531  */
532 
533 void
534 NetSetHandler(rxhand_f * f)
535 {
536 	packetHandler = f;
537 }
538 
539 
540 void
541 NetSetTimeout(int iv, thand_f * f)
542 {
543 	if (iv == 0) {
544 		timeHandler = (thand_f *)0;
545 	} else {
546 		timeHandler = f;
547 		timeStart = get_timer(0);
548 		timeDelta = iv;
549 	}
550 }
551 
552 
553 void
554 NetSendPacket(volatile uchar * pkt, int len)
555 {
556 	(void) eth_send(pkt, len);
557 }
558 
559 int
560 NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len)
561 {
562 	/* convert to new style broadcast */
563 	if (dest == 0)
564 		dest = 0xFFFFFFFF;
565 
566 	/* if broadcast, make the ether address a broadcast and don't do ARP */
567 	if (dest == 0xFFFFFFFF)
568 		ether = NetBcastAddr;
569 
570 	/* if MAC address was not discovered yet, save the packet and do an ARP request */
571 	if (memcmp(ether, NetEtherNullAddr, 6) == 0) {
572 
573 #ifdef ET_DEBUG
574 		printf("sending ARP for %08lx\n", dest);
575 #endif
576 
577 		NetArpWaitPacketIP = dest;
578 		NetArpWaitPacketMAC = ether;
579 		NetSetEther (NetArpWaitTxPacket, NetArpWaitPacketMAC, PROT_IP);
580 		NetSetIP (NetArpWaitTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len);
581 		memcpy(NetArpWaitTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE,
582 			(uchar *)NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE, len);
583 
584 		/* size of the waiting packet */
585 		NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE + len;
586 
587 		/* and do the ARP request */
588 		NetArpWaitTry = 1;
589 		NetArpWaitTimerStart = get_timer(0);
590 		ArpRequest();
591 		return 1;	/* waiting */
592 	}
593 
594 #ifdef ET_DEBUG
595 	printf("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n",
596 			dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
597 #endif
598 
599 	NetSetEther (NetTxPacket, ether, PROT_IP);
600 	NetSetIP (NetTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len);
601 	(void) eth_send(NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len);
602 
603 	return 0;	/* transmited */
604 }
605 
606 #if (CONFIG_COMMANDS & CFG_CMD_PING)
607 static ushort PingSeqNo;
608 
609 int PingSend(void)
610 {
611 	static uchar mac[6];
612 	volatile IP_t *ip;
613 	volatile ushort *s;
614 
615 	/* XXX always send arp request */
616 
617 	memcpy(mac, NetEtherNullAddr, 6);
618 
619 #ifdef ET_DEBUG
620 	printf("sending ARP for %08lx\n", NetPingIP);
621 #endif
622 
623 	NetArpWaitPacketIP = NetPingIP;
624 	NetArpWaitPacketMAC = mac;
625 
626 	NetSetEther(NetArpWaitTxPacket, mac, PROT_IP);
627 
628 	ip = (volatile IP_t *)(NetArpWaitTxPacket + ETHER_HDR_SIZE);
629 
630 	/*
631 	 *	Construct an IP and ICMP header.  (need to set no fragment bit - XXX)
632 	 */
633 	ip->ip_hl_v  = 0x45;		/* IP_HDR_SIZE / 4 (not including UDP) */
634 	ip->ip_tos   = 0;
635 	ip->ip_len   = htons(IP_HDR_SIZE_NO_UDP + 8);
636 	ip->ip_id    = htons(NetIPID++);
637 	ip->ip_off   = htons(0x4000);	/* No fragmentation */
638 	ip->ip_ttl   = 255;
639 	ip->ip_p     = 0x01;		/* ICMP */
640 	ip->ip_sum   = 0;
641 	NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
642 	NetCopyIP((void*)&ip->ip_dst, &NetPingIP);	   /* - "" - */
643 	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
644 
645 	s = &ip->udp_src;		/* XXX ICMP starts here */
646 	s[0] = htons(0x0800);		/* echo-request, code */
647 	s[1] = 0;			/* checksum */
648 	s[2] = 0; 			/* identifier */
649 	s[3] = htons(PingSeqNo++);	/* sequence number */
650 	s[1] = ~NetCksum((uchar *)s, 8/2);
651 
652 	/* size of the waiting packet */
653 	NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE_NO_UDP + 8;
654 
655 	/* and do the ARP request */
656 	NetArpWaitTry = 1;
657 	NetArpWaitTimerStart = get_timer(0);
658 	ArpRequest();
659 	return 1;	/* waiting */
660 }
661 
662 static void
663 PingTimeout (void)
664 {
665 	eth_halt();
666 	NetState = NETLOOP_FAIL;	/* we did not get the reply */
667 }
668 
669 static void
670 PingHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
671 {
672 	IPaddr_t tmp;
673 	volatile IP_t *ip = (volatile IP_t *)pkt;
674 
675 	tmp = NetReadIP((void *)&ip->ip_src);
676 	if (tmp != NetPingIP)
677 		return;
678 
679 	NetState = NETLOOP_SUCCESS;
680 }
681 
682 static void PingStart(void)
683 {
684 	NetSetTimeout (10 * CFG_HZ, PingTimeout);
685 	NetSetHandler (PingHandler);
686 
687 	PingSend();
688 }
689 
690 #endif
691 
692 void
693 NetReceive(volatile uchar * pkt, int len)
694 {
695 	Ethernet_t *et;
696 	IP_t	*ip;
697 	ARP_t	*arp;
698 	IPaddr_t tmp;
699 	int	x;
700 
701 	NetRxPkt = pkt;
702 	NetRxPktLen = len;
703 	et = (Ethernet_t *)pkt;
704 
705 	x = ntohs(et->et_protlen);
706 
707 	if (x < 1514) {
708 		/*
709 		 *	Got a 802 packet.  Check the other protocol field.
710 		 */
711 		x = ntohs(et->et_prot);
712 		ip = (IP_t *)(pkt + E802_HDR_SIZE);
713 		len -= E802_HDR_SIZE;
714 	} else {
715 		ip = (IP_t *)(pkt + ETHER_HDR_SIZE);
716 		len -= ETHER_HDR_SIZE;
717 	}
718 
719 #ifdef ET_DEBUG
720 	printf("Receive from protocol 0x%x\n", x);
721 #endif
722 
723 	switch (x) {
724 
725 	case PROT_ARP:
726 		/*
727 		 * We have to deal with two types of ARP packets:
728 		 * - REQUEST packets will be answered by sending  our
729 		 *   IP address - if we know it.
730 		 * - REPLY packates are expected only after we asked
731 		 *   for the TFTP server's or the gateway's ethernet
732 		 *   address; so if we receive such a packet, we set
733 		 *   the server ethernet address
734 		 */
735 #ifdef ET_DEBUG
736 		printf("Got ARP\n");
737 #endif
738 		arp = (ARP_t *)ip;
739 		if (len < ARP_HDR_SIZE) {
740 			printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
741 			return;
742 		}
743 		if (ntohs(arp->ar_hrd) != ARP_ETHER) {
744 			return;
745 		}
746 		if (ntohs(arp->ar_pro) != PROT_IP) {
747 			return;
748 		}
749 		if (arp->ar_hln != 6) {
750 			return;
751 		}
752 		if (arp->ar_pln != 4) {
753 			return;
754 		}
755 
756 		if (NetOurIP == 0) {
757 			return;
758 		}
759 
760 		if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
761 			return;
762 		}
763 
764 		switch (ntohs(arp->ar_op)) {
765 		case ARPOP_REQUEST:		/* reply with our IP address	*/
766 #ifdef ET_DEBUG
767 			printf("Got ARP REQUEST, return our IP\n");
768 #endif
769 			NetSetEther((uchar *)et, et->et_src, PROT_ARP);
770 			arp->ar_op = htons(ARPOP_REPLY);
771 			memcpy   (&arp->ar_data[10], &arp->ar_data[0], 6);
772 			NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
773 			memcpy   (&arp->ar_data[ 0], NetOurEther, 6);
774 			NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
775 			(void) eth_send((uchar *)et, ((uchar *)arp-pkt) + ARP_HDR_SIZE);
776 			return;
777 
778 		case ARPOP_REPLY:		/* arp reply */
779 			/* are we waiting for a reply */
780 			if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
781 				break;
782 #ifdef ET_DEBUG
783 			printf("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n",
784 				arp->ar_data[0], arp->ar_data[1],
785 				arp->ar_data[2], arp->ar_data[3],
786 				arp->ar_data[4], arp->ar_data[5]);
787 #endif
788 
789 			tmp = NetReadIP(&arp->ar_data[6]);
790 
791 			/* matched waiting packet's address */
792 			if (tmp == NetArpWaitReplyIP) {
793 #ifdef ET_DEBUG
794 				printf("Got it\n");
795 #endif
796 				/* save address for later use */
797 				memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
798 
799 				/* modify header, and transmit it */
800 				memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
801 				(void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
802 
803 				/* no arp request pending now */
804 				NetArpWaitPacketIP = 0;
805 				NetArpWaitTxPacketSize = 0;
806 				NetArpWaitPacketMAC = NULL;
807 
808 			}
809 			return;
810 		default:
811 #ifdef ET_DEBUG
812 			printf("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op));
813 #endif
814 			return;
815 		}
816 
817 	case PROT_RARP:
818 #ifdef ET_DEBUG
819 		printf("Got RARP\n");
820 #endif
821 		arp = (ARP_t *)ip;
822 		if (len < ARP_HDR_SIZE) {
823 			printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
824 			return;
825 		}
826 
827 		if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
828 			(ntohs(arp->ar_hrd) != ARP_ETHER)   ||
829 			(ntohs(arp->ar_pro) != PROT_IP)     ||
830 			(arp->ar_hln != 6) || (arp->ar_pln != 4)) {
831 
832 			printf("invalid RARP header\n");
833 		} else {
834 			NetCopyIP(&NetOurIP,    &arp->ar_data[16]);
835 			NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
836 			memcpy (NetServerEther, &arp->ar_data[ 0], 6);
837 
838 			(*packetHandler)(0,0,0,0);
839 		}
840 		break;
841 
842 	case PROT_IP:
843 #ifdef ET_DEBUG
844 		printf("Got IP\n");
845 #endif
846 		if (len < IP_HDR_SIZE) {
847 			debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
848 			return;
849 		}
850 		if (len < ntohs(ip->ip_len)) {
851 			printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
852 			return;
853 		}
854 		len = ntohs(ip->ip_len);
855 #ifdef ET_DEBUG
856 		printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
857 #endif
858 		if ((ip->ip_hl_v & 0xf0) != 0x40) {
859 			return;
860 		}
861 		if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */
862 			return;
863 		}
864 		if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
865 			printf("checksum bad\n");
866 			return;
867 		}
868 		tmp = NetReadIP(&ip->ip_dst);
869 		if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) {
870 			return;
871 		}
872 		/*
873 		 * watch for ICMP host redirects
874 		 *
875 		 * There is no real handler code (yet). We just watch
876 		 * for ICMP host redirect messages. In case anybody
877 		 * sees these messages: please contact me
878 		 * (wd@denx.de), or - even better - send me the
879 		 * necessary fixes :-)
880 		 *
881 		 * Note: in all cases where I have seen this so far
882 		 * it was a problem with the router configuration,
883 		 * for instance when a router was configured in the
884 		 * BOOTP reply, but the TFTP server was on the same
885 		 * subnet. So this is probably a warning that your
886 		 * configuration might be wrong. But I'm not really
887 		 * sure if there aren't any other situations.
888 		 */
889 		if (ip->ip_p == IPPROTO_ICMP) {
890 			ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
891 
892 			switch (icmph->type) {
893 			case ICMP_REDIRECT:
894 			if (icmph->code != ICMP_REDIR_HOST)
895 				return;
896 			puts (" ICMP Host Redirect to ");
897 			print_IPaddr(icmph->un.gateway);
898 			putc(' ');
899 				break;
900 #if (CONFIG_COMMANDS & CFG_CMD_PING)
901 			case ICMP_ECHO_REPLY:
902 				/*
903 				 *	IP header OK.  Pass the packet to the current handler.
904 				 */
905 				/* XXX point to ip packet */
906 				(*packetHandler)((uchar *)ip, 0, 0, 0);
907 				break;
908 #endif
909 			default:
910 				return;
911 			}
912 		} else if (ip->ip_p != IPPROTO_UDP) {	/* Only UDP packets */
913 			return;
914 		}
915 
916 		/*
917 		 *	IP header OK.  Pass the packet to the current handler.
918 		 */
919 		(*packetHandler)((uchar *)ip +IP_HDR_SIZE,
920 						ntohs(ip->udp_dst),
921 						ntohs(ip->udp_src),
922 						ntohs(ip->udp_len) - 8);
923 
924 		break;
925 	}
926 }
927 
928 
929 /**********************************************************************/
930 
931 static int net_check_prereq (proto_t protocol)
932 {
933 	switch (protocol) {
934 			/* Fall through */
935 #if (CONFIG_COMMANDS & CFG_CMD_PING)
936 	case PING:
937 			if (NetPingIP == 0) {
938 				puts ("*** ERROR: ping address not given\n");
939 				return (1);
940 			}
941 			goto common;
942 #endif
943 #if (CONFIG_COMMANDS & CFG_CMD_NFS)
944 	case NFS:
945 #endif
946 	case TFTP:
947 			if (NetServerIP == 0) {
948 				puts ("*** ERROR: `serverip' not set\n");
949 				return (1);
950 			}
951 
952 #if (CONFIG_COMMANDS & CFG_CMD_PING)
953 		common:
954 #endif
955 
956 			if (NetOurIP == 0) {
957 				puts ("*** ERROR: `ipaddr' not set\n");
958 				return (1);
959 			}
960 			/* Fall through */
961 
962 	case DHCP:
963 	case RARP:
964 	case BOOTP:
965 			if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
966 #ifdef CONFIG_NET_MULTI
967 			    extern int eth_get_dev_index (void);
968 			    int num = eth_get_dev_index();
969 
970 			    switch (num) {
971 			    case -1:
972 				puts ("*** ERROR: No ethernet found.\n");
973 				return (1);
974 			    case 0:
975 				puts ("*** ERROR: `ethaddr' not set\n");
976 				break;
977 			    default:
978 				printf ("*** ERROR: `eth%daddr' not set\n",
979 					num);
980 				break;
981 			    }
982 
983 			    NetStartAgain ();
984 			    return (2);
985 #else
986 			    puts ("*** ERROR: `ethaddr' not set\n");
987 			    return (1);
988 #endif
989 			}
990 			/* Fall through */
991 		default:
992 			return(0);
993 	}
994 	return (0);	/* OK */
995 }
996 /**********************************************************************/
997 
998 int
999 NetCksumOk(uchar * ptr, int len)
1000 {
1001 	return !((NetCksum(ptr, len) + 1) & 0xfffe);
1002 }
1003 
1004 
1005 unsigned
1006 NetCksum(uchar * ptr, int len)
1007 {
1008 	ulong	xsum;
1009 
1010 	xsum = 0;
1011 	while (len-- > 0)
1012 		xsum += *((ushort *)ptr)++;
1013 	xsum = (xsum & 0xffff) + (xsum >> 16);
1014 	xsum = (xsum & 0xffff) + (xsum >> 16);
1015 	return (xsum & 0xffff);
1016 }
1017 
1018 
1019 void
1020 NetSetEther(volatile uchar * xet, uchar * addr, uint prot)
1021 {
1022 	Ethernet_t *et = (Ethernet_t *)xet;
1023 
1024 	memcpy (et->et_dest, addr, 6);
1025 	memcpy (et->et_src, NetOurEther, 6);
1026 	et->et_protlen = htons(prot);
1027 }
1028 
1029 
1030 void
1031 NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len)
1032 {
1033 	volatile IP_t *ip = (IP_t *)xip;
1034 
1035 	/*
1036 	 *	If the data is an odd number of bytes, zero the
1037 	 *	byte after the last byte so that the checksum
1038 	 *	will work.
1039 	 */
1040 	if (len & 1)
1041 		xip[IP_HDR_SIZE + len] = 0;
1042 
1043 	/*
1044 	 *	Construct an IP and UDP header.
1045 			(need to set no fragment bit - XXX)
1046 	 */
1047 	ip->ip_hl_v  = 0x45;		/* IP_HDR_SIZE / 4 (not including UDP) */
1048 	ip->ip_tos   = 0;
1049 	ip->ip_len   = htons(IP_HDR_SIZE + len);
1050 	ip->ip_id    = htons(NetIPID++);
1051 	ip->ip_off   = htons(0x4000);	/* No fragmentation */
1052 	ip->ip_ttl   = 255;
1053 	ip->ip_p     = 17;		/* UDP */
1054 	ip->ip_sum   = 0;
1055 	NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
1056 	NetCopyIP((void*)&ip->ip_dst, &dest);	   /* - "" - */
1057 	ip->udp_src  = htons(sport);
1058 	ip->udp_dst  = htons(dport);
1059 	ip->udp_len  = htons(8 + len);
1060 	ip->udp_xsum = 0;
1061 	ip->ip_sum   = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
1062 }
1063 
1064 void copy_filename (uchar *dst, uchar *src, int size)
1065 {
1066 	if (*src && (*src == '"')) {
1067 		++src;
1068 		--size;
1069 	}
1070 
1071 	while ((--size > 0) && *src && (*src != '"')) {
1072 		*dst++ = *src++;
1073 	}
1074 	*dst = '\0';
1075 }
1076 
1077 #endif /* CFG_CMD_NET */
1078 
1079 void ip_to_string (IPaddr_t x, char *s)
1080 {
1081     x = ntohl(x);
1082     sprintf (s,"%d.%d.%d.%d",
1083 	(int)((x >> 24) & 0xff),
1084 	(int)((x >> 16) & 0xff),
1085 	(int)((x >>  8) & 0xff),
1086 	(int)((x >>  0) & 0xff)
1087     );
1088 }
1089 
1090 IPaddr_t string_to_ip(char *s)
1091 {
1092 	IPaddr_t addr;
1093 	char *e;
1094 	int i;
1095 
1096 	if (s == NULL)
1097 		return(0);
1098 
1099 	for (addr=0, i=0; i<4; ++i) {
1100 		ulong val = s ? simple_strtoul(s, &e, 10) : 0;
1101 		addr <<= 8;
1102 		addr |= (val & 0xFF);
1103 		if (s) {
1104 			s = (*e) ? e+1 : e;
1105 		}
1106 	}
1107 
1108 	return (htonl(addr));
1109 }
1110 
1111 void print_IPaddr (IPaddr_t x)
1112 {
1113     char tmp[16];
1114 
1115     ip_to_string(x, tmp);
1116 
1117     puts(tmp);
1118 }
1119 
1120 IPaddr_t getenv_IPaddr (char *var)
1121 {
1122 	return (string_to_ip(getenv(var)));
1123 }
1124