]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - net/net.c
drivers/i2c/davinci_i2c.c: Fix GCC 4.6 warning
[karo-tx-uboot.git] / net / net.c
index 1f3d70bd9052f59098a5daca0f52cf88e26322ed..d0fe1c4960a2fb024dc5cb704712fb0e61ab785e 100644 (file)
--- a/net/net.c
+++ b/net/net.c
@@ -169,14 +169,12 @@ uchar             NetCDPAddr[6] = { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc };
 #endif
 /* Network loop state */
 int            NetState;
-#ifdef CONFIG_NET_MULTI
 /* Tried all network devices */
 int            NetRestartWrap;
 /* Network loop restarted */
 static int     NetRestarted;
 /* At least one device configured */
 static int     NetDevExists;
-#endif
 
 /* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */
 /* default is without VLAN */
@@ -217,6 +215,9 @@ volatile uchar *NetRxPackets[PKTBUFSRX];
 
 /* Current RX packet handler */
 static rxhand_f *packetHandler;
+#ifdef CONFIG_CMD_TFTPPUT
+static rxhand_icmp_f *packet_icmp_handler;     /* Current ICMP rx handler */
+#endif
 /* Current timeout handler */
 static thand_f *timeHandler;
 /* Time base value */
@@ -226,7 +227,7 @@ static ulong        timeDelta;
 /* THE transmit packet */
 volatile uchar *NetTxPacket;
 
-static int net_check_prereq(proto_t protocol);
+static int net_check_prereq(enum proto_t protocol);
 
 static int NetTryCount;
 
