Bug 188177

Summary: ADMtek USB To LAN Converter does not work
Product: Base System Reporter: josla972
Component: powerpcAssignee: Pyun YongHyeon <yongari>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 10.0-RELEASE   
Hardware: Any   
OS: Any   

Description josla972 2014-04-01 20:40:00 UTC
(About the uname -a output: I use an experimental kernel where I tried using aue as a module instead. The problem is also present with the GENERIC kernel.)

I'm having problems with my ADMtek USB ethernet adapter on my Mac Mini G4 (PowerPC). It works flawlessly on the raspberry pi. The driver is detected on the Mac Mini but I cannot use it, even ping does not work. Comparing the MAC addresses, it seems that there might be an endian issue.

Device (dmesg output):

aue0: <ADMtek USB To LAN Converter, rev 2.00/1.01, addr 5> on usbus0
miibus1: <MII bus> on aue0

Mac mini:

ue0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=80000<LINKSTATE>
        ether 05:00:05:1b:b4:28
        inet 192.168.0.8 netmask 0xffffff00 broadcast 192.168.0.255
        inet6 fe80::20d:93ff:fe60:fc1c%ue0 prefixlen 64 scopeid 0x3
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet autoselect (100baseTX <full-duplex>)
        status: active

raspberry pi (FreeBSD fbsdpi 10.0-CURRENT FreeBSD 10.0-CURRENT #9 r250604M: Mon May 13 21:20:03 CEST 2013):

ue1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=80000<LINKSTATE>
        ether 00:05:1b:05:28:b4
        inet ***.***.***.*** netmask 0xffffff00 broadcast ***.***.***.***
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
        media: Ethernet autoselect (100baseTX <full-duplex>)
        status: active

Fix: 

I am unsure about a fix, but at least I did some investigation:

If I interpreted the code correctly, the MAC address is read from eeprom as 3 words which are then saved contiguously in memory.

In the following function there is an interesting line:
static uint16_t aue_csr_read_2(struct aue_softc *sc, uint16_t reg)

return (le16toh(val));

This is probably correct if we can guarantee that the earlier function call uether_do_request(&sc->sc_ue, &req, &val, 1000); results in a value that comes in little endian form, but is this necessarily the case? I think the USB standard uses little endian form, but I am not sure if this is compensated for by the USB stack.

Maybe I am looking at the wrong things, but I still do find it peculiar that the MAC adresses differs when I use ifconfig.
How-To-Repeat: I guess you would need a similar USB ethernet adapter and a powerpc to reproduce it.
Comment 1 Pyun YongHyeon freebsd_committer freebsd_triage 2014-04-02 05:51:35 UTC
State Changed
From-To: open->feedback

Would you try the patch at the following URL? 
http://people.freebsd.org/~yongari/aue/aue.endianness.diff 


Comment 2 Pyun YongHyeon freebsd_committer freebsd_triage 2014-04-02 05:51:35 UTC
Responsible Changed
From-To: freebsd-ppc->yongari

Grab.
Comment 3 josef.lar 2014-04-02 16:41:23 UTC
It works! I did a similar easy fix just to test after I reported the bug
and got it working, but this code is nicer. Thanks!
Comment 4 dfilter service freebsd_committer freebsd_triage 2014-04-03 02:32:47 UTC
Author: yongari
Date: Thu Apr  3 01:32:43 2014
New Revision: 264062
URL: http://svnweb.freebsd.org/changeset/base/264062

Log:
  Correct endianness handling in getting station address from EEPROM.
  While I'm here, remove aue_eeprom_getword() as its only usage is to
  read station address and make it more readable.  This change is
  inspired by NetBSD.
  With this change, aue(4) should work on big endian architectures.
  
  PR:	188177

Modified:
  head/sys/dev/usb/net/if_aue.c

Modified: head/sys/dev/usb/net/if_aue.c
==============================================================================
--- head/sys/dev/usb/net/if_aue.c	Thu Apr  3 01:02:14 2014	(r264061)
+++ head/sys/dev/usb/net/if_aue.c	Thu Apr  3 01:32:43 2014	(r264062)
@@ -212,9 +212,7 @@ static uint8_t	aue_csr_read_1(struct aue
 static uint16_t	aue_csr_read_2(struct aue_softc *, uint16_t);
 static void	aue_csr_write_1(struct aue_softc *, uint16_t, uint8_t);
 static void	aue_csr_write_2(struct aue_softc *, uint16_t, uint16_t);
-static void	aue_eeprom_getword(struct aue_softc *, int, uint16_t *);
-static void	aue_read_eeprom(struct aue_softc *, uint8_t *, uint16_t,
-		    uint16_t);
+static uint16_t	aue_eeprom_getword(struct aue_softc *, int);
 static void	aue_reset(struct aue_softc *);
 static void	aue_reset_pegasus_II(struct aue_softc *);
 
@@ -376,11 +374,10 @@ aue_csr_write_2(struct aue_softc *sc, ui
 /*
  * Read a word of data stored in the EEPROM at address 'addr.'
  */
-static void
-aue_eeprom_getword(struct aue_softc *sc, int addr, uint16_t *dest)
+static uint16_t
+aue_eeprom_getword(struct aue_softc *sc, int addr)
 {
 	int i;
-	uint16_t word = 0;
 
 	aue_csr_write_1(sc, AUE_EE_REG, addr);
 	aue_csr_write_1(sc, AUE_EE_CTL, AUE_EECTL_READ);
@@ -395,22 +392,23 @@ aue_eeprom_getword(struct aue_softc *sc,
 	if (i == AUE_TIMEOUT)
 		device_printf(sc->sc_ue.ue_dev, "EEPROM read timed out\n");
 
-	word = aue_csr_read_2(sc, AUE_EE_DATA);
-	*dest = word;
+	return (aue_csr_read_2(sc, AUE_EE_DATA));
 }
 
 /*
- * Read a sequence of words from the EEPROM.
+ * Read station address(offset 0) from the EEPROM.
  */
 static void
-aue_read_eeprom(struct aue_softc *sc, uint8_t *dest,
-    uint16_t off, uint16_t len)
+aue_read_mac(struct aue_softc *sc, uint8_t *eaddr)
 {
-	uint16_t *ptr = (uint16_t *)dest;
-	int i;
+	int i, offset;
+	uint16_t word;
 
-	for (i = 0; i != len; i++, ptr++)
-		aue_eeprom_getword(sc, off + i, ptr);
+	for (i = 0, offset = 0; i < ETHER_ADDR_LEN / 2; i++) {
+		word = aue_eeprom_getword(sc, offset + i);
+		eaddr[i * 2] = (uint8_t)word;
+		eaddr[i * 2 + 1] = (uint8_t)(word >> 8);
+	}
 }
 
 static int
@@ -636,7 +634,7 @@ aue_attach_post(struct usb_ether *ue)
 	aue_reset(sc);
 
 	/* get station address from the EEPROM */
-	aue_read_eeprom(sc, ue->ue_eaddr, 0, 3);
+	aue_read_mac(sc, ue->ue_eaddr);
 }
 
 /*
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 5 Pyun YongHyeon freebsd_committer freebsd_triage 2014-04-03 02:32:52 UTC
State Changed
From-To: feedback->patched

Thanks for testing! 
Fixed in r264062.
Comment 6 dfilter service freebsd_committer freebsd_triage 2014-04-22 05:30:30 UTC
Author: yongari
Date: Tue Apr 22 04:30:24 2014
New Revision: 264745
URL: http://svnweb.freebsd.org/changeset/base/264745

Log:
  MFC r264062:
    Correct endianness handling in getting station address from EEPROM.
    While I'm here, remove aue_eeprom_getword() as its only usage is to
    read station address and make it more readable.  This change is
    inspired by NetBSD.
    With this change, aue(4) should work on big endian architectures.
  
    PR:	188177

Modified:
  stable/10/sys/dev/usb/net/if_aue.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/usb/net/if_aue.c
==============================================================================
--- stable/10/sys/dev/usb/net/if_aue.c	Mon Apr 21 22:52:18 2014	(r264744)
+++ stable/10/sys/dev/usb/net/if_aue.c	Tue Apr 22 04:30:24 2014	(r264745)
@@ -208,9 +208,7 @@ static uint8_t	aue_csr_read_1(struct aue
 static uint16_t	aue_csr_read_2(struct aue_softc *, uint16_t);
 static void	aue_csr_write_1(struct aue_softc *, uint16_t, uint8_t);
 static void	aue_csr_write_2(struct aue_softc *, uint16_t, uint16_t);
-static void	aue_eeprom_getword(struct aue_softc *, int, uint16_t *);
-static void	aue_read_eeprom(struct aue_softc *, uint8_t *, uint16_t,
-		    uint16_t);
+static uint16_t	aue_eeprom_getword(struct aue_softc *, int);
 static void	aue_reset(struct aue_softc *);
 static void	aue_reset_pegasus_II(struct aue_softc *);
 
@@ -372,11 +370,10 @@ aue_csr_write_2(struct aue_softc *sc, ui
 /*
  * Read a word of data stored in the EEPROM at address 'addr.'
  */
-static void
-aue_eeprom_getword(struct aue_softc *sc, int addr, uint16_t *dest)
+static uint16_t
+aue_eeprom_getword(struct aue_softc *sc, int addr)
 {
 	int i;
-	uint16_t word = 0;
 
 	aue_csr_write_1(sc, AUE_EE_REG, addr);
 	aue_csr_write_1(sc, AUE_EE_CTL, AUE_EECTL_READ);
@@ -391,22 +388,23 @@ aue_eeprom_getword(struct aue_softc *sc,
 	if (i == AUE_TIMEOUT)
 		device_printf(sc->sc_ue.ue_dev, "EEPROM read timed out\n");
 
-	word = aue_csr_read_2(sc, AUE_EE_DATA);
-	*dest = word;
+	return (aue_csr_read_2(sc, AUE_EE_DATA));
 }
 
 /*
- * Read a sequence of words from the EEPROM.
+ * Read station address(offset 0) from the EEPROM.
  */
 static void
-aue_read_eeprom(struct aue_softc *sc, uint8_t *dest,
-    uint16_t off, uint16_t len)
+aue_read_mac(struct aue_softc *sc, uint8_t *eaddr)
 {
-	uint16_t *ptr = (uint16_t *)dest;
-	int i;
+	int i, offset;
+	uint16_t word;
 
-	for (i = 0; i != len; i++, ptr++)
-		aue_eeprom_getword(sc, off + i, ptr);
+	for (i = 0, offset = 0; i < ETHER_ADDR_LEN / 2; i++) {
+		word = aue_eeprom_getword(sc, offset + i);
+		eaddr[i * 2] = (uint8_t)word;
+		eaddr[i * 2 + 1] = (uint8_t)(word >> 8);
+	}
 }
 
 static int
@@ -632,7 +630,7 @@ aue_attach_post(struct usb_ether *ue)
 	aue_reset(sc);
 
 	/* get station address from the EEPROM */
-	aue_read_eeprom(sc, ue->ue_eaddr, 0, 3);
+	aue_read_mac(sc, ue->ue_eaddr);
 }
 
 /*
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 7 dfilter service freebsd_committer freebsd_triage 2014-04-22 05:31:12 UTC
Author: yongari
Date: Tue Apr 22 04:31:07 2014
New Revision: 264746
URL: http://svnweb.freebsd.org/changeset/base/264746

Log:
  MFC r264062:
    Correct endianness handling in getting station address from EEPROM.
    While I'm here, remove aue_eeprom_getword() as its only usage is to
    read station address and make it more readable.  This change is
    inspired by NetBSD.
    With this change, aue(4) should work on big endian architectures.
  
    PR:	188177

Modified:
  stable/9/sys/dev/usb/net/if_aue.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/dev/   (props changed)

Modified: stable/9/sys/dev/usb/net/if_aue.c
==============================================================================
--- stable/9/sys/dev/usb/net/if_aue.c	Tue Apr 22 04:30:24 2014	(r264745)
+++ stable/9/sys/dev/usb/net/if_aue.c	Tue Apr 22 04:31:07 2014	(r264746)
@@ -208,9 +208,7 @@ static uint8_t	aue_csr_read_1(struct aue
 static uint16_t	aue_csr_read_2(struct aue_softc *, uint16_t);
 static void	aue_csr_write_1(struct aue_softc *, uint16_t, uint8_t);
 static void	aue_csr_write_2(struct aue_softc *, uint16_t, uint16_t);
-static void	aue_eeprom_getword(struct aue_softc *, int, uint16_t *);
-static void	aue_read_eeprom(struct aue_softc *, uint8_t *, uint16_t,
-		    uint16_t);
+static uint16_t	aue_eeprom_getword(struct aue_softc *, int);
 static void	aue_reset(struct aue_softc *);
 static void	aue_reset_pegasus_II(struct aue_softc *);
 
@@ -372,11 +370,10 @@ aue_csr_write_2(struct aue_softc *sc, ui
 /*
  * Read a word of data stored in the EEPROM at address 'addr.'
  */
-static void
-aue_eeprom_getword(struct aue_softc *sc, int addr, uint16_t *dest)
+static uint16_t
+aue_eeprom_getword(struct aue_softc *sc, int addr)
 {
 	int i;
-	uint16_t word = 0;
 
 	aue_csr_write_1(sc, AUE_EE_REG, addr);
 	aue_csr_write_1(sc, AUE_EE_CTL, AUE_EECTL_READ);
@@ -391,22 +388,23 @@ aue_eeprom_getword(struct aue_softc *sc,
 	if (i == AUE_TIMEOUT)
 		device_printf(sc->sc_ue.ue_dev, "EEPROM read timed out\n");
 
-	word = aue_csr_read_2(sc, AUE_EE_DATA);
-	*dest = word;
+	return (aue_csr_read_2(sc, AUE_EE_DATA));
 }
 
 /*
- * Read a sequence of words from the EEPROM.
+ * Read station address(offset 0) from the EEPROM.
  */
 static void
-aue_read_eeprom(struct aue_softc *sc, uint8_t *dest,
-    uint16_t off, uint16_t len)
+aue_read_mac(struct aue_softc *sc, uint8_t *eaddr)
 {
-	uint16_t *ptr = (uint16_t *)dest;
-	int i;
+	int i, offset;
+	uint16_t word;
 
-	for (i = 0; i != len; i++, ptr++)
-		aue_eeprom_getword(sc, off + i, ptr);
+	for (i = 0, offset = 0; i < ETHER_ADDR_LEN / 2; i++) {
+		word = aue_eeprom_getword(sc, offset + i);
+		eaddr[i * 2] = (uint8_t)word;
+		eaddr[i * 2 + 1] = (uint8_t)(word >> 8);
+	}
 }
 
 static int
@@ -632,7 +630,7 @@ aue_attach_post(struct usb_ether *ue)
 	aue_reset(sc);
 
 	/* get station address from the EEPROM */
-	aue_read_eeprom(sc, ue->ue_eaddr, 0, 3);
+	aue_read_mac(sc, ue->ue_eaddr);
 }
 
 /*
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 8 Pyun YongHyeon freebsd_committer freebsd_triage 2014-04-22 05:42:00 UTC
State Changed
From-To: patched->closed

MFC to both stable/10 and stable/9 complete. 
Thanks for reporting!