]> 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 5e67886b6806d98b7fc000ae8c996d6dfe2003cd..d0fe1c4960a2fb024dc5cb704712fb0e61ab785e 100644 (file)
--- a/net/net.c
+++ b/net/net.c
@@ -215,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 */
@@ -224,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;
 
@@ -243,7 +246,6 @@ int         NetArpWaitTry;
 
 void ArpRequest(void)
 {
-       int i;
        volatile uchar *pkt;
        ARP_t *arp;
 
@@ -265,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) {
@@ -310,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;
@@ -340,10 +368,10 @@ 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;
 
        NetRestarted = 0;
        NetDevExists = 0;
@@ -405,10 +433,14 @@ restart:
 
        case 0:
                NetDevExists = 1;
+               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:
@@ -470,7 +502,6 @@ restart:
                        break;
                }
 
-               NetBootFileXferSize = 0;
                break;
        }
 
@@ -512,7 +543,7 @@ restart:
                if (ctrlc()) {
                        eth_halt();
                        puts("\nAbort\n");
-                       return -1;
+                       goto done;
                }
 
                ArpTimeoutCheck();
@@ -564,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;
 }
 
 /**********************************************************************/
@@ -643,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)
@@ -1034,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? */
@@ -1106,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 */
@@ -1331,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)
 {
@@ -1615,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;
                }
@@ -1728,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 */
@@ -1759,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;