svn_rev_095
Currently U-Boot uses globally defined eth_* functions. This is horribly unflexible. This patch replaces the global functions with pointers from structs. We could also use CONFIG_NET_MULTI, but this has other implications, though we should merge this some day. Also, U-Boot has no unique way to handle MAC addresses. Each and every board and network driver uses it's own mechanism to set the MAC address. There are several problems which I've for too often. For example everything goes well if we boot from network, but when we boot from flash U-Boot forgets to set the MAC address and the linux network driver has none. This patch adds [gs]et_mac_address to the eth_device struct and handles it as follows: - First try to get a valid MAC address from the EEPROM and set 'ethaddr' accordingly. - If no valid MAC address is found in the EEPROM (or no EEPROM is connected), we set the devices MAC address from 'ethaddr' This is done in eth_initialize which is called on startup for every board.
This commit is contained in:
parent
793babe674
commit
f6508e1c4b
|
@ -151,7 +151,7 @@ UCHAR at91rm9200_EmacWritePhy (AT91PS_EMAC p_mac,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int eth_init (bd_t * bd)
|
static int at91rm9200_eth_init (struct eth_device *ndev, bd_t * bd)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
@ -190,10 +190,6 @@ int eth_init (bd_t * bd)
|
||||||
rbfdt[RBF_FRAMEMAX - 1].addr |= RBF_WRAP;
|
rbfdt[RBF_FRAMEMAX - 1].addr |= RBF_WRAP;
|
||||||
rbfp = &rbfdt[0];
|
rbfp = &rbfdt[0];
|
||||||
|
|
||||||
p_mac->EMAC_SA2L = (bd->bi_enetaddr[3] << 24) | (bd->bi_enetaddr[2] << 16)
|
|
||||||
| (bd->bi_enetaddr[1] << 8) | (bd->bi_enetaddr[0]);
|
|
||||||
p_mac->EMAC_SA2H = (bd->bi_enetaddr[5] << 8) | (bd->bi_enetaddr[4]);
|
|
||||||
|
|
||||||
p_mac->EMAC_RBQP = (long) (&rbfdt[0]);
|
p_mac->EMAC_RBQP = (long) (&rbfdt[0]);
|
||||||
p_mac->EMAC_RSR &= ~(AT91C_EMAC_RSR_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
|
p_mac->EMAC_RSR &= ~(AT91C_EMAC_RSR_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
|
||||||
|
|
||||||
|
@ -211,6 +207,13 @@ int eth_init (bd_t * bd)
|
||||||
|
|
||||||
p_mac->EMAC_CTL |= AT91C_EMAC_TE | AT91C_EMAC_RE;
|
p_mac->EMAC_CTL |= AT91C_EMAC_TE | AT91C_EMAC_RE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int at91rm9200_eth_open (struct eth_device *ndev, bd_t * bd)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
at91rm9200_GetPhyInterface (& PhyOps);
|
at91rm9200_GetPhyInterface (& PhyOps);
|
||||||
|
|
||||||
if (!PhyOps.IsPhyConnected (p_mac))
|
if (!PhyOps.IsPhyConnected (p_mac))
|
||||||
|
@ -226,11 +229,9 @@ int eth_init (bd_t * bd)
|
||||||
printf ("No link\n\r");
|
printf ("No link\n\r");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int eth_send (volatile void *packet, int length)
|
static int at91rm9200_eth_send (struct eth_device *ndev, volatile void *packet, int length)
|
||||||
{
|
{
|
||||||
while (!(p_mac->EMAC_TSR & AT91C_EMAC_BNQ));
|
while (!(p_mac->EMAC_TSR & AT91C_EMAC_BNQ));
|
||||||
p_mac->EMAC_TAR = (long) packet;
|
p_mac->EMAC_TAR = (long) packet;
|
||||||
|
@ -240,7 +241,7 @@ int eth_send (volatile void *packet, int length)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int eth_rx (void)
|
static int at91rm9200_eth_rx (struct eth_device *ndev)
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
|
@ -261,7 +262,7 @@ int eth_rx (void)
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void eth_halt (void)
|
static void at91rm9200_eth_halt (struct eth_device *ndev)
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -294,6 +295,31 @@ int at91rm9200_miiphy_initialize(bd_t *bis)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int at91rm9200_get_mac_address(struct eth_device *eth, unsigned char *adr)
|
||||||
|
{
|
||||||
|
/* We have no eeprom */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int at91rm9200_set_mac_address(struct eth_device *eth, unsigned char *adr)
|
||||||
|
{
|
||||||
|
p_mac->EMAC_SA2L = (adr[3] << 24) | (adr[2] << 16)
|
||||||
|
| (adr[1] << 8) | (adr[0]);
|
||||||
|
p_mac->EMAC_SA2H = (adr[5] << 8) | (adr[4]);
|
||||||
|
|
||||||
|
return -0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct eth_device at91rm9200_eth = {
|
||||||
|
.init = at91rm9200_eth_init,
|
||||||
|
.open = at91rm9200_eth_open,
|
||||||
|
.send = at91rm9200_eth_send,
|
||||||
|
.recv = at91rm9200_eth_rx,
|
||||||
|
.halt = at91rm9200_eth_halt,
|
||||||
|
.get_mac_address = at91rm9200_get_mac_address,
|
||||||
|
.set_mac_address = at91rm9200_set_mac_address,
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
|
#endif /* CONFIG_COMMANDS & CFG_CMD_NET */
|
||||||
|
|
||||||
#endif /* CONFIG_DRIVER_ETHER */
|
#endif /* CONFIG_DRIVER_ETHER */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -99,9 +99,12 @@ struct eth_device {
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
int (*init) (struct eth_device*, bd_t*);
|
int (*init) (struct eth_device*, bd_t*);
|
||||||
|
int (*open) (struct eth_device*, bd_t*);
|
||||||
int (*send) (struct eth_device*, volatile void* pachet, int length);
|
int (*send) (struct eth_device*, volatile void* pachet, int length);
|
||||||
int (*recv) (struct eth_device*);
|
int (*recv) (struct eth_device*);
|
||||||
void (*halt) (struct eth_device*);
|
void (*halt) (struct eth_device*);
|
||||||
|
int (*get_mac_address) (struct eth_device*, unsigned char *adr);
|
||||||
|
int (*set_mac_address) (struct eth_device*, unsigned char *adr);
|
||||||
|
|
||||||
struct eth_device *next;
|
struct eth_device *next;
|
||||||
void *priv;
|
void *priv;
|
||||||
|
@ -451,5 +454,13 @@ extern ushort getenv_VLAN(char *);
|
||||||
extern void copy_filename (char *dst, char *src, int size);
|
extern void copy_filename (char *dst, char *src, int size);
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
/* Network devices */
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
extern void eth_set_current(struct eth_device *eth);
|
||||||
|
extern struct eth_device *eth_get_current(void);
|
||||||
|
|
||||||
|
extern struct eth_device at91rm9200_eth;
|
||||||
|
extern struct eth_device smc91111_eth;
|
||||||
|
|
||||||
#endif /* __NET_H__ */
|
#endif /* __NET_H__ */
|
||||||
|
|
146
net/eth.c
146
net/eth.c
|
@ -56,8 +56,6 @@ extern int tsec_initialize(bd_t*, int, char *);
|
||||||
extern int npe_initialize(bd_t *);
|
extern int npe_initialize(bd_t *);
|
||||||
extern int uec_initialize(int);
|
extern int uec_initialize(int);
|
||||||
|
|
||||||
static struct eth_device *eth_devices, *eth_current;
|
|
||||||
|
|
||||||
struct eth_device *eth_get_dev(void)
|
struct eth_device *eth_get_dev(void)
|
||||||
{
|
{
|
||||||
return eth_current;
|
return eth_current;
|
||||||
|
@ -358,56 +356,6 @@ void eth_set_enetaddr(int num, char *addr) {
|
||||||
memcpy(dev->enetaddr, enetaddr, 6);
|
memcpy(dev->enetaddr, enetaddr, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
int eth_init(bd_t *bis)
|
|
||||||
{
|
|
||||||
struct eth_device* old_current;
|
|
||||||
|
|
||||||
if (!eth_current)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
old_current = eth_current;
|
|
||||||
do {
|
|
||||||
debug ("Trying %s\n", eth_current->name);
|
|
||||||
|
|
||||||
if (eth_current->init(eth_current, bis)) {
|
|
||||||
eth_current->state = ETH_STATE_ACTIVE;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
debug ("FAIL\n");
|
|
||||||
|
|
||||||
eth_try_another(0);
|
|
||||||
} while (old_current != eth_current);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void eth_halt(void)
|
|
||||||
{
|
|
||||||
if (!eth_current)
|
|
||||||
return;
|
|
||||||
|
|
||||||
eth_current->halt(eth_current);
|
|
||||||
|
|
||||||
eth_current->state = ETH_STATE_PASSIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int eth_send(volatile void *packet, int length)
|
|
||||||
{
|
|
||||||
if (!eth_current)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return eth_current->send(eth_current, packet, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int eth_rx(void)
|
|
||||||
{
|
|
||||||
if (!eth_current)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return eth_current->recv(eth_current);
|
|
||||||
}
|
|
||||||
|
|
||||||
void eth_try_another(int first_restart)
|
void eth_try_another(int first_restart)
|
||||||
{
|
{
|
||||||
static struct eth_device *first_failed = NULL;
|
static struct eth_device *first_failed = NULL;
|
||||||
|
@ -464,6 +412,55 @@ char *eth_get_name (void)
|
||||||
}
|
}
|
||||||
#elif (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_NET_MULTI)
|
#elif (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_NET_MULTI)
|
||||||
|
|
||||||
|
static struct eth_device *eth_current;
|
||||||
|
|
||||||
|
void eth_set_current(struct eth_device *eth)
|
||||||
|
{
|
||||||
|
eth_current = eth;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct eth_device * eth_get_current(void)
|
||||||
|
{
|
||||||
|
return eth_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
int eth_init(bd_t *bis)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!eth_current)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
eth_current->open(eth_current, bis);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void eth_halt(void)
|
||||||
|
{
|
||||||
|
if (!eth_current)
|
||||||
|
return;
|
||||||
|
|
||||||
|
eth_current->halt(eth_current);
|
||||||
|
|
||||||
|
eth_current->state = ETH_STATE_PASSIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int eth_send(volatile void *packet, int length)
|
||||||
|
{
|
||||||
|
if (!eth_current)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return eth_current->send(eth_current, packet, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
int eth_rx(void)
|
||||||
|
{
|
||||||
|
if (!eth_current)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return eth_current->recv(eth_current);
|
||||||
|
}
|
||||||
|
|
||||||
extern int at91rm9200_miiphy_initialize(bd_t *bis);
|
extern int at91rm9200_miiphy_initialize(bd_t *bis);
|
||||||
extern int emac4xx_miiphy_initialize(bd_t *bis);
|
extern int emac4xx_miiphy_initialize(bd_t *bis);
|
||||||
extern int mcf52x2_miiphy_initialize(bd_t *bis);
|
extern int mcf52x2_miiphy_initialize(bd_t *bis);
|
||||||
|
@ -471,6 +468,51 @@ extern int ns7520_miiphy_initialize(bd_t *bis);
|
||||||
|
|
||||||
int eth_initialize(bd_t *bis)
|
int eth_initialize(bd_t *bis)
|
||||||
{
|
{
|
||||||
|
unsigned char ethaddr_tmp[20];
|
||||||
|
unsigned char *ethaddr, *e = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!eth_current) {
|
||||||
|
printf("%s: no eth device set\n", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eth_current->init(eth_current, bis)) {
|
||||||
|
printf("failed to initialize network device\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eth_current->get_mac_address) {
|
||||||
|
printf("no get_mac_address found for current eth device\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ethaddr = eth_current->enetaddr;
|
||||||
|
|
||||||
|
/* Try to get a MAC address from the eeprom set 'ethaddr' to it.
|
||||||
|
* If this fails we rely on 'ethaddr' being set by the user.
|
||||||
|
*/
|
||||||
|
if (eth_current->get_mac_address(eth_current, ethaddr) == 0) {
|
||||||
|
sprintf (ethaddr_tmp, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||||
|
ethaddr[0], ethaddr[1], ethaddr[2], ethaddr[3], ethaddr[4], ethaddr[5]);
|
||||||
|
printf("got MAC address from EEPROM: %s\n",ethaddr_tmp);
|
||||||
|
setenv ("ethaddr", ethaddr_tmp);
|
||||||
|
} else {
|
||||||
|
ethaddr = getenv ("ethaddr");
|
||||||
|
if (!ethaddr){
|
||||||
|
printf("could not get MAC address from device and ethaddr not set\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < 6; i++) {
|
||||||
|
eth_current->enetaddr[i] = ethaddr ? simple_strtoul (ethaddr, &e, 16) : 0;
|
||||||
|
if (ethaddr) {
|
||||||
|
ethaddr = (*e) ? e + 1 : e;
|
||||||
|
}
|
||||||
|
eth_current->set_mac_address(eth_current, eth_current->enetaddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
|
#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII)
|
||||||
miiphy_init();
|
miiphy_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -308,7 +308,7 @@ restart:
|
||||||
#ifdef CONFIG_NET_MULTI
|
#ifdef CONFIG_NET_MULTI
|
||||||
memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
|
memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
|
||||||
#else
|
#else
|
||||||
memcpy (NetOurEther, bd->bi_enetaddr, 6);
|
memcpy (NetOurEther, &(eth_get_current()->enetaddr), 6);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NetState = NETLOOP_CONTINUE;
|
NetState = NETLOOP_CONTINUE;
|
||||||
|
|
Loading…
Reference in New Issue