📄 net.c
字号:
/* * Copied from Linux Monitor (LiMon) - Networking. * * Copyright 1994 - 2000 Neil Russell. * (See License) * Copyright 2000 Roland Borde * Copyright 2000 Paolo Scaffardi * Copyright 2000-2002 Wolfgang Denk, wd@denx.de *//* * General Desription: * * The user interface supports commands for BOOTP, RARP, and TFTP. * Also, we support ARP internally. Depending on available data, * these interact as follows: * * BOOTP: * * Prerequisites: - own ethernet address * We want: - own IP address * - TFTP server IP address * - name of bootfile * Next step: ARP * * RARP: * * Prerequisites: - own ethernet address * We want: - own IP address * - TFTP server IP address * Next step: ARP * * ARP: * * Prerequisites: - own ethernet address * - own IP address * - TFTP server IP address * We want: - TFTP server ethernet address * Next step: TFTP * * DHCP: * * Prerequisites: - own ethernet address * We want: - IP, Netmask, ServerIP, Gateway IP * - bootfilename, lease time * Next step: - TFTP * * TFTP: * * Prerequisites: - own ethernet address * - own IP address * - TFTP server IP address * - TFTP server ethernet address * - name of bootfile (if unknown, we use a default name * derived from our own IP address) * We want: - load the boot file * Next step: none * * NFS: * * Prerequisites: - own ethernet address * - own IP address * - name of bootfile (if unknown, we use a default name * derived from our own IP address) * We want: - load the boot file * Next step: none */#include <common.h>#include <watchdog.h>#include <command.h>#include <net.h>#include "bootp.h"#include "tftp.h"#include "rarp.h"#include "nfs.h"#ifdef CONFIG_STATUS_LED#include <status_led.h>#include <miiphy.h>#endif#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/** BOOTP EXTENTIONS **/IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */IPaddr_t NetOurGatewayIP=0; /* Our gateways IP address */IPaddr_t NetOurDNSIP=0; /* Our DNS IP address */#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2)IPaddr_t NetOurDNS2IP=0; /* Our 2nd DNS IP address */#endifchar NetOurNISDomain[32]={0,}; /* Our NIS domain */char NetOurHostName[32]={0,}; /* Our hostname */char NetOurRootPath[64]={0,}; /* Our bootpath */ushort NetBootFileSize=0; /* Our bootfile size in blocks *//** END OF BOOTP EXTENTIONS **/ulong NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */uchar NetOurEther[6]; /* Our ethernet address */uchar NetServerEther[6] = /* Boot server enet address */ { 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 */int NetRxPktLen; /* Current rx packet length */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 };#if (CONFIG_COMMANDS & CFG_CMD_CDP)uchar NetCDPAddr[6] = /* Ethernet bcast address */ { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc };#endifint NetState; /* Network loop state */#ifdef CONFIG_NET_MULTIint NetRestartWrap = 0; /* Tried all network devices */static int NetRestarted = 0; /* Network loop restarted */static int NetDevExists = 0; /* At least one device configured */#endif/* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */ushort NetOurVLAN = 0xFFFF; /* default is without VLAN */ushort NetOurNativeVLAN = 0xFFFF; /* ditto */char BootFile[128]; /* Boot File name */#if (CONFIG_COMMANDS & CFG_CMD_PING)IPaddr_t NetPingIP; /* the ip address to ping */static void PingStart(void);#endif#if (CONFIG_COMMANDS & CFG_CMD_CDP)static void CDPStart(void);#endif#ifdef CONFIG_NETCONSOLEvoid NcStart(void);int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len);#endifvolatile uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */static rxhand_f *packetHandler; /* Current RX packet handler */static thand_f *timeHandler; /* Current timeout handler */static ulong timeStart; /* Time base value */static ulong timeDelta; /* Current timeout value */volatile uchar *NetTxPacket = 0; /* THE transmit packet */static int net_check_prereq (proto_t protocol);/**********************************************************************/IPaddr_t NetArpWaitPacketIP;IPaddr_t NetArpWaitReplyIP;uchar *NetArpWaitPacketMAC; /* MAC address of waiting packet's destination */uchar *NetArpWaitTxPacket; /* 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;#ifdef ET_DEBUG printf ("ARP broadcast %d\n", NetArpWaitTry);#endif pkt = NetTxPacket; pkt += NetSetEther (pkt, NetBcastAddr, PROT_ARP); 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"); } NetArpWaitReplyIP = NetOurGatewayIP; } else { NetArpWaitReplyIP = NetArpWaitPacketIP; } NetWriteIP ((uchar *) & arp->ar_data[16], NetArpWaitReplyIP); (void) eth_send (NetTxPacket, (pkt - NetTxPacket) + 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. */intNetLoop(proto_t protocol){ DECLARE_GLOBAL_DATA_PTR; bd_t *bd = gd->bd;#ifdef CONFIG_NET_MULTI NetRestarted = 0; NetDevExists = 0;#endif /* XXX problem with bss workaround */ NetArpWaitPacketMAC = NULL; NetArpWaitTxPacket = NULL; NetArpWaitPacketIP = 0; NetArpWaitReplyIP = 0; NetArpWaitTxPacket = NULL; NetTxPacket = NULL; if (!NetTxPacket) { int i; /* * Setup packet buffers, aligned correctly. */ NetTxPacket = &PktBuf[0] + (PKTALIGN - 1); NetTxPacket -= (ulong)NetTxPacket % PKTALIGN; 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();#ifdef CONFIG_NET_MULTI eth_set_current();#endif if (eth_init(bd) < 0) return(-1);restart:#ifdef CONFIG_NET_MULTI memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);#else memcpy (NetOurEther, bd->bi_enetaddr, 6);#endif NetState = NETLOOP_CONTINUE; /* * Start the ball rolling with the given start function. From * here on, this code is a state machine driven by received * packets and timer events. */ switch (protocol) {#if (CONFIG_COMMANDS & CFG_CMD_NFS) case NFS:#endif#if (CONFIG_COMMANDS & CFG_CMD_PING) case PING:#endif case NETCONS: case TFTP: NetCopyIP(&NetOurIP, &bd->bi_ip_addr); NetOurGatewayIP = getenv_IPaddr ("gatewayip"); NetOurSubnetMask= getenv_IPaddr ("netmask"); NetOurVLAN = getenv_VLAN("vlan"); NetOurNativeVLAN = getenv_VLAN("nvlan"); switch (protocol) {#if (CONFIG_COMMANDS & CFG_CMD_NFS) case NFS:#endif case NETCONS: case TFTP: NetServerIP = getenv_IPaddr ("serverip"); break;#if (CONFIG_COMMANDS & CFG_CMD_PING) case PING: /* nothing */ break;#endif default: break; } break; case BOOTP: case RARP: /* * initialize our IP addr to 0 in order to accept ANY * IP addr assigned to us by the BOOTP / RARP server */ NetOurIP = 0; NetServerIP = getenv_IPaddr ("serverip"); NetOurVLAN = getenv_VLAN("vlan"); /* VLANs must be read */ NetOurNativeVLAN = getenv_VLAN("nvlan"); case CDP: NetOurVLAN = getenv_VLAN("vlan"); /* VLANs must be read */ NetOurNativeVLAN = getenv_VLAN("nvlan"); break; default: break; } switch (net_check_prereq (protocol)) { case 1: /* network not configured */ 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 switch (protocol) { case TFTP: /* always use ARP to get server ethernet address */ TftpStart(); break;#if (CONFIG_COMMANDS & CFG_CMD_DHCP) case DHCP: /* Start with a clean slate... */ BootpTry = 0; NetOurIP = 0; NetServerIP = getenv_IPaddr ("serverip"); DhcpRequest(); /* Basically same as BOOTP */ break;#endif /* CFG_CMD_DHCP */ case BOOTP: BootpTry = 0; BootpRequest (); break; case RARP: RarpTry = 0; RarpRequest (); break;#if (CONFIG_COMMANDS & CFG_CMD_PING) case PING: PingStart(); break;#endif#if (CONFIG_COMMANDS & CFG_CMD_NFS) case NFS: NfsStart(); break;#endif#if (CONFIG_COMMANDS & CFG_CMD_CDP) case CDP: CDPStart(); break;#endif#ifdef CONFIG_NETCONSOLE case NETCONS: NcStart(); break;#endif default: break; } NetBootFileXferSize = 0; break; }#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)#if defined(CFG_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED) /* * Echo the inverted link state to the fault LED. */ if(miiphy_link(CFG_FAULT_MII_ADDR)) { status_led_set (STATUS_LED_RED, STATUS_LED_OFF); } else { status_led_set (STATUS_LED_RED, STATUS_LED_ON); }#endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */#endif /* CONFIG_MII, ... */ /* * Main packet reception loop. Loop receiving packets until * someone sets `NetQuit'. */ for (;;) { WATCHDOG_RESET();#ifdef CONFIG_SHOW_ACTIVITY { extern void show_activity(int arg); show_activity(1); }#endif /* * Check the ethernet for a new packet. The ethernet * receive routine will process it. */ eth_rx(); /* * Abort if ctrl-c was pressed. */ if (ctrlc()) { eth_halt(); puts ("\nAbort\n"); return (-1); } ArpTimeoutCheck(); /* * Check for a timeout, and run the timeout handler * if we have one. */ if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) { thand_f *x;#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)#if defined(CFG_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED) /* * Echo the inverted link state to the fault LED. */ if(miiphy_link(CFG_FAULT_MII_ADDR)) { status_led_set (STATUS_LED_RED, STATUS_LED_OFF); } else { status_led_set (STATUS_LED_RED, STATUS_LED_ON); }#endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */#endif /* CONFIG_MII, ... */ x = timeHandler; timeHandler = (thand_f *)0; (*x)(); } switch (NetState) { case NETLOOP_RESTART:#ifdef CONFIG_NET_MULTI NetRestarted = 1;#endif goto restart; case NETLOOP_SUCCESS: if (NetBootFileXferSize > 0) { char buf[10]; printf("Bytes transferred = %ld (%lx hex)\n", NetBootFileXferSize, NetBootFileXferSize); sprintf(buf, "%lx", NetBootFileXferSize); setenv("filesize", buf); sprintf(buf, "%lX", (unsigned long)load_addr); setenv("fileaddr", buf); } eth_halt(); return NetBootFileXferSize; case NETLOOP_FAIL: return (-1); } }}/**********************************************************************/static voidstartAgainTimeout(void){ NetState = NETLOOP_RESTART;}static voidstartAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len){ /* Totally ignore the packet */}void NetStartAgain (void){#ifdef CONFIG_NET_MULTI DECLARE_GLOBAL_DATA_PTR;#endif char *nretry; int noretry = 0, once = 0; if ((nretry = getenv ("netretry")) != NULL) { noretry = (strcmp (nretry, "no") == 0); once = (strcmp (nretry, "once") == 0); } if (noretry) { eth_halt (); NetState = NETLOOP_FAIL; return; }#ifndef CONFIG_NET_MULTI NetSetTimeout (10 * CFG_HZ, startAgainTimeout);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -