9
0
Fork 0

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:
Sascha Hauer 2007-07-05 18:01:22 +02:00 committed by Sascha Hauer
parent 793babe674
commit f6508e1c4b
5 changed files with 387 additions and 762 deletions

View File

@ -151,7 +151,7 @@ UCHAR at91rm9200_EmacWritePhy (AT91PS_EMAC p_mac,
return TRUE;
}
int eth_init (bd_t * bd)
static int at91rm9200_eth_init (struct eth_device *ndev, bd_t * bd)
{
int ret;
int i;
@ -190,10 +190,6 @@ int eth_init (bd_t * bd)
rbfdt[RBF_FRAMEMAX - 1].addr |= RBF_WRAP;
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_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;
return 0;
}
static int at91rm9200_eth_open (struct eth_device *ndev, bd_t * bd)
{
int ret;
at91rm9200_GetPhyInterface (& PhyOps);
if (!PhyOps.IsPhyConnected (p_mac))
@ -226,11 +229,9 @@ int eth_init (bd_t * bd)
printf ("No link\n\r");
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));
p_mac->EMAC_TAR = (long) packet;
@ -240,7 +241,7 @@ int eth_send (volatile void *packet, int length)
return 0;
}
int eth_rx (void)
static int at91rm9200_eth_rx (struct eth_device *ndev)
{
int size;
@ -261,7 +262,7 @@ int eth_rx (void)
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;
}
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_DRIVER_ETHER */

File diff suppressed because it is too large Load Diff

View File

@ -99,9 +99,12 @@ struct eth_device {
int state;
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 (*recv) (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;
void *priv;
@ -451,5 +454,13 @@ extern ushort getenv_VLAN(char *);
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__ */

146
net/eth.c
View File

@ -56,8 +56,6 @@ extern int tsec_initialize(bd_t*, int, char *);
extern int npe_initialize(bd_t *);
extern int uec_initialize(int);
static struct eth_device *eth_devices, *eth_current;
struct eth_device *eth_get_dev(void)
{
return eth_current;
@ -358,56 +356,6 @@ void eth_set_enetaddr(int num, char *addr) {
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)
{
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)
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 emac4xx_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)
{
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)
miiphy_init();
#endif

View File

@ -308,7 +308,7 @@ restart:
#ifdef CONFIG_NET_MULTI
memcpy (NetOurEther, eth_get_dev()->enetaddr, 6);
#else
memcpy (NetOurEther, bd->bi_enetaddr, 6);
memcpy (NetOurEther, &(eth_get_current()->enetaddr), 6);
#endif
NetState = NETLOOP_CONTINUE;