From owner-freebsd-arm@FreeBSD.ORG Fri Jun 8 18:11:29 2007 Return-Path: X-Original-To: arm@freebsd.org Delivered-To: freebsd-arm@FreeBSD.ORG Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 68A5316A41F for ; Fri, 8 Jun 2007 18:11:29 +0000 (UTC) (envelope-from imp@bsdimp.com) Received: from harmony.bsdimp.com (bsdimp.com [199.45.160.85]) by mx1.freebsd.org (Postfix) with ESMTP id 272C213C4C8 for ; Fri, 8 Jun 2007 18:11:29 +0000 (UTC) (envelope-from imp@bsdimp.com) Received: from localhost (localhost [127.0.0.1]) by harmony.bsdimp.com (8.13.8/8.13.4) with ESMTP id l58I8fuI002567; Fri, 8 Jun 2007 12:08:42 -0600 (MDT) (envelope-from imp@bsdimp.com) Date: Fri, 08 Jun 2007 12:09:02 -0600 (MDT) Message-Id: <20070608.120902.-399284744.imp@bsdimp.com> To: bkoenig@alpha-tierchen.de From: "M. Warner Losh" In-Reply-To: <53385.2001:6f8:101e:0:20e:cff:fe6d:6adb.1181314300.squirrel@webmail.alpha-tierchen.de> References: <53385.2001:6f8:101e:0:20e:cff:fe6d:6adb.1181314300.squirrel@webmail.alpha-tierchen.de> X-Mailer: Mew version 5.2 on Emacs 21.3 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Text/Plain; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-2.0 (harmony.bsdimp.com [127.0.0.1]); Fri, 08 Jun 2007 12:08:42 -0600 (MDT) Cc: arm@freebsd.org Subject: Re: if_ate handles the bytes of the MAC address in a "wrong" order X-BeenThere: freebsd-arm@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Porting FreeBSD to the StrongARM Processor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 08 Jun 2007 18:11:29 -0000 In message: <53385.2001:6f8:101e:0:20e:cff:fe6d:6adb.1181314300.squirre= l@webmail.alpha-tierchen.de> Bj=F6rn_K=F6nig writes: : Hello, : = : while reading code of the at91 ethernet driver (ate) I noticed that i= t : uses an order of the MAC address registers which is not intended by A= tmel. : = : In FreeBSD you typically store the MAC address in an array of six oct= ets, : for example : = : uint8_t eaddr[] =3D { 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/indiv= idual : bit. : = : So far so good. That's the theory. : = : The specification of the Atmel AT91RM9200 controller clearly says : something about how to store the MAC address in the two address regis= ters : (section 36.5.5, page 602). When I read the manual, it was anything but clear. Looks like rev F does add some verbage, but it is still less than clear: There are four 48-bit specific address registers, each taking up two memory locations. The first location contains the first four bytes of the address; the second location contains the last two bytes of the address stored in its least significant byte positions. Ethernet frames are transmitted a byte at a time, LSB first. The first bit ... of the destination address is the group/individual bit ... This bit corresponds to bit 24 of the first word of the specific address register. The MSB of the first byte corresponds to bit 31 of the specific address register. : In fact that the first four bytes : (01:02:03:04) are stored in the low register and the last two bytes : (05:06) in the high register. Furthermore they write that the : group/individual bit corresponds with with bit 24 of the address regi= ster : which means that they really want that you store first byte in the lo= w : register, because bit 24 of the high register is unused. That's indeed what it says. : So the correct code would store the low register in eaddr[0-3] and th= e : 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 =3D RD4(sc, ETH_SA1L); high =3D RD4(sc, ETH_SA1H); if ((low | (high & 0xffff)) =3D=3D 0) return (ENXIO); eaddr[0] =3D (high >> 8) & 0xff; eaddr[1] =3D high & 0xff; eaddr[2] =3D (low >> 24) & 0xff; eaddr[3] =3D (low >> 16) & 0xff; eaddr[4] =3D (low >> 8) & 0xff; eaddr[5] =3D low & 0xff; which does look like it is wrong, based on what the text says. : 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])); 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 =3D (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[= 5]; localMAChigh =3D (mac[0] << 8) | mac[1]; which matches the code I quoted before: eaddr[0] =3D (high >> 8) & 0xff; eaddr[1] =3D high & 0xff; eaddr[2] =3D (low >> 24) & 0xff; eaddr[3] =3D (low >> 16) & 0xff; eaddr[4] =3D (low >> 8) & 0xff; eaddr[5] =3D 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=3D8843 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 :-(. Warner