svn commit: r224398 - in stable/8/sys/dev/usb: . net

Pyun YongHyeon yongari at FreeBSD.org
Mon Jul 25 20:06:19 UTC 2011


Author: yongari
Date: Mon Jul 25 20:06:18 2011
New Revision: 224398
URL: http://svn.freebsd.org/changeset/base/224398

Log:
  MFC r224020:
    Add initial support for AX88772B USB Fast Ethernet. AX88772B
    supports IPv4/IPv6 checksum offloading and VLAN tag insertion/
    stripping as well as WOL.  Because uether does not provide a way
    to announce driver specific offload capabilities to upper stack,
    checksum offloading support needs more work and will be done in
    future.
    Special thanks to ASIX for donating sample hardware.
  
    H/W donated by:	ASIX Electronics
    Reviewed by:		hselasky

Modified:
  stable/8/sys/dev/usb/net/if_axe.c
  stable/8/sys/dev/usb/net/if_axereg.h
  stable/8/sys/dev/usb/usbdevs
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/geom/label/   (props changed)

Modified: stable/8/sys/dev/usb/net/if_axe.c
==============================================================================
--- stable/8/sys/dev/usb/net/if_axe.c	Mon Jul 25 19:13:51 2011	(r224397)
+++ stable/8/sys/dev/usb/net/if_axe.c	Mon Jul 25 20:06:18 2011	(r224398)
@@ -142,6 +142,7 @@ static const STRUCT_USB_HOST_ID axe_devs
 	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 void	axe_ifmedia_sts(struct ifnet
 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 usb_config axe_confi
 	},
 };
 
+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),
@@ -671,16 +685,11 @@ axe_ax88772_init(struct axe_softc *sc)
 }
 
 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 |
@@ -706,6 +715,55 @@ axe_ax88772a_init(struct axe_softc *sc)
 	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: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);
 }
 
@@ -734,6 +792,8 @@ axe_reset(struct axe_softc *sc)
 		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
@@ -757,29 +817,29 @@ axe_attach_post(struct usb_ether *ue)
 		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;
@@ -1106,18 +1166,30 @@ axe_init(struct usb_ether *ue)
 		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;
 	}

Modified: stable/8/sys/dev/usb/net/if_axereg.h
==============================================================================
--- stable/8/sys/dev/usb/net/if_axereg.h	Mon Jul 25 19:13:51 2011	(r224397)
+++ stable/8/sys/dev/usb/net/if_axereg.h	Mon Jul 25 20:06:18 2011	(r224398)
@@ -96,6 +96,8 @@
 #define	AXE_CMD_READ_VLAN_CTRL			0x4027
 #define	AXE_CMD_WRITE_VLAN_CTRL			0x4028
 
+#define	AXE_772B_CMD_RXCTL_WRITE_CFG		0x012A
+
 #define	AXE_SW_RESET_CLEAR			0x00
 #define	AXE_SW_RESET_RR				0x01
 #define	AXE_SW_RESET_RT				0x02
@@ -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 @@ struct axe_softc {
 
 	uint8_t			sc_ipgs[3];
 	uint8_t			sc_phyaddrs[2];
+	uint16_t		sc_pwrcfg;
 	int			sc_tx_bufsz;
 };
 

Modified: stable/8/sys/dev/usb/usbdevs
==============================================================================
--- stable/8/sys/dev/usb/usbdevs	Mon Jul 25 19:13:51 2011	(r224397)
+++ stable/8/sys/dev/usb/usbdevs	Mon Jul 25 20:06:18 2011	(r224398)
@@ -1043,6 +1043,7 @@ product ASIX AX88172		0x1720	10/100 Ethe
 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


More information about the svn-src-stable-8 mailing list