@@ -245,7 +246,6 @@ int         NetArpWaitTry;
 
 void ArpRequest(void)
 {
-       int i;
        volatile uchar *pkt;
        ARP_t *arp;
 
@@ -267,11 +267,8 @@ void ArpRequest(void)
        memcpy(&arp->ar_data[0], NetOurEther, 6);
        /* source IP addr */
        NetWriteIP((uchar *) &arp->ar_data[6], NetOurIP);
-       for (i = 10; i < 16; ++i) {
-               /* dest ET addr = 0 */
-               arp->ar_data[i] = 0;
-       }
-
+       /* dest ET addr = 0 */
+       memset(&arp->ar_data[10], '\0', 6);
        if ((NetArpWaitPacketIP & NetOurSubnetMask) !=
            (NetOurIP & NetOurSubnetMask)) {
                if (NetOurGatewayIP == 0) {
@@ -312,8 +309,37 @@ void ArpTimeoutCheck(void)
        }
 }
 
-static void
-NetInitLoop(proto_t protocol)
+/*
+ * Check if autoload is enabled. If so, use either NFS or TFTP to download
+ * the boot file.
+ */
+void net_auto_load(void)
+{
+       const char *s = getenv("autoload");
+
+       if (s != NULL) {
+               if (*s == 'n') {
+                       /*
+                        * Just use BOOTP/RARP to configure system;
+                        * Do not use TFTP to load the bootfile.
+                        */
+                       NetState = NETLOOP_SUCCESS;
+                       return;
+               }
+#if defined(CONFIG_CMD_NFS)
+               if (strcmp(s, "NFS") == 0) {
+                       /*
+                        * Use NFS to load the bootfile.
+                        */
+                       NfsStart();
+                       return;
+               }
+#endif
+       }
+       TftpStart(TFTPGET);
+}
+
+static void NetInitLoop(enum proto_t protocol)
 {
        static int env_changed_id;
        bd_t *bd = gd->bd;
@@ -321,7 +347,8 @@ NetInitLoop(proto_t protocol)
 
        /* update only when the environment has changed */
        if (env_changed_id != env_id) {
-               NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
+               NetOurIP = getenv_IPaddr("ipaddr");
+               NetCopyIP(&bd->bi_ip_addr, &NetOurIP);
                NetOurGatewayIP = getenv_IPaddr("gatewayip");
                NetOurSubnetMask = getenv_IPaddr("netmask");
                NetServerIP = getenv_IPaddr("serverip");
@@ -341,15 +368,13 @@ NetInitLoop(proto_t protocol)
  *     Main network processing loop.
  */
 
-int
-NetLoop(proto_t protocol)
+int NetLoop(enum proto_t protocol)
 {
        bd_t *bd = gd->bd;
+       int ret = -1;
 
-#ifdef CONFIG_NET_MULTI
        NetRestarted = 0;
        NetDevExists = 0;
-#endif
 
        /* XXX problem with bss workaround */
        NetArpWaitPacketMAC = NULL;
@@ -378,20 +403,14 @@ NetLoop(proto_t protocol)
        }
 
        eth_halt();
-#ifdef CONFIG_NET_MULTI
        eth_set_current();
-#endif
        if (eth_init(bd) < 0) {
                eth_halt();
                return -1;
        }
 
 restart:
-#ifdef CONFIG_NET_MULTI
        memcpy(NetOurEther, eth_get_dev()->enetaddr, 6);
-#else
-       eth_getenv_enetaddr("ethaddr", NetOurEther);
-#endif
 
        NetState = NETLOOP_CONTINUE;
 
@@ -408,22 +427,26 @@ restart:
                eth_halt();
                return -1;
 
-#ifdef CONFIG_NET_MULTI
        case 2:
                /* network device not configured */
                break;
-#endif /* CONFIG_NET_MULTI */
 
        case 0:
-#ifdef CONFIG_NET_MULTI
                NetDevExists = 1;
-#endif
+               NetBootFileXferSize = 0;
                switch (protocol) {
-               case TFTP:
+               case TFTPGET:
+#ifdef CONFIG_CMD_TFTPPUT
+               case TFTPPUT:
+#endif
                        /* always use ARP to get server ethernet address */
-                       TftpStart();
+                       TftpStart(protocol);
                        break;
-
+#ifdef CONFIG_CMD_TFTPSRV
+               case TFTPSRV:
+                       TftpStartServer();
+                       break;
+#endif
 #if defined(CONFIG_CMD_DHCP)
                case DHCP:
                        BootpTry = 0;
@@ -479,7 +502,6 @@ restart:
                        break;
                }
 
-               NetBootFileXferSize = 0;
                break;
        }
 
@@ -521,7 +543,7 @@ restart:
                if (ctrlc()) {
                        eth_halt();
                        puts("\nAbort\n");
-                       return -1;
+                       goto done;
                }
 
                ArpTimeoutCheck();
@@ -557,9 +579,7 @@ restart:
                switch (NetState) {
 
                case NETLOOP_RESTART:
-#ifdef CONFIG_NET_MULTI
                        NetRestarted = 1;
-#endif
                        goto restart;
 
                case NETLOOP_SUCCESS:
@@ -575,12 +595,21 @@ restart:
                                setenv("fileaddr", buf);
                        }
                        eth_halt();
-                       return NetBootFileXferSize;
+                       ret = NetBootFileXferSize;
+                       goto done;
 
                case NETLOOP_FAIL:
-                       return -1;
+                       goto done;
                }
        }
+
+done:
+#ifdef CONFIG_CMD_TFTPPUT
+       /* Clear out the handlers */
+       NetSetHandler(NULL);
+       net_set_icmp_handler(NULL);
+#endif
+       return ret;
 }
 
 /**********************************************************************/
@@ -625,10 +654,6 @@ void NetStartAgain(void)
 
        NetTryCount++;
 
-#ifndef CONFIG_NET_MULTI
-       NetSetTimeout(10000UL, startAgainTimeout);
-       NetSetHandler(startAgainHandler);
-#else  /* !CONFIG_NET_MULTI*/
        eth_halt();
 #if !defined(CONFIG_NET_DO_NOT_TRY_ANOTHER)
        eth_try_another(!NetRestarted);
@@ -645,7 +670,6 @@ void NetStartAgain(void)
        } else {
                NetState = NETLOOP_RESTART;
        }
-#endif /* CONFIG_NET_MULTI */
 }
 
 /**********************************************************************/
@@ -659,6 +683,12 @@ NetSetHandler(rxhand_f *f)
        packetHandler = f;
 }
 
+#ifdef CONFIG_CMD_TFTPPUT
+void net_set_icmp_handler(rxhand_icmp_f *f)
+{
+       packet_icmp_handler = f;
+}
+#endif
 
 void
 NetSetTimeout(ulong iv, thand_f *f)
