Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
* 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
* - own IP address
* We want: - network time
* Next step: none
*/
#include <common.h>
#include <watchdog.h>
#include <command.h>
#include <net.h>
#include "bootp.h"
#include "tftp.h"
#include "rarp.h"
#ifdef CONFIG_STATUS_LED
#include <status_led.h>
#include <miiphy.h>
#endif
#if defined(CONFIG_CMD_SNTP)
#if defined(CONFIG_CDP_VERSION)
#include <timestamp.h>
#endif
#if defined(CONFIG_CMD_NET)
DECLARE_GLOBAL_DATA_PTR;
# define ARP_TIMEOUT 5000UL /* Milliseconds before trying ARP again */
# define ARP_TIMEOUT CONFIG_ARP_TIMEOUT
# define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */
# define ARP_TIMEOUT_COUNT CONFIG_NET_RETRY_COUNT
#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 defined(CONFIG_BOOTP_DNS2)
Stefan Roese
committed
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 */
#ifdef CONFIG_MCAST_TFTP /* Multicast TFTP */
IPaddr_t Mcast_addr;
#endif
/** 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 */
IPaddr_t NetServerIP; /* Server IP addr (0 = unknown) */
volatile uchar *NetRxPacket; /* Current receive packet */
int NetRxPacketLen; /* 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 };
#ifdef CONFIG_API
void (*push_packet)(volatile void *, int len) = 0;
#endif
#if defined(CONFIG_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 */
#if defined(CONFIG_CMD_PING)
IPaddr_t NetPingIP; /* the ip address to ping */
static void PingStart(void);
#endif
#if defined(CONFIG_CMD_CDP)
static void CDPStart(void);
#endif
#if defined(CONFIG_CMD_SNTP)
IPaddr_t NetNtpServerIP; /* NTP server IP address */
int NetTimeOffset=0; /* offset time from UTC */
#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 NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
ulong NetArpWaitTimerStart;
int NetArpWaitTry;
pkt += NetSetEther (pkt, NetBcastAddr, PROT_ARP);
arp->ar_hrd = htons (ARP_ETHER);
arp->ar_pro = htons (PROT_IP);
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 = NetArpWaitPacketIP;
} else {
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) {
NetArpWaitTry++;
if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) {
puts ("\nARP Retry count exceeded; starting again\n");
NetArpWaitTry = 0;
NetStartAgain();
} else {
NetArpWaitTimerStart = t;
ArpRequest();
}
}
}
bd_t *bd = gd->bd;
int env_id = get_env_id ();
/* update only when the environment has changed */
NetCopyIP(&NetOurIP, &bd->bi_ip_addr);
NetOurGatewayIP = getenv_IPaddr ("gatewayip");
NetOurSubnetMask= getenv_IPaddr ("netmask");
NetServerIP = getenv_IPaddr ("serverip");
NetOurNativeVLAN = getenv_VLAN("nvlan");
NetOurVLAN = getenv_VLAN("vlan");
env_changed_id = env_id;
/**********************************************************************/
/*
* Main network processing loop.
*/
int
NetLoop(proto_t protocol)
{
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;
if (eth_init(bd) < 0) {
eth_halt();
restart:
#ifdef CONFIG_NET_MULTI
memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
#else
eth_getenv_enetaddr("ethaddr", NetOurEther);
#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 (net_check_prereq (protocol)) {
case 1:
/* network not configured */
#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 */
#if defined(CONFIG_CMD_DHCP)
DhcpRequest(); /* Basically same as BOOTP */
break;
case BOOTP:
BootpTry = 0;
BootpRequest ();
break;
case RARP:
RarpTry = 0;
RarpRequest ();
break;
#if defined(CONFIG_CMD_PING)
#if defined(CONFIG_CMD_NFS)
case NFS:
NfsStart();
break;
#if defined(CONFIG_CMD_CDP)
case CDP:
CDPStart();
break;
#endif
#ifdef CONFIG_NETCONSOLE
case NETCONS:
NcStart();
break;
#if defined(CONFIG_CMD_SNTP)
case SNTP:
SntpStart();
break;
default:
break;
}
NetBootFileXferSize = 0;
break;
}
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
#if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED)
* Echo the inverted link state to the fault LED.
if(miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR)) {
status_led_set (STATUS_LED_RED, STATUS_LED_OFF);
} else {
status_led_set (STATUS_LED_RED, STATUS_LED_ON);
}
#endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */
/*
* Main packet reception loop. Loop receiving packets until
*/
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.
*/
/*
* Abort if ctrl-c was pressed.
*/
if (ctrlc()) {
/*
* Check for a timeout, and run the timeout handler
* if we have one.
*/
if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) {
Loading
Loading full blame...