Newer
Older
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <command.h>
#include <net.h>
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI)
#ifdef CFG_GT_6426x
extern int gt6426x_eth_initialize(bd_t *bis);
#endif
extern int e1000_initialize(bd_t*);
extern int eepro100_initialize(bd_t*);
extern int natsemi_initialize(bd_t*);
extern int ns8382x_initialize(bd_t*);
extern int dc21x4x_initialize(bd_t*);
extern int eth_3com_initialize(bd_t*);
extern int pcnet_initialize(bd_t*);
extern int fec_initialize(bd_t*);
extern int scc_initialize(bd_t*);
extern int inca_switch_initialize(bd_t*);
extern int ppc_4xx_eth_initialize(bd_t *);
extern int plb2800_eth_initialize(bd_t*);
extern int mpc5xxx_fec_initialize(bd_t*);
extern int tsec_initialize(bd_t*);
extern int au1x00_enet_initialize(bd_t*);
extern int rtl8139_initialize(bd_t*);
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
static struct eth_device *eth_devices, *eth_current;
struct eth_device *eth_get_dev(void)
{
return eth_current;
}
int eth_get_dev_index (void)
{
struct eth_device *dev;
int num = 0;
if (!eth_devices) {
return (-1);
}
for (dev = eth_devices; dev; dev = dev->next) {
if (dev == eth_current)
break;
++num;
}
if (dev) {
return (num);
}
return (0);
}
int eth_register(struct eth_device* dev)
{
struct eth_device *d;
if (!eth_devices) {
eth_current = eth_devices = dev;
} else {
for (d=eth_devices; d->next!=eth_devices; d=d->next);
d->next = dev;
}
dev->state = ETH_STATE_INIT;
dev->next = eth_devices;
return 0;
}
int eth_initialize(bd_t *bis)
{
unsigned char enetvar[32], env_enetaddr[6];
int i, eth_number = 0;
char *tmp, *end;
eth_devices = NULL;
eth_current = NULL;
#if defined(CONFIG_405GP) || defined(CONFIG_440) || defined(CONFIG_405EP)
#ifdef CONFIG_INCA_IP_SWITCH
inca_switch_initialize(bis);
#endif
#ifdef CONFIG_PLB2800_ETHER
plb2800_eth_initialize(bis);
#endif
#ifdef CONFIG_E1000
e1000_initialize(bis);
#endif
#ifdef CONFIG_EEPRO100
eepro100_initialize(bis);
#endif
#ifdef CONFIG_TULIP
dc21x4x_initialize(bis);
#endif
#ifdef CONFIG_3COM
eth_3com_initialize(bis);
#endif
#ifdef CONFIG_PCNET
pcnet_initialize(bis);
#endif
#ifdef CFG_GT_6426x
gt6426x_eth_initialize(bis);
#endif
#ifdef CONFIG_NATSEMI
natsemi_initialize(bis);
#endif
#ifdef CONFIG_NS8382X
ns8382x_initialize(bis);
#endif
#ifdef SCC_ENET
scc_initialize(bis);
#endif
#if defined(FEC_ENET) || defined(CONFIG_ETHER_ON_FCC)
#if defined(CONFIG_MPC5XXX_FEC)
mpc5xxx_fec_initialize(bis);
#endif
#if defined(CONFIG_SK98)
skge_initialize(bis);
#endif
#ifdef CONFIG_TSEC_ENET
tsec_initialize(bis);
#endif
#if defined(CONFIG_AU1X00)
au1x00_enet_initialize(bis);
#endif
#if defined(CONFIG_RTL8139)
rtl8139_initialize(bis);
#endif
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
if (!eth_devices) {
puts ("No ethernet found.\n");
} else {
struct eth_device *dev = eth_devices;
char *ethprime = getenv ("ethprime");
do {
if (eth_number)
puts (", ");
printf("%s", dev->name);
if (ethprime && strcmp (dev->name, ethprime) == 0) {
eth_current = dev;
puts (" [PRIME]");
}
sprintf(enetvar, eth_number ? "eth%daddr" : "ethaddr", eth_number);
tmp = getenv (enetvar);
for (i=0; i<6; i++) {
env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
if (tmp)
tmp = (*end) ? end+1 : end;
}
if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6)) {
if (memcmp(dev->enetaddr, "\0\0\0\0\0\0", 6) &&
memcmp(dev->enetaddr, env_enetaddr, 6))
{
printf("\nWarning: %s MAC addresses don't match:\n", dev->name);
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
printf("Address in SROM is "
"%02X:%02X:%02X:%02X:%02X:%02X\n",
dev->enetaddr[0], dev->enetaddr[1],
dev->enetaddr[2], dev->enetaddr[3],
dev->enetaddr[4], dev->enetaddr[5]);
printf("Address in environment is "
"%02X:%02X:%02X:%02X:%02X:%02X\n",
env_enetaddr[0], env_enetaddr[1],
env_enetaddr[2], env_enetaddr[3],
env_enetaddr[4], env_enetaddr[5]);
}
memcpy(dev->enetaddr, env_enetaddr, 6);
}
eth_number++;
dev = dev->next;
} while(dev != eth_devices);
putc ('\n');
}
return eth_number;
}
void eth_set_enetaddr(int num, char *addr) {
struct eth_device *dev;
unsigned char enetaddr[6];
char *end;
int i;
debug ("eth_set_enetaddr(num=%d, addr=%s)\n", num, addr);
if (!eth_devices)
return;
for (i=0; i<6; i++) {
enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
if (addr)
addr = (*end) ? end+1 : end;
}
dev = eth_devices;
while(num-- > 0) {
dev = dev->next;
if (dev == eth_devices)
return;
}
debug ( "Setting new HW address on %s\n"
"New Address is %02X:%02X:%02X:%02X:%02X:%02X\n",
dev->name,
dev->enetaddr[0], dev->enetaddr[1],
dev->enetaddr[2], dev->enetaddr[3],
dev->enetaddr[4], dev->enetaddr[5]);
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;
}
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
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;
if (!eth_current)
return;
if (first_restart)
{
first_failed = eth_current;
}
eth_current = eth_current->next;
if (first_failed == eth_current)
{
NetRestartWrap = 1;
}
}
char *eth_get_name (void)
{
return (eth_current ? eth_current->name : "unknown");
}