@@ -811,9 +841,7 @@ PingHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
 
 static void PingStart(void)
 {
-#if defined(CONFIG_NET_MULTI)
        printf("Using %s device\n", eth_get_name());
-#endif /* CONFIG_NET_MULTI */
        NetSetTimeout(10000UL, PingTimeout);
        NetSetHandler(PingHandler);
 
@@ -1052,7 +1080,6 @@ CDPHandler(const uchar *pkt, unsigned len)
        const uchar *t;
        const ushort *ss;
        ushort type, tlen;
-       uchar applid;
        ushort vlan, nvlan;
 
        /* minimum size? */
@@ -1124,11 +1151,10 @@ CDPHandler(const uchar *pkt, unsigned len)
                                if (tlen < 3)
                                        goto pkt_short;
 
-                               applid = t[0];
                                ss = (const ushort *)(t + 1);
 
 #ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE
-                               if (applid == CONFIG_CDP_APPLIANCE_VLAN_TYPE)
+                               if (t[0] == CONFIG_CDP_APPLIANCE_VLAN_TYPE)
                                        vlan = *ss;
 #else
                                /* XXX will this work; dunno */
@@ -1163,9 +1189,7 @@ CDPHandler(const uchar *pkt, unsigned len)
 
 static void CDPStart(void)
 {
-#if defined(CONFIG_NET_MULTI)
        printf("Using %s device\n", eth_get_name());
-#endif
        CDPSeq = 0;
        CDPOK = 0;
 
@@ -1351,6 +1375,68 @@ static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
 }
 #endif
 
+/**
+ * Receive an ICMP packet. We deal with REDIRECT and PING here, and silently
+ * drop others.
+ *
+ * @parma ip   IP packet containing the ICMP
+ */
+static void receive_icmp(IP_t *ip, int len, IPaddr_t src_ip, Ethernet_t *et)
+{
+       ICMP_t *icmph = (ICMP_t *)&ip->udp_src;
+
+       switch (icmph->type) {
+       case ICMP_REDIRECT:
+               if (icmph->code != ICMP_REDIR_HOST)
+                       return;
+               printf(" ICMP Host Redirect to %pI4 ",
+                       &icmph->un.gateway);
+               break;
+#if defined(CONFIG_CMD_PING)
+       case ICMP_ECHO_REPLY:
+               /*
+                       * IP header OK.  Pass the packet to the
+                       * current handler.
+                       */
+               /*
+                * XXX point to ip packet - should this use
+                * packet_icmp_handler?
+                */
+               (*packetHandler)((uchar *)ip, 0, src_ip, 0, 0);
+               break;
+       case ICMP_ECHO_REQUEST:
+               debug("Got ICMP ECHO REQUEST, return %d bytes\n",
+                       ETHER_HDR_SIZE + len);
+
+               memcpy(&et->et_dest[0], &et->et_src[0], 6);
+               memcpy(&et->et_src[0], NetOurEther, 6);
+
+               ip->ip_sum = 0;
+               ip->ip_off = 0;
+               NetCopyIP((void *)&ip->ip_dst, &ip->ip_src);
+               NetCopyIP((void *)&ip->ip_src, &NetOurIP);
+               ip->ip_sum = ~NetCksum((uchar *)ip,
+                                       IP_HDR_SIZE_NO_UDP >> 1);
+
+               icmph->type = ICMP_ECHO_REPLY;
+               icmph->checksum = 0;
+               icmph->checksum = ~NetCksum((uchar *)icmph,
+                       (len - IP_HDR_SIZE_NO_UDP) >> 1);
+               (void) eth_send((uchar *)et,
+                               ETHER_HDR_SIZE + len);
+               break;
+#endif
+       default:
+#ifdef CONFIG_CMD_TFTPPUT
+               if (packet_icmp_handler)
+                       packet_icmp_handler(icmph->type, icmph->code,
+                               ntohs(ip->udp_dst), src_ip, ntohs(ip->udp_src),
+                               icmph->un.data, ntohs(ip->udp_len));
+#endif
+               break;
+       }
+}
+
 void
 NetReceive(volatile uchar *inpkt, int len)
 {
@@ -1616,7 +1702,8 @@ NetReceive(volatile uchar *inpkt, int len)
                 * a fragment, and either the complete packet or NULL if
                 * it is a fragment (if !CONFIG_IP_DEFRAG, it returns NULL)
                 */
-               if (!(ip = NetDefragment(ip, &len)))
+               ip = NetDefragment(ip, &len);
+               if (!ip)
                        return;
                /*
                 * watch for ICMP host redirects
@@ -1634,51 +1721,14 @@ NetReceive(volatile uchar *inpkt, int len)
                 * subnet. So this is probably a warning that your
                 * configuration might be wrong. But I'm not really
                 * sure if there aren't any other situations.
+                *
+                * Simon Glass <sjg@chromium.org>: We get an ICMP when
+                * we send a tftp packet to a dead connection, or when
+                * there is no server at the other end.
                 */
                if (ip->ip_p == IPPROTO_ICMP) {
-                       ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
-
-                       switch (icmph->type) {
-                       case ICMP_REDIRECT:
-                               if (icmph->code != ICMP_REDIR_HOST)
-                                       return;
-                               printf(" ICMP Host Redirect to %pI4 ",
-                                       &icmph->un.gateway);
-                               return;
-#if defined(CONFIG_CMD_PING)
-                       case ICMP_ECHO_REPLY:
-                               /*
-                                * IP header OK.  Pass the packet to the
-                                * current handler.
-                                */
-                               /* XXX point to ip packet */
-                               (*packetHandler)((uchar *)ip, 0, src_ip, 0, 0);
-                               return;
-                       case ICMP_ECHO_REQUEST:
-                               debug("Got ICMP ECHO REQUEST, return %d bytes\n",
-                                     ETHER_HDR_SIZE + len);
-
-                               memcpy(&et->et_dest[0], &et->et_src[0], 6);
-                               memcpy(&et->et_src[0], NetOurEther, 6);
-
-                               ip->ip_sum = 0;
-                               ip->ip_off = 0;
-                               NetCopyIP((void *)&ip->ip_dst, &ip->ip_src);
-                               NetCopyIP((void *)&ip->ip_src, &NetOurIP);
-                               ip->ip_sum = ~NetCksum((uchar *)ip,
-                                                      IP_HDR_SIZE_NO_UDP >> 1);
-
-                               icmph->type = ICMP_ECHO_REPLY;
-                               icmph->checksum = 0;
-                               icmph->checksum = ~NetCksum((uchar *)icmph,
-                                       (len - IP_HDR_SIZE_NO_UDP) >> 1);
-                               (void) eth_send((uchar *)et,
-                                               ETHER_HDR_SIZE + len);
-                               return;
-#endif
-                       default:
-                               return;
-                       }
+                       receive_icmp(ip, len, src_ip, et);
+                       return;
                } else if (ip->ip_p != IPPROTO_UDP) {   /* Only UDP packets */
                        return;
                }
@@ -1747,7 +1797,7 @@ NetReceive(volatile uchar *inpkt, int len)
 
 /**********************************************************************/
 
-static int net_check_prereq(proto_t protocol)
+static int net_check_prereq(enum proto_t protocol)
 {
        switch (protocol) {
                /* Fall through */
@@ -1778,7 +1828,8 @@ static int net_check_prereq(proto_t protocol)
 #if defined(CONFIG_CMD_NFS)
        case NFS:
 #endif
-       case TFTP:
+       case TFTPGET:
+       case TFTPPUT:
                if (NetServerIP == 0) {
                        puts("*** ERROR: `serverip' not set\n");
                        return 1;
@@ -1790,6 +1841,7 @@ common:
                /* Fall through */
 
        case NETCONS:
+       case TFTPSRV:
                if (NetOurIP == 0) {
                        puts("*** ERROR: `ipaddr' not set\n");
                        return 1;
@@ -1803,7 +1855,6 @@ common:
        case CDP:
        case DHCP:
                if (memcmp(NetOurEther, "\0\0\0\0\0\0", 6) == 0) {
-#ifdef CONFIG_NET_MULTI
                        extern int eth_get_dev_index(void);
                        int num = eth_get_dev_index();
 
@@ -1822,10 +1873,6 @@ common:
 
                        NetStartAgain();
                        return 2;
-#else
-                       puts("*** ERROR: `ethaddr' not set\n");
-                       return 1;
-#endif
                }
                /* Fall through */
        default: