Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Jul 2011 17:05:41 -0700
From:      YongHyeon PYUN <pyunyh@gmail.com>
To:        Andrey Smagin <samspeed@mail.ru>
Cc:        freebsd-current@freebsd.org
Subject:   Re: AX88772A AX88772B chipset differences?
Message-ID:  <20110713000541.GC7564@michelle.cdnetworks.com>
In-Reply-To: <20110630171914.GA12124@michelle.cdnetworks.com>
References:  <E1QcEjo-0005Zh-00.samspeed-mail-ru@f287.mail.ru> <20110630171914.GA12124@michelle.cdnetworks.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--2oS5YaxWCcQjTEyO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Thu, Jun 30, 2011 at 10:19:14AM -0700, YongHyeon PYUN wrote:
> On Thu, Jun 30, 2011 at 02:44:48PM +0400, Andrey Smagin wrote:
> > I have card based on AX88772B. I tried patch axe driver for vendor and device IDs. card detected, set up link, but no data received. What else need for patch in  this driver ? Anybody have datasheet ?
> 
> ASIX requires a login account to get the data sheet so it's not
> publicly available to open source developers.
> AFAIK the difference between AX88772A and AX88772B is IPv4/IPv6
> checksum offloading support of AX88772B. The introduction of
> checksum offloading means they might have changed its RX header
> format which in turn makes current RX handler to not work.  The
> other difference would be more advanced power saving used in
> AX8877B but it wouldn't be much difference to axe(4) driver once
> PHY is correctly woken in initialization phase.
> Could you show me your diff and verbose boot output to know PHY
> model and EEPROM data?

I have a minimal patch for AX88772B. It requires more work to
support TX/RX checksum offloading, flow-control and power saving
but attached patch would be enough for most cases.
Let me know whether it works or not.

--2oS5YaxWCcQjTEyO
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="axe.88772B.diff"

Index: sys/dev/usb/usbdevs
===================================================================
--- sys/dev/usb/usbdevs	(revision 223958)
+++ sys/dev/usb/usbdevs	(working copy)
@@ -1045,6 +1045,7 @@
 product ASIX AX88178		0x1780	AX88178
 product ASIX AX88772		0x7720	AX88772
 product ASIX AX88772A		0x772a	AX88772A USB 2.0 10/100 Ethernet
+product ASIX AX88772B		0x772b	AX88772B USB 2.0 10/100 Ethernet
 
 /* ASUS products */
 product ASUS2 USBN11		0x0b05	USB-N11
Index: sys/dev/usb/net/if_axereg.h
===================================================================
--- sys/dev/usb/net/if_axereg.h	(revision 223958)
+++ sys/dev/usb/net/if_axereg.h	(working copy)
@@ -92,6 +92,8 @@
 #define	AXE_CMD_SW_PHY_STATUS			0x0021
 #define	AXE_CMD_SW_PHY_SELECT			0x0122
 
+#define	AXE_772B_CMD_RXCTL_WRITE_CFG		0x012A
+
 /* AX88772A and AX88772B only. */
 #define	AXE_CMD_READ_VLAN_CTRL			0x4027
 #define	AXE_CMD_WRITE_VLAN_CTRL			0x4028
@@ -132,12 +134,18 @@
 #define	AXE_178_RXCMD_KEEP_INVALID_CRC		0x0004
 #define	AXE_RXCMD_BROADCAST			0x0008
 #define	AXE_RXCMD_MULTICAST			0x0010
+#define	AXE_RXCMD_ACCEPT_RUNT			0x0040	/* AX88772B */
 #define	AXE_RXCMD_ENABLE			0x0080
 #define	AXE_178_RXCMD_MFB_MASK			0x0300
 #define	AXE_178_RXCMD_MFB_2048			0x0000
 #define	AXE_178_RXCMD_MFB_4096			0x0100
 #define	AXE_178_RXCMD_MFB_8192			0x0200
 #define	AXE_178_RXCMD_MFB_16384			0x0300
+#define	AXE_772B_RXCMD_HDR_TYPE_0		0x0000
+#define	AXE_772B_RXCMD_HDR_TYPE_1		0x0100
+#define	AXE_772B_RXCMD_IPHDR_ALIGN		0x0200
+#define	AXE_772B_RXCMD_ADD_CHKSUM		0x0400
+#define	AXE_RXCMD_LOOPBACK			0x1000	/* AX88772A/AX88772B */
 
 #define	AXE_PHY_SEL_PRI		1
 #define	AXE_PHY_SEL_SEC		0
@@ -176,7 +184,7 @@
 #define	AXE_PHY_MODE_REALTEK_8251CL	0x0E
 #define	AXE_PHY_MODE_ATTANSIC		0x40
 
-/* AX88772A only. */
+/* AX88772A/AX88772B only. */
 #define	AXE_SW_PHY_SELECT_EXT		0x0000
 #define	AXE_SW_PHY_SELECT_EMBEDDED	0x0001
 #define	AXE_SW_PHY_SELECT_AUTO		0x0002
