[U-Boot-Users] [PATCH] lan91c96 driver MAC address detection

Hi all,
This is a small patch for the lan91c96 ethernet driver that adds the capability to automatically detect the MAC address stored in EPROM in the absence of a valid MAC address in the environment. It is modelled on the system used by the smc91111 driver as suggested by Marius Groeger (thanks!)
The patch itself was created against the CVS repository tag "U-Boot-1_1_0" using the command : diff -purN u-boot u-boot-omap730p2 > u-boot-1.1.0-omap730p2.patch
All comments and feedback welcome.
Best Wishes,
Dave Peverley
--------------------------------------------------------------------------- Dave Peverley, Software Engineer, MPC Data Limited. Phone : [+44] (0) 1225 868 228 Web : http://www.mpc-data.co.uk
diff -purN u-boot/drivers/lan91c96.c u-boot-new/drivers/lan91c96.c --- u-boot/drivers/lan91c96.c 2003-06-27 22:32:37.000000000 +0100 +++ u-boot-new/drivers/lan91c96.c 2004-04-29 18:00:44.000000000 +0100 @@ -162,7 +162,7 @@ void smc_destructor (void); * The kernel calls this function when someone wants to use the device, * typically 'ifconfig ethX up'. */ -static int smc_open (void); +static int smc_open (bd_t *bd);
/* @@ -178,6 +178,12 @@ static int smc_close (void); */ static int smc_rcv (void);
+/* See if a MAC address is defined in the current environment. If so use it. If not + . print a warning and set the environment and other globals with the default. + . If an EEPROM is present it really should be consulted. +*/ +int smc_get_ethaddr(bd_t *bd); +int get_rom_mac(char *v_rom_mac);
/* ------------------------------------------------------------ * Internal routines @@ -588,9 +594,9 @@ void smc_destructor () * Set up everything, reset the card, etc .. * */ -static int smc_open () +static int smc_open (bd_t *bd) { - int i; /* used to set hw ethernet address */ + int i, err; /* used to set hw ethernet address */
PRINTK2 ("%s:smc_open\n", SMC_DEV_NAME);
@@ -601,6 +607,12 @@ static int smc_open ()
SMC_SELECT_BANK (1);
+ err = smc_get_ethaddr (bd); /* set smc_mac_addr, and sync it with u-boot globals */ + if (err < 0) { + memset (bd->bi_enetaddr, 0, 6); /* hack to make error stick! upper code will abort if not set */ + return (-1); /* upper code ignores this, but NOT bi_enetaddr */ + } +#ifdef USE_32_BIT for (i = 0; i < 6; i += 2) { word address;
@@ -608,6 +620,10 @@ static int smc_open () address |= smc_mac_addr[i]; SMC_outw (address, LAN91C96_IA0 + i); } +#else + for (i = 0; i < 6; i++) + SMC_outb (smc_mac_addr[i], LAN91C96_IA0 + i); +#endif return 0; }
@@ -782,8 +798,7 @@ static void print_packet (byte * buf, in
int eth_init (bd_t * bd) { - smc_open (); - return 0; + return (smc_open(bd)); }
void eth_halt () @@ -801,10 +816,6 @@ int eth_send (volatile void *packet, int return smc_send_packet (packet, length); }
-int eth_hw_init () -{ - return smc_hw_init (); -}
/*------------------------------------------------------------------------- * smc_hw_init() @@ -852,4 +863,103 @@ static int smc_hw_init ()
#endif /* COMMANDS & CFG_NET */
+ +/* smc_get_ethaddr (bd_t * bd) + * + * This checks both the environment and the ROM for an ethernet address. If + * found, the environment takes precedence. + */ + +int smc_get_ethaddr (bd_t * bd) +{ + int env_size = 0; + int rom_valid = 0; + int env_present = 0; + int reg = 0; + char *s = NULL; + char *e = NULL; + char *v_mac, es[] = "11:22:33:44:55:66"; + uchar s_env_mac[64]; + uchar v_env_mac[6]; + uchar v_rom_mac[6]; + + env_size = getenv_r ("ethaddr", s_env_mac, sizeof (s_env_mac)); + if (env_size != sizeof(es)) { /* Ignore if env is bad or not set */ + printf ("\n*** Warning: ethaddr is not set properly, ignoring!!\n"); + } else { + env_present = 1; + s = s_env_mac; + + for (reg = 0; reg < 6; ++reg) { /* turn string into mac value */ + v_env_mac[reg] = s ? simple_strtoul (s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + } + + rom_valid = get_rom_mac (v_rom_mac); /* get ROM mac value if any */ + + if (!env_present) { /* if NO env */ + if (rom_valid) { /* but ROM is valid */ + v_mac = v_rom_mac; + sprintf (s_env_mac, "%02X:%02X:%02X:%02X:%02X:%02X", + v_mac[0], v_mac[1], v_mac[2], v_mac[3], + v_mac[4], v_mac[5]); + setenv ("ethaddr", s_env_mac); + } else { /* no env, bad ROM */ + printf ("\n*** ERROR: ethaddr is NOT set !!\n"); + return (-1); + } + } else { /* good env, don't care ROM */ + v_mac = v_env_mac; /* always use a good env over a ROM */ + } + + if (env_present && rom_valid) { /* if both env and ROM are good */ + if (memcmp (v_env_mac, v_rom_mac, 6) != 0) { + printf ("\nWarning: MAC addresses don't match:\n"); + printf ("\tHW MAC address: " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + v_rom_mac[0], v_rom_mac[1], + v_rom_mac[2], v_rom_mac[3], + v_rom_mac[4], v_rom_mac[5] ); + printf ("\t"ethaddr" value: " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + v_env_mac[0], v_env_mac[1], + v_env_mac[2], v_env_mac[3], + v_env_mac[4], v_env_mac[5]) ; + debug ("### Set MAC addr from environment\n"); + } + } + memcpy (bd->bi_enetaddr, v_mac, 6); /* update global address to match env (allows env changing) */ + smc_set_mac_addr (v_mac); /* use old function to update smc default */ + PRINTK("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", v_mac[0], v_mac[1], + v_mac[2], v_mac[3], v_mac[4], v_mac[5]); + return (0); +} + +/* + * get_rom_mac() + * Note, this has omly been tested for the OMAP730 P2. + */ + +int get_rom_mac (char *v_rom_mac) +{ +#ifdef HARDCODE_MAC /* used for testing or to supress run time warnings */ + char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 }; + + memcpy (v_rom_mac, hw_mac_addr, 6); + return (1); +#else + int i; + SMC_SELECT_BANK (1); + for (i=0; i<6; i++) + { + v_rom_mac[i] = SMC_inb (LAN91C96_IA0 + i); + } + return (1); +#endif +} + + + #endif /* CONFIG_DRIVER_LAN91C96 */ diff -purN u-boot/drivers/lan91c96.h u-boot-new/drivers/lan91c96.h --- u-boot/drivers/lan91c96.h 2003-06-27 22:32:37.000000000 +0100 +++ u-boot-new/drivers/lan91c96.h 2004-04-29 18:00:44.000000000 +0100 @@ -52,7 +52,6 @@ */
void smc_set_mac_addr(const char *addr); -int eth_hw_init(void);
/* I want some simple types */

On Thu, Apr 29, 2004 at 06:02:01PM +0100, Dave Peverley wrote:
Hi all,
This is a small patch for the lan91c96 ethernet driver that adds the capability to automatically detect the MAC address stored in EPROM in the absence of a valid MAC address in the environment. It is modelled on the system used by the smc91111 driver as suggested by Marius Groeger (thanks!)
The patch itself was created against the CVS repository tag "U-Boot-1_1_0" using the command : diff -purN u-boot u-boot-omap730p2 > u-boot-1.1.0-omap730p2.patch
All comments and feedback welcome.
Cool! Thanks for that! I have a minor suggestion though. Can we squelch the warning for the "setenv ethaddr" case? Like so:
--- drivers/lan91c96.c.orig 2004-04-29 13:15:14.000000000 -0400 +++ drivers/lan91c96.c 2004-04-30 15:47:45.000000000 -0400 @@ -886,9 +886,7 @@ uchar v_rom_mac[6];
env_size = getenv_r ("ethaddr", s_env_mac, sizeof (s_env_mac)); - if (env_size != sizeof(es)) { /* Ignore if env is bad or not set */ - printf ("\n*** Warning: ethaddr is not set properly, ignoring!!\n"); - } else { + if (env_size == sizeof(es)) { env_present = 1; s = s_env_mac;
@@ -897,7 +895,8 @@ if (s) s = (*e) ? e + 1 : e; } - } + } else if (env_size >= 0) /* Ignore if env is bad */ + printf ("\n*** Warning: ethaddr is not set properly, ignoring!!\n");
rom_valid = get_rom_mac (v_rom_mac); /* get ROM mac value if any */
I've tested your patch with the above change and it works for me:
OMAP1510 Innovator # bootp Using MAC Address 08:00:28:32:0F:FF BOOTP broadcast 1 DHCP client bound to address 192.168.1.91 OMAP1510 Innovator # setenv ethaddr 00:11:22:33:44 OMAP1510 Innovator # bootp
*** Warning: ethaddr is not set properly, ignoring!! Using MAC Address 08:00:28:32:0F:FF BOOTP broadcast 1 DHCP client bound to address 192.168.1.91 OMAP1510 Innovator # setenv ethaddr OMAP1510 Innovator # bootp Using MAC Address 08:00:28:32:0F:FF BOOTP broadcast 1 DHCP client bound to address 192.168.1.91
Thanks again!
-- Regards, George
Best Wishes,
Dave Peverley
<snip>

George G. Davis wrote:
Cool! Thanks for that!
No porbs :-)
I have a minor suggestion though. Can we squelch the warning for the "setenv ethaddr" case? Like so:
Sure, I have no preference either way. I think I originally put in the warning as I have the impression that Wolfgang's preference is to have the user use the environment to set the MAC address rather than have it detected.
Of course the easiest way to suppress the message is to do a 'bootp' to read teh detected address, and then 'saveenv' to set it permenently. This is perhaps something I should have added to the README?
Best Wishes,
~Pev
--------------------------------------------------------------------------- Dave Peverley, Software Engineer, MPC Data Limited. Phone : [+44] (0) 1225 868 228 Web : http://www.mpc-data.co.uk

In message 409766D3.2030409@mpc-data.co.uk you wrote:
I have a minor suggestion though. Can we squelch the warning for the "setenv ethaddr" case? Like so:
Sure, I have no preference either way. I think I originally put in the warning as I have the impression that Wolfgang's preference is to have the user use the environment to set the MAC address rather than have it detected.
The rules are simple and documented:
o If the SROM has a valid MAC address, and there is no address in the environment, the SROM's address is used.
o If there is no valid address in the SROM, and a definition in the environment exists, then the value from the environment variable is used.
o If both the SROM and the environment contain a MAC address, and both addresses are the same, this MAC address is used.
o If both the SROM and the environment contain a MAC address, and the addresses differ, the value from the environment is used and a warning is printed.
o If neither SROM nor the environment contain a MAC address, an error is raised.
Of course the easiest way to suppress the message is to do a 'bootp' to read teh detected address, and then 'saveenv' to set it permenently.
You cannot use BOOTP (nor ony other network related protocol) to detect a MAC address!!!
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
The rules are simple and documented:
Sure, I've read these...
You cannot use BOOTP (nor ony other network related protocol) to detect a MAC address!!!
I think that either we operate on utterly different brainwave-lengths or theres some kind of language barrier issue here!
If you issue a 'bootp' command to u-boot via its interface as I stated, the following call sequence happens if you're using the lan91c96 (with patch) or smc91111 ethernet devices :
do_bootp() [cmd_net.c] netboot_common() [cmd_net.c] NetLoop() [net.c] eth_init() [lan91c96.c] smc_open() [lan91c96.c] smc_get_ethaddr() [lan91c96.c] get_rom_mac() [lan91c96.c]
So in practical use, issuing a bootp detects the mac address of the adapter.
(nor ony other network related protocol)
Well, the following network related protocol calls : do_tftpb() do_rarpb() do_dhcp() do_nfs() all call netboot_common() so will in effect detect the MAC address as well ;-)
Best Wishes,
Dave Peverley
--------------------------------------------------------------------------- Dave Peverley, Software Engineer, MPC Data Limited. Phone : [+44] (0) 1225 868 228 Web : http://www.mpc-data.co.uk

In message 40978D65.7030805@mpc-data.co.uk you wrote:
You cannot use BOOTP (nor ony other network related protocol) to detect a MAC address!!!
I think that either we operate on utterly different brainwave-lengths or theres some kind of language barrier issue here!
BOOTP is a well-defined protocol which is based on the assumption that you have a network interface that can be used to send and receive packets. To do so, the interface must be initialized. BOOTP does in NO WAY work if your interface does not have a MAC address set. Especially, it does NOT retrieve the MAC address from anywhere.
If you issue a 'bootp' command to u-boot via its interface as I stated, the following call sequence happens if you're using the lan91c96 (with patch) or smc91111 ethernet devices :
do_bootp() [cmd_net.c] netboot_common() [cmd_net.c] NetLoop() [net.c] eth_init() [lan91c96.c]
Stop here. eth_init() performs the initialization of the ethernet interface, if this did not happen before, because an initialized ethernet interface is a precondition to use BOOTP.
So in practical use, issuing a bootp detects the mac address of the adapter.
No, no, no. This is plainly wrong.
Well, the following network related protocol calls : do_tftpb() do_rarpb() do_dhcp() do_nfs() all call netboot_common() so will in effect detect the MAC address as well ;-)
None of these protocols has ato do anything with setting the MAC address. Please don't mix things up.
You could as well claim that bootp sets the baudrate of the serial console, because to run bootp you must execute an initialization sequence which includes the serial port, thus setting the baudrate.
IT AIN'T SO!
Wolfgang Denk

Wolfgang Denk wrote:
If you issue a 'bootp' command to u-boot via its interface as I stated, the following call sequence happens
...
So in practical use, issuing a bootp detects the mac address of the adapter.
No, no, no. This is plainly wrong.
I've tried my best to explain this concisely and with no room for mis-interpretation but I have seemed to fail and I can't see why. I don't think anyone else managed to mis-read me as radically as this, so I've taken this off list to try and clear up with Wolfgang whatever the mixup seems to be. Apologies to all....
Best Wishes,
~Pev
--------------------------------------------------------------------------- Dave Peverley, Software Engineer, MPC Data Limited. Phone : [+44] (0) 1225 868 228 Web : http://www.mpc-data.co.uk

Dear Dave,
in message 40913509.1090309@mpc-data.co.uk you wrote:
This is a small patch for the lan91c96 ethernet driver that adds the capability to automatically detect the MAC address stored in EPROM in the absence of a valid MAC address in the environment. It is modelled on the system used by the smc91111 driver as suggested by Marius Groeger
Added, thanks.
Best regards,
Wolfgang Denk
participants (3)
-
Dave Peverley
-
George G. Davis
-
Wolfgang Denk