Author: yongari
Date: Thu Jul 14 17:19:00 2011
New Revision: 224020
URL: http://svn.freebsd.org/changeset/base/224020

Log:
  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:
  head/sys/dev/usb/net/if_axe.c
  head/sys/dev/usb/net/if_axereg.h
  head/sys/dev/usb/usbdevs

Modified: head/sys/dev/usb/net/if_axe.c
==============================================================================
--- head/sys/dev/usb/net/if_axe.c       Thu Jul 14 15:35:43 2011        
(r224019)
+++ head/sys/dev/usb/net/if_axe.c       Thu Jul 14 17:19:00 2011        
(r224020)
@@ -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),
@@ -669,16 +683,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 |
@@ -704,6 +713,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);
 }
 
@@ -732,6 +790,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
@@ -755,29 +815,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;
@@ -1104,18 +1164,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: head/sys/dev/usb/net/if_axereg.h
==============================================================================
--- head/sys/dev/usb/net/if_axereg.h    Thu Jul 14 15:35:43 2011        
(r224019)
+++ head/sys/dev/usb/net/if_axereg.h    Thu Jul 14 17:19:00 2011        
(r224020)
@@ -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: head/sys/dev/usb/usbdevs
==============================================================================
--- head/sys/dev/usb/usbdevs    Thu Jul 14 15:35:43 2011        (r224019)
+++ head/sys/dev/usb/usbdevs    Thu Jul 14 17:19:00 2011        (r224020)
@@ -1045,6 +1045,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
_______________________________________________
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-unsubscr...@freebsd.org"

Reply via email to