@@ -199,6 +207,24 @@
 #define	AXE_CONFIG_IDX		0	/* config number 1 */
 #define	AXE_IFACE_IDX		0
 
+/* EEPROM Map. */
+#define	AXE_EEPROM_772B_NODE_ID		0x04
+#define	AXE_EEPROM_772B_PHY_PWRCFG	0x18
+
+struct ax88772b_mfb {
+	int	byte_cnt;
+	int	threshold;
+	int	size;
+};
+#define	AX88772B_MFB_2K		0
+#define	AX88772B_MFB_4K		1
+#define	AX88772B_MFB_6K		2
+#define	AX88772B_MFB_8K		3
+#define	AX88772B_MFB_16K	4
+#define	AX88772B_MFB_20K	5
+#define	AX88772B_MFB_24K	6
+#define	AX88772B_MFB_32K	7
+
 struct axe_sframe_hdr {
 	uint16_t len;
 	uint16_t ilen;
@@ -228,6 +254,7 @@
 
 	uint8_t			sc_ipgs[3];
 	uint8_t			sc_phyaddrs[2];
+	uint16_t		sc_pwrcfg;
 	int			sc_tx_bufsz;
 };
 
Index: sys/dev/usb/net/if_axe.c
===================================================================
--- sys/dev/usb/net/if_axe.c	(revision 223958)
+++ sys/dev/usb/net/if_axe.c	(working copy)
@@ -142,6 +142,7 @@
 	AXE_DEV(ASIX, AX88178, AXE_FLAG_178),
 	AXE_DEV(ASIX, AX88772, AXE_FLAG_772),
 	AXE_DEV(ASIX, AX88772A, AXE_FLAG_772A),
+	AXE_DEV(ASIX, AX88772B, AXE_FLAG_772B),
 	AXE_DEV(ATEN, UC210T, 0),
 	AXE_DEV(BELKIN, F5D5055, AXE_FLAG_178),
 	AXE_DEV(BILLIONTON, USB2AR, 0),
@@ -190,7 +191,9 @@
 static int	axe_cmd(struct axe_softc *, int, int, int, void *);
 static void	axe_ax88178_init(struct axe_softc *);
 static void	axe_ax88772_init(struct axe_softc *);
+static void	axe_ax88772_phywake(struct axe_softc *);
 static void	axe_ax88772a_init(struct axe_softc *);
+static void	axe_ax88772b_init(struct axe_softc *);
 static int	axe_get_phyno(struct axe_softc *, int);
 
 static const struct usb_config axe_config[AXE_N_TRANSFER] = {
@@ -217,6 +220,17 @@
 	},
 };
 
+static const struct ax88772b_mfb ax88772b_mfb_table[] = {
+	{ 0x8000, 0x8001, 2048 },
+        { 0x8100, 0x8147, 4096},
+        { 0x8200, 0x81EB, 6144},
+        { 0x8300, 0x83D7, 8192},
+        { 0x8400, 0x851E, 16384},
+        { 0x8500, 0x8666, 20480},
+        { 0x8600, 0x87AE, 24576},
+        { 0x8700, 0x8A3D, 32768}
+};
+
 static device_method_t axe_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe, axe_probe),
@@ -669,16 +683,11 @@
 }
 
 static void
-axe_ax88772a_init(struct axe_softc *sc)
+axe_ax88772_phywake(struct axe_softc *sc)
 {
 	struct usb_ether *ue;
-	uint16_t eeprom;
 
 	ue = &sc->sc_ue;
-	axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom);
-	eeprom = le16toh(eeprom);
-	/* Reload EEPROM. */
-	AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM, hz / 32);
 	if (sc->sc_phyno == AXE_772_PHY_NO_EPHY) {
 		/* Manually select internal(embedded) PHY - MAC mode. */
 		axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, AXE_SW_PHY_SELECT_SS_ENB |
@@ -704,9 +713,58 @@
 	uether_pause(&sc->sc_ue, hz / 32);
 	axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_IPRL, NULL);
 	uether_pause(&sc->sc_ue, hz / 32);
+}
+
+static void
+axe_ax88772a_init(struct axe_softc *sc)
+{
+	struct usb_ether *ue;
+
+	ue = &sc->sc_ue;
+	/* Reload EEPROM. */
+	AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM, hz / 32);
+	axe_ax88772_phywake(sc);
+	/* Stop MAC. */
 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
 }
 
