if_ate handles the bytes of the MAC address in a "wrong" order

Bernd Walter ticso at cicely12.cicely.de
Fri Jun 8 22:59:29 UTC 2007


On Fri, Jun 08, 2007 at 12:09:02PM -0600, M. Warner Losh wrote:
> In message: <53385.2001:6f8:101e:0:20e:cff:fe6d:6adb.1181314300.squirrel at webmail.alpha-tierchen.de>
>             Björn_König <bkoenig at alpha-tierchen.de> writes:
> : Hello,
> : 
> : while reading code of the at91 ethernet driver (ate) I noticed that it
> : uses an order of the MAC address registers which is not intended by Atmel.
> : 
> : In FreeBSD you typically store the MAC address in an array of six octets,
> : for example
> : 
> :   uint8_t eaddr[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
> : 
> : which will be represented as 01:02:03:04:05:06 (transmission order) . 0x01
> : is the most significant byte and 0x06 the least significant byte. The
> : least significant bit of the most significant byte is the group/individual
> : bit.

Ethernet is little endian.
0x01 is the first byte to be transmitted and it is done in 1000000
order.
For my understanding 0x01 is the _least_ significant byte.

> : So the correct code would store the low register in eaddr[0-3] and the
> : high register in eaddr[4-5], but actually the ate_get_mac function in
> : src/sys/arm/at91/if_ate.c uses another order.
> 
> We use the following code:
> 	low = RD4(sc, ETH_SA1L);
> 	high =  RD4(sc, ETH_SA1H);
> 	if ((low | (high & 0xffff)) == 0)
> 		return (ENXIO);
> 	eaddr[0] = (high >> 8) & 0xff;
> 	eaddr[1] = high & 0xff;
> 	eaddr[2] = (low >> 24) & 0xff;
> 	eaddr[3] = (low >> 16) & 0xff;
> 	eaddr[4] = (low >> 8) & 0xff;
> 	eaddr[5] = low & 0xff;

> which does look like it is wrong, based on what the text says.

Yes - this doesn't look right.

> : This won't hurt as long as you use a loader that stores the bytes the same
> : way as the driver read them. I wouldn't care if I wouldn't have this
> : problem: Linux and the U-Boot loader stores the bytes it in a manner that
> : is different from the FreeBSD method and also different from Atmel's
> : suggestion.
> 
> I see the problem.  There's a disconnect between the above code and
> the set code:
> 
> 	WR4(sc, ETH_SA1L, (eaddr[3] << 24) | (eaddr[2] << 16) |
> 	    (eaddr[1] << 8) | eaddr[0]);
> 	WR4(sc, ETH_SA1H, (eaddr[5] << 8) | (eaddr[4]));

Interesting - this shuffles the order.
And this seems to work, since I get proper data when tcpdump'ing
the traffic on another host.
This sounds like this is the only correct order used.
It also matches with the datasheet, with 0x01 beeing the least
significant byte.

> which is different still than the document says, which is, if I'm
> reading it right:
> 
> 	WR4(sc, ETH_SA1L, (eaddr[0] << 24) | (eaddr[1] << 16) |
> 	    (eaddr[2] << 8) | eaddr[3]);
> 	WR4(sc, ETH_SA1H, (eaddr[4] << 8) | (eaddr[5]));
> 
> : What do you think?
> 
> I'll investigate.  However, the order that they are stored in comes
> from a boot loader that was emulating redboot and able to boot Linux.
> If the MAC address is wrong, the ARP won't work since it is used to
> process the incoming MAC address.  I don't think that the boot
> loader's tftp function would work right with the bad address.  But to
> be honest, that address doesn't have the be right, just consistent.  I
> don't recall doing an arp -n on the server to see what's what.
> 
> Looking at the boot code, we see:
> 
> 	localMAClow = (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5];
> 	localMAChigh = (mac[0] << 8) | mac[1];
> 
> which matches the code I quoted before:
> 
> 	eaddr[0] = (high >> 8) & 0xff;
> 	eaddr[1] = high & 0xff;
> 	eaddr[2] = (low >> 24) & 0xff;
> 	eaddr[3] = (low >> 16) & 0xff;
> 	eaddr[4] = (low >> 8) & 0xff;
> 	eaddr[5] = low & 0xff;
> 
> which is why we get the 'right' MAC on the probe line:
> 
> ate0: Ethernet address: 00:30:96:00:00:07
> 
> And on one of the units I have up, I see:
> 
> ate0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
>         inet 206.168.13.132 netmask 0xffffff80 broadcast 206.168.13.255
>         ether 00:30:96:00:00:07
> 
> and on the other end of my telnet connection I see:
> 
> ? (206.168.13.132) at 00:30:96:00:00:07 on bge0 [ethernet]
> 
> from arp.
> 
> Time for pencil and paper to see why this all works :-(.

It looks like the documentation is wrong and the shuffling fixes
it.
bootcode TFTP with the wrong address will work by automatic ARP
learning on the tftp-server - I don't asume that the tftp-server will
send any ARP-request.

-- 
B.Walter                http://www.bwct.de      http://www.fizon.de
bernd at bwct.de           info at bwct.de            support at fizon.de


More information about the freebsd-arm mailing list