diff -ruNb u-boot-0.3.0-orig/include/net.h u-boot-0.3.0/include/net.h --- u-boot-0.3.0-orig/include/net.h Mon Apr 21 10:10:04 2003 +++ u-boot-0.3.0/include/net.h Tue Apr 22 12:37:48 2003 @@ -326,6 +326,9 @@ /* Transmit "NetTxPacket" */ extern void NetSendPacket(volatile uchar *, int); +/* Transmit UDP packet, performing ARP request if needed */ +extern int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len); + /* Processes a received packet */ extern void NetReceive(volatile uchar *, int); diff -ruNb u-boot-0.3.0-orig/net/Makefile u-boot-0.3.0/net/Makefile --- u-boot-0.3.0-orig/net/Makefile Mon Apr 21 10:10:04 2003 +++ u-boot-0.3.0/net/Makefile Tue Apr 22 12:32:44 2003 @@ -27,7 +27,7 @@ LIB = libnet.a -OBJS = net.o tftp.o bootp.o rarp.o arp.o eth.o +OBJS = net.o tftp.o bootp.o rarp.o eth.o all: $(LIB) $(LIB): $(START) $(OBJS) diff -ruNb u-boot-0.3.0-orig/net/arp.c u-boot-0.3.0/net/arp.c --- u-boot-0.3.0-orig/net/arp.c Mon Apr 21 10:10:04 2003 +++ u-boot-0.3.0/net/arp.c Thu Jan 1 02:00:00 1970 @@ -1,120 +0,0 @@ -/* - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include -#include -#include -#include "bootp.h" -#include "tftp.h" -#include "arp.h" - -#if (CONFIG_COMMANDS & CFG_CMD_NET) - -#define TIMEOUT 5 /* Seconds before trying ARP again */ -#ifndef CONFIG_NET_RETRY_COUNT -# define TIMEOUT_COUNT 5 /* # of timeouts before giving up */ -#else -# define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT) -#endif - -static void ArpHandler(uchar *pkt, unsigned dest, unsigned src, unsigned len); -static void ArpTimeout(void); - -int ArpTry = 0; - -/* - * Handle a ARP received packet. - */ -static void -ArpHandler(uchar *pkt, unsigned dest, unsigned src, unsigned len) -{ - /* Check if the frame is really an ARP reply */ - if (memcmp (NetServerEther, NetBcastAddr, 6) != 0) { -#ifdef DEBUG - printf("Got good ARP - start TFTP\n"); -#endif - TftpStart (); - } -} - - -/* - * Timeout on ARP request. - */ -static void -ArpTimeout(void) -{ - if (ArpTry >= TIMEOUT_COUNT) { - puts ("\nRetry count exceeded; starting again\n"); - NetStartAgain (); - } else { - NetSetTimeout (TIMEOUT * CFG_HZ, ArpTimeout); - ArpRequest (); - } -} - - -void -ArpRequest (void) -{ - int i; - volatile uchar *pkt; - ARP_t * arp; - - printf("ARP broadcast %d\n", ++ArpTry); - pkt = NetTxPacket; - - NetSetEther(pkt, NetBcastAddr, PROT_ARP); - pkt += ETHER_HDR_SIZE; - - arp = (ARP_t *)pkt; - - arp->ar_hrd = htons(ARP_ETHER); - arp->ar_pro = htons(PROT_IP); - arp->ar_hln = 6; - arp->ar_pln = 4; - arp->ar_op = htons(ARPOP_REQUEST); - - memcpy (&arp->ar_data[0], NetOurEther, 6); /* source ET addr */ - NetWriteIP((uchar*)&arp->ar_data[6], NetOurIP); /* source IP addr */ - for (i=10; i<16; ++i) { - arp->ar_data[i] = 0; /* dest ET addr = 0 */ - } - - if((NetServerIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask)) { - if (NetOurGatewayIP == 0) { - puts ("## Warning: gatewayip needed but not set\n"); - } - NetWriteIP((uchar*)&arp->ar_data[16], NetOurGatewayIP); - } else { - NetWriteIP((uchar*)&arp->ar_data[16], NetServerIP); - } - - - NetSendPacket(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE); - - NetSetTimeout(TIMEOUT * CFG_HZ, ArpTimeout); - NetSetHandler(ArpHandler); -} - -#endif /* CFG_CMD_NET */ diff -ruNb u-boot-0.3.0-orig/net/arp.h u-boot-0.3.0/net/arp.h --- u-boot-0.3.0-orig/net/arp.h Mon Apr 21 10:10:04 2003 +++ u-boot-0.3.0/net/arp.h Thu Jan 1 02:00:00 1970 @@ -1,40 +0,0 @@ -/* - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - - -#ifndef __ARP_H__ -#define __ARP_H__ - -/**********************************************************************/ -/* - * Global functions and variables. - */ - -extern int ArpTry; - -extern void ArpRequest (void); /* Send a ARP request */ - -/**********************************************************************/ - -#endif /* __ARP_H__ */ - diff -ruNb u-boot-0.3.0-orig/net/bootp.c u-boot-0.3.0/net/bootp.c --- u-boot-0.3.0-orig/net/bootp.c Mon Apr 21 10:10:04 2003 +++ u-boot-0.3.0/net/bootp.c Tue Apr 22 12:32:45 2003 @@ -24,7 +24,6 @@ #include #include "bootp.h" #include "tftp.h" -#include "arp.h" #ifdef CONFIG_STATUS_LED #include #endif @@ -335,10 +334,7 @@ return; } - /* Send ARP request to get TFTP server ethernet address. - * This automagically starts TFTP, too. - */ - ArpRequest(); + TftpStart(); } #endif /* !CFG_CMD_DHCP */ @@ -866,10 +862,7 @@ NetState = NETLOOP_SUCCESS; return; } - /* Send ARP request to get TFTP server ethernet address. - * This automagically starts TFTP, too. - */ - ArpRequest(); + TftpStart(); return; } break; diff -ruNb u-boot-0.3.0-orig/net/net.c u-boot-0.3.0/net/net.c --- u-boot-0.3.0-orig/net/net.c Mon Apr 21 10:10:04 2003 +++ u-boot-0.3.0/net/net.c Tue Apr 22 12:32:45 2003 @@ -65,10 +65,16 @@ #include "bootp.h" #include "tftp.h" #include "rarp.h" -#include "arp.h" #if (CONFIG_COMMANDS & CFG_CMD_NET) +#define ARP_TIMEOUT 5 /* Seconds before trying ARP again */ +#ifndef CONFIG_NET_RETRY_COUNT +# define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */ +#else +# define ARP_TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT) +#endif + #if 0 #define ET_DEBUG #endif @@ -88,7 +94,7 @@ ulong NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */ uchar NetOurEther[6]; /* Our ethernet address */ uchar NetServerEther[6] = /* Boot server enet address */ - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + { 0, 0, 0, 0, 0, 0 }; IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */ IPaddr_t NetServerIP; /* Our IP addr (0 = unknown) */ volatile uchar *NetRxPkt; /* Current receive packet */ @@ -96,6 +102,8 @@ unsigned NetIPID; /* IP packet ID */ uchar NetBcastAddr[6] = /* Ethernet bcast address */ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +uchar NetEtherNullAddr[6] = + { 0, 0, 0, 0, 0, 0 }; int NetState; /* Network loop state */ #ifdef CONFIG_NET_MULTI int NetRestartWrap = 0; /* Tried all network devices */ @@ -117,6 +125,78 @@ static int net_check_prereq (proto_t protocol); /**********************************************************************/ + +IPaddr_t NetArpWaitPacketIP; +uchar *NetArpWaitPacketMAC; /* MAC address of waiting packet's destination */ +uchar *NetArpWaitTxPacket = 0; /* THE transmit packet */ +int NetArpWaitTxPacketSize; +uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN]; +ulong NetArpWaitTimerStart; +int NetArpWaitTry; + +void ArpRequest(void) +{ + int i; + volatile uchar *pkt; + ARP_t * arp; + + printf("ARP broadcast %d\n", NetArpWaitTry); + pkt = NetTxPacket; + + NetSetEther(pkt, NetBcastAddr, PROT_ARP); + pkt += ETHER_HDR_SIZE; + + arp = (ARP_t *)pkt; + + arp->ar_hrd = htons(ARP_ETHER); + arp->ar_pro = htons(PROT_IP); + arp->ar_hln = 6; + arp->ar_pln = 4; + arp->ar_op = htons(ARPOP_REQUEST); + + memcpy (&arp->ar_data[0], NetOurEther, 6); /* source ET addr */ + NetWriteIP((uchar*)&arp->ar_data[6], NetOurIP); /* source IP addr */ + for (i=10; i<16; ++i) { + arp->ar_data[i] = 0; /* dest ET addr = 0 */ + } + + if((NetArpWaitPacketIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask)) { + if (NetOurGatewayIP == 0) { + puts ("## Warning: gatewayip needed but not set\n"); + } + NetWriteIP((uchar*)&arp->ar_data[16], NetOurGatewayIP); + } else { + NetWriteIP((uchar*)&arp->ar_data[16], NetArpWaitPacketIP); + } + + (void) eth_send(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE); +} + +void ArpTimeoutCheck(void) +{ + ulong t; + + if (!NetArpWaitPacketIP) + return; + + t = get_timer(0); + + /* check for arp timeout */ + if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ) { + NetArpWaitTry++; + + if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) { + puts ("\nARP Retry count exceeded; starting again\n"); + NetArpWaitTry = 0; + NetStartAgain(); + } else { + NetArpWaitTimerStart = t; + ArpRequest(); + } + } +} + +/**********************************************************************/ /* * Main network processing loop. */ @@ -144,6 +224,13 @@ for (i = 0; i < PKTBUFSRX; i++) { NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN; } + + } + + if (!NetArpWaitTxPacket) { + NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1); + NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN; + NetArpWaitTxPacketSize = 0; } eth_halt(); @@ -202,8 +289,7 @@ switch (protocol) { case TFTP: /* always use ARP to get server ethernet address */ - ArpTry = 0; - ArpRequest (); + TftpStart(); break; #if (CONFIG_COMMANDS & CFG_CMD_DHCP) @@ -260,6 +346,7 @@ return (-1); } + ArpTimeoutCheck(); /* * Check for a timeout, and run the timeout handler @@ -376,7 +463,44 @@ (void) eth_send(pkt, len); } +int +NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len) +{ + /* if MAC address was not discovered yet, save the packet and do an ARP request */ + if (memcmp(ether, NetEtherNullAddr, 6) == 0) { + +#ifdef ET_DEBUG + printf("sending ARP for %08lx\n", dest); +#endif + + NetArpWaitPacketIP = dest; + NetArpWaitPacketMAC = ether; + NetSetEther (NetArpWaitTxPacket, NetArpWaitPacketMAC, PROT_IP); + NetSetIP (NetArpWaitTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len); + memcpy(NetArpWaitTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE, + (uchar *)NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE, len); + + /* size of the waiting packet */ + NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE + len; + + /* and do the ARP request */ + NetArpWaitTry = 1; + NetArpWaitTimerStart = get_timer(0); + ArpRequest(); + return 1; /* waiting */ + } + +#ifdef ET_DEBUG + printf("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n", + dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]); +#endif + NetSetEther (NetTxPacket, ether, PROT_IP); + NetSetIP (NetTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len); + (void) eth_send(NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len); + + return 0; /* transmited */ +} void NetReceive(volatile uchar * pkt, int len) @@ -462,14 +586,40 @@ NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]); memcpy (&arp->ar_data[ 0], NetOurEther, 6); NetCopyIP(&arp->ar_data[ 6], &NetOurIP); - NetSendPacket((uchar *)et,((uchar *)arp-pkt)+ARP_HDR_SIZE); + (void) eth_send((uchar *)et, ((uchar *)arp-pkt) + ARP_HDR_SIZE); return; - case ARPOP_REPLY: /* set TFTP server eth addr */ + + case ARPOP_REPLY: /* arp reply */ + /* are we waiting for a reply */ + if (!NetArpWaitPacketIP) + break; #ifdef ET_DEBUG - printf("Got ARP REPLY, set server/gtwy eth addr\n"); + printf("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n", + arp->ar_data[0], arp->ar_data[1], + arp->ar_data[2], arp->ar_data[3], + arp->ar_data[4], arp->ar_data[5]); #endif - memcpy (NetServerEther, &arp->ar_data[0], 6); - (*packetHandler)(0,0,0,0); /* start TFTP */ + + tmp = NetReadIP(&arp->ar_data[6]); + + /* matched waiting packet's address */ + if (tmp == NetArpWaitPacketIP) { +#ifdef ET_DEBUG + printf("Got it\n"); +#endif + /* save address for later use */ + memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6); + + /* modify header, and transmit it */ + memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6); + (void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize); + + /* no arp request pending now */ + NetArpWaitPacketIP = 0; + NetArpWaitTxPacketSize = 0; + NetArpWaitPacketMAC = NULL; + + } return; default: #ifdef ET_DEBUG diff -ruNb u-boot-0.3.0-orig/net/tftp.c u-boot-0.3.0/net/tftp.c --- u-boot-0.3.0-orig/net/tftp.c Mon Apr 21 10:10:04 2003 +++ u-boot-0.3.0/net/tftp.c Tue Apr 22 12:40:41 2003 @@ -142,10 +142,7 @@ break; } - NetSetEther (NetTxPacket, NetServerEther, PROT_IP); - NetSetIP (NetTxPacket + ETHER_HDR_SIZE, NetServerIP, - TftpServerPort, TftpOurPort, len); - NetSendPacket (NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len); + NetSendUDPPacket(NetServerEther, NetServerIP, TftpServerPort, TftpOurPort, len); } @@ -257,17 +254,6 @@ void TftpStart (void) { -#ifdef ET_DEBUG - printf ("\nServer ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n", - NetServerEther[0], - NetServerEther[1], - NetServerEther[2], - NetServerEther[3], - NetServerEther[4], - NetServerEther[5] - ); -#endif /* DEBUG */ - if (BootFile[0] == '\0') { IPaddr_t OurIP = ntohl(NetOurIP);