+static void
+axe_ax88772b_init(struct axe_softc *sc)
+{
+	struct usb_ether *ue;
+	uint16_t eeprom;
+	uint8_t *eaddr;
+	int i;
+
+	ue = &sc->sc_ue;
+	/* Reload EEPROM. */
+	AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM, hz / 32);
+	/*
+	 * Save PHY power saving configuration(high byte) and
+	 * clear EEPROM checksum value(low byte).
+	 */
+	axe_cmd(sc, AXE_CMD_SROM_READ, 0, AXE_EEPROM_772B_PHY_PWRCFG, &eeprom);
+	sc->sc_pwrcfg = le16toh(eeprom) & 0xFF00;
+
+	/*
+	 * Auto-loaded default station address from internal ROM is
+	 * 00:00:00:00:00 such that an explicit access to EEPROM is
+	 * required to get real station address.
+	 */
+	eaddr = ue->ue_eaddr;
+	for (i = 0; i < ETHER_ADDR_LEN / 2; i++) {
+		axe_cmd(sc, AXE_CMD_SROM_READ, 0, AXE_EEPROM_772B_NODE_ID + i,
+		    &eeprom);
+		eeprom = le16toh(eeprom);
+		*eaddr++ = (uint8_t)(eeprom & 0xFF);
+		*eaddr++ = (uint8_t)((eeprom >> 8) & 0xFF);
+	}
+	/* Wakeup PHY. */
+	axe_ax88772_phywake(sc);
+	/* Stop MAC. */
+	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
+}
+
 #undef	AXE_GPIO_WRITE
 
 static void
@@ -732,6 +790,8 @@
 		axe_ax88772_init(sc);
 	else if (sc->sc_flags & AXE_FLAG_772A)
 		axe_ax88772a_init(sc);
+	else if (sc->sc_flags & AXE_FLAG_772B)
+		axe_ax88772b_init(sc);
 }
 
 static void
@@ -755,29 +815,29 @@
 		sc->sc_phyno = 0;
 	}
 
+	/* Initialize controller and get station address. */
 	if (sc->sc_flags & AXE_FLAG_178) {
 		axe_ax88178_init(sc);
 		sc->sc_tx_bufsz = 16 * 1024;
+		axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, ue->ue_eaddr);
 	} else if (sc->sc_flags & AXE_FLAG_772) {
 		axe_ax88772_init(sc);
 		sc->sc_tx_bufsz = 8 * 1024;
+		axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, ue->ue_eaddr);
 	} else if (sc->sc_flags & AXE_FLAG_772A) {
 		axe_ax88772a_init(sc);
 		sc->sc_tx_bufsz = 8 * 1024;
-	}
-
-	/*
-	 * Get station address.
-	 */
-	if (AXE_IS_178_FAMILY(sc))
 		axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, ue->ue_eaddr);
-	else
+	} else if (sc->sc_flags & AXE_FLAG_772B) {
+		axe_ax88772b_init(sc);
+		sc->sc_tx_bufsz = 8 * 1024;
+	} else
 		axe_cmd(sc, AXE_172_CMD_READ_NODEID, 0, 0, ue->ue_eaddr);
 
 	/*
 	 * Fetch IPG values.
 	 */
-	if (sc->sc_flags & AXE_FLAG_772A) {
+	if (sc->sc_flags & (AXE_FLAG_772A | AXE_FLAG_772B)) {
 		/* Set IPG values. */
 		sc->sc_ipgs[0] = 0x15;
 		sc->sc_ipgs[1] = 0x16;
@@ -1104,18 +1164,30 @@
 		axe_cmd(sc, AXE_172_CMD_WRITE_IPG2, 0, sc->sc_ipgs[2], NULL);
 	}
 
-	/* Enable receiver, set RX mode */
+	/* AX88772B uses different maximum frame burst configuration. */
+	if (sc->sc_flags & AXE_FLAG_772B)
+		axe_cmd(sc, AXE_772B_CMD_RXCTL_WRITE_CFG,
+		    ax88772b_mfb_table[AX88772B_MFB_16K].threshold,
+		    ax88772b_mfb_table[AX88772B_MFB_16K].byte_cnt, NULL);
+
+	/* Enable receiver, set RX mode. */
 	rxmode = (AXE_RXCMD_MULTICAST | AXE_RXCMD_ENABLE);
 	if (AXE_IS_178_FAMILY(sc)) {
-#if 0
-		rxmode |= AXE_178_RXCMD_MFB_2048;	/* chip default */
-#else
-		/*
-		 * Default Rx buffer size is too small to get
-		 * maximum performance.
-		 */
-		rxmode |= AXE_178_RXCMD_MFB_16384;
-#endif
+		if (sc->sc_flags & AXE_FLAG_772B) {
+			/*
+			 * Select RX header format type 1.  Aligning IP
+			 * header on 4 byte boundary is not needed
+			 * because we always copy the received frame in
+			 * RX handler.
+			 */
+			rxmode |= AXE_772B_RXCMD_HDR_TYPE_1;
+		} else {
+			/*
+			 * Default Rx buffer size is too small to get
+			 * maximum performance.
+			 */
+			rxmode |= AXE_178_RXCMD_MFB_16384;
+		}
 	} else {
 		rxmode |= AXE_172_RXCMD_UNICAST;
 	}

--2oS5YaxWCcQjTEyO--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20110713000541.GC7564>