📄 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)
#if 1
#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 */
#endif
char 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 };
#endif
int NetState; /* Network loop state */
#ifdef CONFIG_NET_MULTI
int 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_NETCONSOLE
void NcStart(void);
int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len);
#endif
volatile 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.
*/
int
NetLoop(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 void
startAgainTimeout(void)
{
NetState = NETLOOP_RESTART;
}
static void
startAgainHandler(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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -