tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Another update for axe(4)



On Sun, 13 Jun 2010, Izumi Tsutsui wrote:

My changes (for -current as of today) are attached.  (I still need to
update the axe(4) man page.)

Comments about only cosmetics:

Thanks - I apprecaite all the feedback. Please see my responses in-line.

I have attached updated diffs based on your feedback. (I have also added diffs for the axe(4) man page!)

+#include <machine/bus.h>

We should use <sys/bus.h> nowadays,
but is this one actually required?

Yes, it is really needed. I need to include usb/usbdivar.h to get the usb speed data, and usbdivar.h references bus_dma_tag_t. I have changed it to use <sys/bus.h>

+#ifdef __NetBSD__
+ #define letoh16 htole16
+ #define letoh32 htole32
+#endif

I don't like these ifdefs.
We have had own le16toh(9) and le32toh(9) and
OpenBSD guys renamed them when they pulled them.

Yeah, I didn't like them either. I just grabbed the #defines from another driver that did the same thing. I'll remove the #defines and use the proper le16toh() instead of letoh16().

+void axe_ax88178_init(struct axe_softc *);
+void axe_ax88772_init(struct axe_softc *);

Why not Static?

They weren't static in the OpenBSD version!  I can easily add that.

-       allmulti:
+allmulti:

Not in KNF, but I like one space before labels.
(to avoid diff(1) thinks it's a function name)

Yup - fixed.

+       u_int16_t eeprom;

uintNN_t types are prefered, at least in new code.

Simple copy from the OpenBSD code - I have updated it.

+void
+axe_ax88772_init(struct axe_softc *sc)
+{
+       axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL);
+       usbd_delay_ms(sc->axe_udev, 40);

KNF says "Insert an empty line if the function has no local variables."

Done.

+       sc->axe_flags = axe_lookup(uaa->vendor, uaa->product)->axe_flags;

It looks sc->axe_flags should be set in axe_match()
where axe_lookup() is called first.

No, I don't think so. The results of the lookup in axe_match() are discarded until the autoconfig stuff selects the best match. And axe_match() doesn't even have a softc in which to store the results.

+       memcpy(&sc->init_eaddr, &eaddr, sizeof(sc->init_eaddr));

Do we really have to save MAC address into softc?
Can't we refer it by "CLLADDR(ifp->if_sadl)"?

I'll be totally honest here - I really haven't dived very deeply into the network interface architecture at all. So I have no idea if your suggestion would work or not. Where does ifp->if_sadl get stored?

-                       c->axe_buf = usbd_alloc_buffer(c->axe_xfer, AXE_BUFSZ);
+                       c->axe_buf = usbd_alloc_buffer(c->axe_xfer,
+                                                      sc->axe_bufsz);

KNF?

:)  Fixed (although I still prefer my own format here!)

+       u_char                  *buf;

This should be uint8_t?

This is from the OpenBSD code.  buf is being assigned from

        buf = c->axe_buf

where c->axe_buf is a (char *), so not sure if (uint8_t *) would be correct.

+                       if ((pktlen % 2) != 0)
+                               pktlen++;

roundup2(9)?

Done.

+struct axe_sframe_hdr {
+       u_int16_t               len;
+       u_int16_t               ilen;
+} __packed;

Is __packed actually required?

Probably not, but the struct does reflect the format of data on the physical media. Just to avoid any future issues on an architecture that might want to align thing on 32-bit boundary, I would prefer to leave __packed here.



-------------------------------------------------------------------------
| Paul Goyette     | PGP Key fingerprint:     | E-mail addresses:       |
| Customer Service | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com    |
| Network Engineer | 0786 F758 55DE 53BA 7731 | pgoyette at juniper.net |
| Kernel Developer |                          | pgoyette at netbsd.org  |
-------------------------------------------------------------------------
Index: axe.4
===================================================================
RCS file: /cvsroot/src/share/man/man4/axe.4,v
retrieving revision 1.6
diff -u -p -r1.6 axe.4
--- axe.4       15 Jan 2010 19:24:49 -0000      1.6
+++ axe.4       13 Jun 2010 09:11:41 -0000
@@ -27,12 +27,46 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd October 23, 2004
+.\" Copyright (c) 1997, 1998, 1999, 2000-2003
+.\"     Bill Paul <wpaul%windriver.com@localhost>. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"     This product includes software developed by Bill Paul.
+.\" 4. Neither the name of the author nor the names of any co-contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"   without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+.\" THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD: /repoman/r/ncvs/src/share/man/man4/axe.4,v 1.3 2003/05/29 
21:28:35 ru Exp $
+.\" $OpenBSD: axe.4,v 1.37 2009/11/08 20:25:29 jasper Exp $
+.\"
+
+.Dd June 13, 2010
 .Dt AXE 4
 .Os
 .Sh NAME
 .Nm axe
-.Nd ASIX AX88172 USB Ethernet driver
+.Nd ASIX Electronics AX88172/AX88178/AX88772 10/100/Gigabit USB Ethernet device
 .Sh SYNOPSIS
 .Cd "axe*   at uhub?"
 .Cd "XXphy* at mii?"
@@ -42,26 +76,53 @@ The
 driver supports the following adapters:
 .Pp
 .Bl -tag -width Dv -offset indent -compact
-.It Tn Corega FEther USB2-TX
-.It Tn D-Link DUB-E100
-.It Tn Linksys USB 200M
-.It Tn Melco LUA-U2-KTX
-.It Tn Netgear FA120
-.It Tn Sitecom LN029
-.It Tn Systemtalks SGCX2UL
+.It Apple USB Ethernet Adapter A1277
+.It ATEN UC-210T
+.It BAFO BF-320
+.It Billionton Systems USB2AR 
+.It Buffalo(MELCO) LUA-U2-GT
+.It Buffalo(MELCO) LUA-U2-KTX
+.It Corega FEther USB2-TX 
+.It D-Link DUB-E100
+.It Good Way GWUSB2E
+.It Hawking UF200
+.It Intellinet USB 2.0 to Ethernet (rev A)
+.It IO-Data ETG-US2
+.It JVC MP-PRX1
+.It Konig CMP-NWUSB20 
+.It Level One USB-0200
+.It Linksys USB200M
+.It Linksys USB1000
+.It Logitec LAN-GTJ/U2
+.It Netgear FA120
+.It Nintendo Wii USB Lan Ethernet Adapter RVL-015
+.It OQO model 01+ Ethernet
+.It Sitecom LN-029
+.It SMC 2209USB/ETH
+.It SnapPort USB 2.0 LAN Adapter
+.It ST Lab USB 2.0 Fast Ethernet
+.It Surecom EP-1427X-2
+.It System TALKS SGC-X2UL
+.It TRENDnet TU2-ET100
+.It Z-TEK ZK-R01-2
 .El
 .Sh DESCRIPTION
 The
 .Nm
-driver provides support for USB (2.0)
+driver provides support for USB
 .Tn Ethernet
-adapters based on the ASIX AX88172 chip.
+adapters based on the ASIX Electronics AX88172, AX88178, and AX88772
+USB 2.0 chipsets.
 .Pp
 The chip contains a 10/100
 .Tn Ethernet
 MAC with MII interface and is designed to work with both
 .Tn Ethernet
 and HomePNA transceivers.
+The AX8172 and AX88772 contain 10/100 Ethernet MACs with MII interfaces.
+The AX8178 contains a 10/100/1000 Gigabit
+.Tn Ethernet
+MAC with a GMII/MII interface.
 The chip also supports USB 2.0, thereby accommodating 100 Mb/s data rates.
 .Pp
 The
@@ -97,6 +158,10 @@ Not specifying
 implies
 .Ar half-duplex
 mode.
+.It 1000baseT
+Set 1000Mbps (Gigabit
+.Tn Ethernet )
+operation (AX88178 only).
 .El
 .Pp
 The
@@ -114,6 +179,7 @@ For more information on configuring this
 .Xr ifconfig 8 .
 .Sh SEE ALSO
 .Xr arp 4 ,
+.Xr ifmedia 4 ,
 .Xr netintro 4 ,
 .Xr usb 4 ,
 .Xr ifconfig 8
Index: if_axe.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_axe.c,v
retrieving revision 1.32
diff -u -p -r1.32 if_axe.c
--- if_axe.c    5 Apr 2010 07:21:48 -0000       1.32
+++ if_axe.c    13 Jun 2010 10:23:57 -0000
@@ -1,4 +1,21 @@
 /*     $NetBSD: if_axe.c,v 1.32 2010/04/05 07:21:48 joerg Exp $        */
+/*     $OpenBSD: if_axe.c,v 1.96 2010/01/09 05:33:08 jsg Exp $ */
+
+/*
+ * Copyright (c) 2005, 2006, 2007 Jonathan Gray <jsg%openbsd.org@localhost>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
 
 /*
  * Copyright (c) 1997, 1998, 1999, 2000-2003
@@ -97,6 +114,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1
 #include <sys/rnd.h>
 #endif
 
+#include <sys/bus.h>
+
 #include <net/if.h>
 #if defined(__NetBSD__)
 #include <net/if_arp.h>
@@ -130,6 +149,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_axe.c,v 1
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
 #include <dev/usb/usbdi_util.h>
 #include <dev/usb/usbdevs.h>
 
@@ -148,14 +168,35 @@ int       axedebug = 0;
  * Various supported device vendors/products.
  */
 Static const struct axe_type axe_devs[] = {
+       { { USB_VENDOR_ABOCOM,          USB_PRODUCT_ABOCOM_UFE2000}, 0 },
+       { { USB_VENDOR_ACERCM,          USB_PRODUCT_ACERCM_EP1427X2}, 0 },
+       { { USB_VENDOR_APPLE,           USB_PRODUCT_APPLE_ETHERNET }, AX772 },
        { { USB_VENDOR_ASIX,            USB_PRODUCT_ASIX_AX88172}, 0 },
+       { { USB_VENDOR_ASIX,            USB_PRODUCT_ASIX_AX88772}, AX772 },
+       { { USB_VENDOR_ASIX,            USB_PRODUCT_ASIX_AX88772A}, AX772 },
+       { { USB_VENDOR_ASIX,            USB_PRODUCT_ASIX_AX88178}, AX178 },
+       { { USB_VENDOR_ATEN,            USB_PRODUCT_ATEN_UC210T}, 0 },
+       { { USB_VENDOR_BELKIN,          USB_PRODUCT_BELKIN_F5D5055 }, AX178 },
+       { { USB_VENDOR_BILLIONTON,      USB_PRODUCT_BILLIONTON_USB2AR}, 0},
+       { { USB_VENDOR_CISCOLINKSYS,    USB_PRODUCT_CISCOLINKSYS_USB200MV2}, 
AX772 },
        { { USB_VENDOR_COREGA,          USB_PRODUCT_COREGA_FETHER_USB2_TX }, 0},
        { { USB_VENDOR_DLINK,           USB_PRODUCT_DLINK_DUBE100}, 0 },
+       { { USB_VENDOR_DLINK,           USB_PRODUCT_DLINK_DUBE100B1 }, AX772 },
+       { { USB_VENDOR_GOODWAY,         USB_PRODUCT_GOODWAY_GWUSB2E}, 0 },
+       { { USB_VENDOR_IODATA,          USB_PRODUCT_IODATA_ETGUS2 }, AX178 },
+       { { USB_VENDOR_JVC,             USB_PRODUCT_JVC_MP_PRX1}, 0 },
        { { USB_VENDOR_LINKSYS2,        USB_PRODUCT_LINKSYS2_USB200M}, 0 },
+       { { USB_VENDOR_LINKSYS4,        USB_PRODUCT_LINKSYS4_USB1000 }, AX178 },
+       { { USB_VENDOR_LOGITEC,         USB_PRODUCT_LOGITEC_LAN_GTJU2}, AX178 },
+       { { USB_VENDOR_MELCO,           USB_PRODUCT_MELCO_LUAU2GT}, AX178 },
        { { USB_VENDOR_MELCO,           USB_PRODUCT_MELCO_LUAU2KTX}, 0 },
+       { { USB_VENDOR_MSI,             USB_PRODUCT_MSI_AX88772A}, AX772 },
        { { USB_VENDOR_NETGEAR,         USB_PRODUCT_NETGEAR_FA120}, 0 },
-       { { USB_VENDOR_SITECOM,         USB_PRODUCT_SITECOM_LN029}, 0 },
+       { { USB_VENDOR_OQO,             USB_PRODUCT_OQO_ETHER01PLUS }, AX772 },
+       { { USB_VENDOR_PLANEX3,         USB_PRODUCT_PLANEX3_GU1000T }, AX178 },
        { { USB_VENDOR_SYSTEMTALKS,     USB_PRODUCT_SYSTEMTALKS_SGCX2UL}, 0 },
+       { { USB_VENDOR_SITECOM,         USB_PRODUCT_SITECOM_LN029}, 0 },
+       { { USB_VENDOR_SITECOMEU,       USB_PRODUCT_SITECOMEU_LN028 }, AX178 }
 };
 #define axe_lookup(v, p) ((const struct axe_type *)usb_lookup(axe_devs, v, p))
 
@@ -193,6 +234,9 @@ Static void axe_setmulti(struct axe_soft
 Static void axe_lock_mii(struct axe_softc *sc);
 Static void axe_unlock_mii(struct axe_softc *sc);
 
+Static void axe_ax88178_init(struct axe_softc *);
+Static void axe_ax88772_init(struct axe_softc *);
+
 /* Get exclusive access to the MII registers */
 Static void
 axe_lock_mii(struct axe_softc *sc)
@@ -317,6 +361,23 @@ axe_miibus_statchg(device_t dev)
                val = AXE_MEDIA_FULL_DUPLEX;
        else
                val = 0;
+
+       if (sc->axe_flags & AX178 || sc->axe_flags & AX772) {
+               val |= (AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC);
+
+               switch (IFM_SUBTYPE(mii->mii_media_active)) {
+               case IFM_1000_T:  
+                       val |= AXE_178_MEDIA_GMII | AXE_178_MEDIA_ENCK;
+                       break;
+               case IFM_100_TX:
+                       val |= AXE_178_MEDIA_100TX;
+                       break;
+               case IFM_10_T:
+                       /* doesn't need to be handled */
+                       break;
+               }
+       }
+
        DPRINTF(("axe_miibus_statchg: val=0x%x\n", val));
        axe_lock_mii(sc);
        err = axe_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL);
@@ -347,9 +408,10 @@ axe_setmulti(struct axe_softc *sc)
        rxmode = le16toh(rxmode);
 
        if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
-       allmulti:
+ allmulti:
                rxmode |= AXE_RXCMD_ALLMULTI;
                axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
+               axe_unlock_mii(sc);
                return;
        } else
                rxmode &= ~AXE_RXCMD_ALLMULTI;
@@ -389,6 +451,104 @@ axe_reset(struct axe_softc *sc)
        return;
 }
 
+Static void
+axe_ax88178_init(struct axe_softc *sc)
+{
+       int gpio0 = 0, phymode = 0;
+       uint16_t eeprom;
+
+       axe_cmd(sc, AXE_CMD_SROM_WR_ENABLE, 0, 0, NULL);
+       /* XXX magic */
+       axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom);
+       axe_cmd(sc, AXE_CMD_SROM_WR_DISABLE, 0, 0, NULL);
+
+       eeprom = le16toh(eeprom);
+
+       DPRINTF((" EEPROM is 0x%x\n", eeprom));
+
+       /* if EEPROM is invalid we have to use to GPIO0 */
+       if (eeprom == 0xffff) {
+               phymode = 0;
+               gpio0 = 1;
+       } else {
+               phymode = eeprom & 7;
+               gpio0 = (eeprom & 0x80) ? 0 : 1;
+       }
+
+       DPRINTF(("use gpio0: %d, phymode %d\n", gpio0, phymode));
+
+       axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x008c, NULL);
+       usbd_delay_ms(sc->axe_udev, 40);
+       if ((eeprom >> 8) != 1) {
+               axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL);
+               usbd_delay_ms(sc->axe_udev, 30);
+
+               axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x001c, NULL);
+               usbd_delay_ms(sc->axe_udev, 300);
+
+               axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL);
+               usbd_delay_ms(sc->axe_udev, 30);
+       } else {
+               DPRINTF(("axe gpio phymode == 1 path\n"));
+               axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x0004, NULL);
+               usbd_delay_ms(sc->axe_udev, 30);
+               axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x000c, NULL);
+               usbd_delay_ms(sc->axe_udev, 30);
+       }
+
+       /* soft reset */
+       axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL);
+       usbd_delay_ms(sc->axe_udev, 150);
+       axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
+           AXE_SW_RESET_PRL | AXE_178_RESET_MAGIC, NULL);
+       usbd_delay_ms(sc->axe_udev, 150);
+       /* Enable MII/GMII/RGMII for external PHY */
+       axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0, NULL);
+       usbd_delay_ms(sc->axe_udev, 10);
+       axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
+}
+
+Static void
+axe_ax88772_init(struct axe_softc *sc)
+{
+
+       axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL);
+       usbd_delay_ms(sc->axe_udev, 40);
+
+       if (sc->axe_phyaddrs[1] == AXE_INTPHY) {
+               /* ask for the embedded PHY */
+               axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x01, NULL);
+               usbd_delay_ms(sc->axe_udev, 10);
+
+               /* power down and reset state, pin reset state */
+               axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL);
+               usbd_delay_ms(sc->axe_udev, 60);
+
+               /* power down/reset state, pin operating state */
+               axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
+                   AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL);
+               usbd_delay_ms(sc->axe_udev, 150);
+
+               /* power up, reset */
+               axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_PRL, NULL);
+
+               /* power up, operating */
+               axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
+                   AXE_SW_RESET_IPRL | AXE_SW_RESET_PRL, NULL);
+       } else {
+               /* ask for external PHY */
+               axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x00, NULL);
+               usbd_delay_ms(sc->axe_udev, 10);
+
+               /* power down internal PHY */
+               axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0,
+                   AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL);
+       }
+
+       usbd_delay_ms(sc->axe_udev, 150);
+       axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
+}
+
 /*
  * Probe for a AX88172 chip.
  */
@@ -436,6 +596,8 @@ axe_attach(device_t parent, device_t sel
                return;
        }
 
+       sc->axe_flags = axe_lookup(uaa->vendor, uaa->product)->axe_flags;
+
        usb_init_task(&sc->axe_tick_task, axe_tick_task, sc);
        mutex_init(&sc->axe_mii_lock, MUTEX_DEFAULT, IPL_NONE);
        usb_init_task(&sc->axe_stop_task, (void (*)(void *))axe_stop, sc);
@@ -452,6 +614,13 @@ axe_attach(device_t parent, device_t sel
 
        id = usbd_get_interface_descriptor(sc->axe_iface);
 
+       /* decide on what our bufsize will be */
+       if (sc->axe_flags & AX178 || sc->axe_flags & AX772)
+               sc->axe_bufsz = (sc->axe_udev->speed == USB_SPEED_HIGH) ?
+                   AXE_178_MAX_BUFSZ : AXE_178_MIN_BUFSZ;
+       else
+               sc->axe_bufsz = AXE_172_BUFSZ;
+
        /* Find endpoints. */
        for (i = 0; i < id->bNumEndpoints; i++) {
                ed = usbd_interface2endpoint_descriptor(sc->axe_iface, i);
@@ -473,11 +642,22 @@ axe_attach(device_t parent, device_t sel
 
        s = splnet();
 
+       /* We need the PHYID for init dance in some cases */
+       axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, (void *)&sc->axe_phyaddrs);
+
+       if (sc->axe_flags & AX178)
+               axe_ax88178_init(sc);
+       else if (sc->axe_flags & AX772)
+               axe_ax88772_init(sc);
+
        /*
         * Get station address.
         */
        axe_lock_mii(sc);
-       axe_cmd(sc, AXE_CMD_READ_NODEID, 0, 0, &eaddr);
+       if (sc->axe_flags & AX178 || sc->axe_flags & AX772)
+               axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, &eaddr);
+       else    
+               axe_cmd(sc, AXE_172_CMD_READ_NODEID, 0, 0, &eaddr);
 
        /*
         * Load IPG values and PHY indexes.
@@ -495,8 +675,8 @@ axe_attach(device_t parent, device_t sel
        /*
         * An ASIX chip was detected. Inform the world.
         */
-       aprint_normal_dev(self, "Ethernet address %s\n",
-           ether_sprintf(eaddr));
+       aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(eaddr));
+       memcpy(&sc->init_eaddr, &eaddr, sizeof(sc->init_eaddr));
 
        /* Initialize interface info.*/
        ifp = GET_IFP(sc);
@@ -697,7 +877,8 @@ axe_rx_list_init(struct axe_softc *sc)
                        c->axe_xfer = usbd_alloc_xfer(sc->axe_udev);
                        if (c->axe_xfer == NULL)
                                return (ENOBUFS);
-                       c->axe_buf = usbd_alloc_buffer(c->axe_xfer, AXE_BUFSZ);
+                       c->axe_buf = usbd_alloc_buffer(c->axe_xfer,
+                           sc->axe_bufsz);
                        if (c->axe_buf == NULL) {
                                usbd_free_xfer(c->axe_xfer);
                                return (ENOBUFS);
@@ -727,7 +908,8 @@ axe_tx_list_init(struct axe_softc *sc)
                        c->axe_xfer = usbd_alloc_xfer(sc->axe_udev);
                        if (c->axe_xfer == NULL)
                                return (ENOBUFS);
-                       c->axe_buf = usbd_alloc_buffer(c->axe_xfer, AXE_BUFSZ);
+                       c->axe_buf = usbd_alloc_buffer(c->axe_xfer,
+                                                      sc->axe_bufsz);
                        if (c->axe_buf == NULL) {
                                usbd_free_xfer(c->axe_xfer);
                                return (ENOBUFS);
@@ -757,7 +939,7 @@ axe_rxstart(struct ifnet *ifp)
 
        /* Setup new transfer. */
        usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX],
-           c, mtod(c->axe_mbuf, char *), AXE_BUFSZ, USBD_SHORT_XFER_OK,
+           c, mtod(c->axe_mbuf, char *), sc->axe_bufsz, USBD_SHORT_XFER_OK,
            USBD_NO_TIMEOUT, axe_rxeof);
        usbd_transfer(c->axe_xfer);
        axe_unlock_mii(sc);
@@ -776,12 +958,16 @@ axe_rxeof(usbd_xfer_handle xfer, usbd_pr
        struct axe_softc        *sc;
        struct axe_chain        *c;
        struct ifnet            *ifp;
-       struct mbuf             *m;
+       u_char                  *buf;
        u_int32_t               total_len;
+       u_int16_t               pktlen = 0;
+       struct mbuf             *m;
+       struct axe_sframe_hdr   hdr;
        int                     s;
 
-       c = priv;
+       c = (struct axe_chain *)priv;
        sc = c->axe_sc;
+       buf = c->axe_buf;
        ifp = GET_IFP(sc);
 
        DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->axe_dev),__func__));
@@ -806,44 +992,74 @@ axe_rxeof(usbd_xfer_handle xfer, usbd_pr
 
        usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
 
-       m = c->axe_mbuf;
+       do {
+               if (sc->axe_flags & AX178 || sc->axe_flags & AX772) {
+                       if (total_len < sizeof(hdr)) {
+                               ifp->if_ierrors++;
+                               goto done;
+                       }
+                       buf += pktlen;
 
-       if (total_len <= sizeof(struct ether_header)) {
-               ifp->if_ierrors++;
-               goto done;
-       }
+                       memcpy(&hdr, buf, sizeof(hdr));
+                       total_len -= sizeof(hdr);
 
-       ifp->if_ipackets++;
-       m->m_pkthdr.rcvif = ifp;
-       m->m_pkthdr.len = m->m_len = total_len;
+                       if ((hdr.len ^ hdr.ilen) != 0xffff) {
+                               ifp->if_ierrors++;
+                               goto done;
+                       }
+                       pktlen = le16toh(hdr.len);
+                       if (pktlen > total_len) {
+                               ifp->if_ierrors++;
+                               goto done;
+                       }
 
+                       buf += sizeof(hdr);
 
-       memcpy(mtod(c->axe_mbuf, char *), c->axe_buf, total_len);
+                       pktlen = roundup2(2, pktlen);
 
-       /* No errors; receive the packet. */
-       total_len -= ETHER_CRC_LEN + 4;
+                       if (total_len < pktlen)
+                               total_len = 0;
+                       else
+                               total_len -= pktlen;
+               } else { /* AX172 */
+                       pktlen = total_len;
+                       total_len = 0;
+               }
 
-       s = splnet();
+               m = c->axe_mbuf;
 
-       /* XXX ugly */
-       if (axe_newbuf(sc, c, NULL) == ENOBUFS) {
-               ifp->if_ierrors++;
-               goto done1;
-       }
+               /* XXX ugly */
+               if (axe_newbuf(sc, c, NULL) == ENOBUFS) {
+                       ifp->if_ierrors++;
+                       goto done;
+               }
 
-       bpf_mtap(ifp, m);
+               ifp->if_ipackets++;
+               m->m_pkthdr.rcvif = ifp;
+               m->m_pkthdr.len = m->m_len = pktlen;
 
-       DPRINTFN(10,("%s: %s: deliver %d\n", USBDEVNAME(sc->axe_dev),
-                   __func__, m->m_len));
-       (*(ifp)->if_input)((ifp), (m));
- done1:
-       splx(s);
+               memcpy(mtod(m, char *), buf, pktlen);
+
+               /* No errors; receive the packet. */
+               pktlen -= ETHER_CRC_LEN + 4;
+
+               s = splnet();
+
+               bpf_mtap(ifp, m);
+
+               DPRINTFN(10,("%s: %s: deliver %d\n", USBDEVNAME(sc->axe_dev),
+                           __func__, m->m_len));
+               (*(ifp)->if_input)((ifp), (m));
+
+               splx(s);
+
+       } while (total_len > 0);
 
  done:
 
        /* Setup new transfer. */
        usbd_setup_xfer(xfer, sc->axe_ep[AXE_ENDPT_RX],
-           c, c->axe_buf, AXE_BUFSZ,
+           c, c->axe_buf, sc->axe_bufsz,
            USBD_SHORT_XFER_OK | USBD_NO_COPY,
            USBD_NO_TIMEOUT, axe_rxeof);
        usbd_transfer(xfer);
@@ -958,6 +1174,8 @@ axe_encap(struct axe_softc *sc, struct m
 {
        struct axe_chain        *c;
        usbd_status             err;
+       struct axe_sframe_hdr   hdr;
+       int                     length, boundary;
 
        c = &sc->axe_cdata.axe_tx_chain[idx];
 
@@ -965,11 +1183,32 @@ axe_encap(struct axe_softc *sc, struct m
         * Copy the mbuf data into a contiguous buffer, leaving two
         * bytes at the beginning to hold the frame length.
         */
-       m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf);
+       if (sc->axe_flags & AX178 || sc->axe_flags & AX772) {
+               boundary = (sc->axe_udev->speed == USB_SPEED_HIGH) ? 512 : 64;
+
+               hdr.len = htole16(m->m_pkthdr.len);
+               hdr.ilen = ~hdr.len;
+
+               memcpy(c->axe_buf, &hdr, sizeof(hdr));
+               length = sizeof(hdr);
+
+               m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf + length);
+               length += m->m_pkthdr.len;
+
+               if ((length % boundary) == 0) {
+                       hdr.len = 0x0000;
+                       hdr.ilen = 0xffff;
+                       memcpy(c->axe_buf + length, &hdr, sizeof(hdr));
+                       length += sizeof(hdr);
+               }
+       } else {
+               m_copydata(m, 0, m->m_pkthdr.len, c->axe_buf);
+               length = m->m_pkthdr.len;
+       }
        c->axe_mbuf = m;
 
        usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_TX],
-           c, c->axe_buf, m->m_pkthdr.len, USBD_FORCE_SHORT_XFER, 10000,
+           c, c->axe_buf, length, USBD_FORCE_SHORT_XFER, 10000,
            axe_txeof);
 
        /* Transmit */
@@ -1042,6 +1281,17 @@ axe_init(void *xsc)
         */
        axe_reset(sc);
 
+       /* Set MAC address */
+       if (sc->axe_flags & AX178 || sc->axe_flags & AX772)
+               axe_cmd(sc, AXE_178_CMD_WRITE_NODEID, 0, 0,
+#if defined(__NetBSD__)
+                       /* CLLADDR(ifp->if_sadl) */
+                       &sc->init_eaddr
+#else
+                       &sc->arpcom.ac_enaddr
+#endif
+                       );
+
        /* Enable RX logic. */
 
        /* Init RX ring. */
@@ -1060,12 +1310,24 @@ axe_init(void *xsc)
 
        /* Set transmitter IPG values */
        axe_lock_mii(sc);
-       axe_cmd(sc, AXE_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL);
-       axe_cmd(sc, AXE_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL);
-       axe_cmd(sc, AXE_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL);
+       if (sc->axe_flags & AX178 || sc->axe_flags & AX772)
+               axe_cmd(sc, AXE_178_CMD_WRITE_IPG012, sc->axe_ipgs[2],
+                       (sc->axe_ipgs[1] << 8) | (sc->axe_ipgs[0]), NULL);
+       else {
+               axe_cmd(sc, AXE_172_CMD_WRITE_IPG0, 0, sc->axe_ipgs[0], NULL);
+               axe_cmd(sc, AXE_172_CMD_WRITE_IPG1, 0, sc->axe_ipgs[1], NULL);
+               axe_cmd(sc, AXE_172_CMD_WRITE_IPG2, 0, sc->axe_ipgs[2], NULL);
+       }
 
        /* Enable receiver, set RX mode */
-       rxmode = AXE_RXCMD_UNICAST|AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE;
+       rxmode = AXE_RXCMD_MULTICAST|AXE_RXCMD_ENABLE;
+       if (sc->axe_flags & AX178 || sc->axe_flags & AX772) {
+               if (sc->axe_udev->speed == USB_SPEED_HIGH) {
+                       /* Largest possible USB buffer size for AX88178 */
+                       rxmode |= AXE_178_RXCMD_MFB;
+               }
+       } else
+               rxmode |= AXE_172_RXCMD_UNICAST;
 
        /* If we want promiscuous mode, set the allframes bit. */
        if (ifp->if_flags & IFF_PROMISC)
@@ -1103,7 +1365,7 @@ axe_init(void *xsc)
        for (i = 0; i < AXE_RX_LIST_CNT; i++) {
                c = &sc->axe_cdata.axe_rx_chain[i];
                usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX],
-                   c, mtod(c->axe_mbuf, char *), AXE_BUFSZ,
+                   c, mtod(c->axe_mbuf, char *), sc->axe_bufsz,
                    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, axe_rxeof);
                usbd_transfer(c->axe_xfer);
        }
Index: if_axereg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_axereg.h,v
retrieving revision 1.7
diff -u -p -r1.7 if_axereg.h
--- if_axereg.h 4 Sep 2009 18:10:08 -0000       1.7
+++ if_axereg.h 13 Jun 2010 10:23:57 -0000
@@ -55,9 +55,11 @@
 #define AXE_CMD_LEN(x) (((x) & 0xF000) >> 12)
 #define AXE_CMD_CMD(x) ((x) & 0x00FF)
 
-#define AXE_CMD_READ_RXTX_SRAM                 0x2002
-#define AXE_CMD_WRITE_RX_SRAM                  0x0103
-#define AXE_CMD_WRITE_TX_SRAM                  0x0104
+#define AXE_172_CMD_READ_RXTX_SRAM             0x2002
+#define AXE_182_CMD_READ_RXTX_SRAM             0x6002
+#define AXE_172_CMD_WRITE_RX_SRAM              0x0103
+#define AXE_172_CMD_WRITE_TX_SRAM              0x0104
+#define AXE_182_CMD_WRITE_RXTX_SRAM            0x8103
 #define AXE_CMD_MII_OPMODE_SW                  0x0106
 #define AXE_CMD_MII_READ_REG                   0x2007
 #define AXE_CMD_MII_WRITE_REG                  0x2108
@@ -70,36 +72,74 @@
 #define AXE_CMD_RXCTL_READ                     0x200F
 #define AXE_CMD_RXCTL_WRITE                    0x0110
 #define AXE_CMD_READ_IPG012                    0x3011
-#define AXE_CMD_WRITE_IPG0                     0x0112
-#define AXE_CMD_WRITE_IPG1                     0x0113
-#define AXE_CMD_WRITE_IPG2                     0x0114
+#define AXE_172_CMD_WRITE_IPG0                 0x0112
+#define AXE_172_CMD_WRITE_IPG1                 0x0113
+#define AXE_172_CMD_WRITE_IPG2                 0x0114
+#define AXE_178_CMD_WRITE_IPG012               0x0112
 #define AXE_CMD_READ_MCAST                     0x8015
 #define AXE_CMD_WRITE_MCAST                    0x8116
-#define AXE_CMD_READ_NODEID                    0x6017
-#define AXE_CMD_WRITE_NODEID                   0x6118
+#define AXE_172_CMD_READ_NODEID                        0x6017
+#define AXE_172_CMD_WRITE_NODEID               0x6118
+#define AXE_178_CMD_READ_NODEID                        0x6013
+#define AXE_178_CMD_WRITE_NODEID               0x6114
 #define AXE_CMD_READ_PHYID                     0x2019
-#define AXE_CMD_READ_MEDIA                     0x101A
+#define AXE_172_CMD_READ_MEDIA                 0x101A
+#define AXE_178_CMD_READ_MEDIA                 0x201A
 #define AXE_CMD_WRITE_MEDIA                    0x011B
 #define AXE_CMD_READ_MONITOR_MODE              0x101C
 #define AXE_CMD_WRITE_MONITOR_MODE             0x011D
 #define AXE_CMD_READ_GPIO                      0x101E
 #define AXE_CMD_WRITE_GPIO                     0x011F
-
-#define AXE_MEDIA_FULL_DUPLEX                  0x02
-#define AXE_MEDIA_TX_ABORT_ALLOW               0x04
-#define AXE_MEDIA_FLOW_CONTROL_EN              0x10
+#define AXE_CMD_SW_RESET_REG                   0x0120
+#define AXE_CMD_SW_PHY_STATUS                  0x0021
+#define AXE_CMD_SW_PHY_SELECT                  0x0122
+
+#define AXE_SW_RESET_CLEAR                     0x00
+#define AXE_SW_RESET_RR                                0x01
+#define AXE_SW_RESET_RT                                0x02
+#define AXE_SW_RESET_PRTE                      0x04
+#define AXE_SW_RESET_PRL                       0x08
+#define AXE_SW_RESET_BZ                                0x10
+#define AXE_SW_RESET_IPRL                      0x20
+#define AXE_SW_RESET_IPPD                      0x40
+
+/* AX88178 documentation says to always write this bit... */
+#define AXE_178_RESET_MAGIC                    0x40
+
+#define AXE_178_MEDIA_GMII                     0x0001
+#define AXE_MEDIA_FULL_DUPLEX                  0x0002
+#define AXE_172_MEDIA_TX_ABORT_ALLOW           0x0004
+/* AX88178 documentation says to always write 1 to reserved bit... */
+#define AXE_178_MEDIA_MAGIC                    0x0004
+#define AXE_178_MEDIA_ENCK                     0x0008
+#define AXE_172_MEDIA_FLOW_CONTROL_EN          0x0010
+#define AXE_178_MEDIA_RXFLOW_CONTROL_EN                0x0010
+#define AXE_178_MEDIA_TXFLOW_CONTROL_EN                0x0020
+#define AXE_178_MEDIA_JUMBO_EN                 0x0040
+#define AXE_178_MEDIA_LTPF_ONLY                        0x0080
+#define AXE_178_MEDIA_RX_EN                    0x0100
+#define AXE_178_MEDIA_100TX                    0x0200
+#define AXE_178_MEDIA_SBP                      0x0800
+#define AXE_178_MEDIA_SUPERMAC                 0x1000
 
 #define AXE_RXCMD_PROMISC                      0x0001
 #define AXE_RXCMD_ALLMULTI                     0x0002
-#define AXE_RXCMD_UNICAST                      0x0004
+#define AXE_172_RXCMD_UNICAST                  0x0004
+#define AXE_178_RXCMD_KEEP_INVALID_CRC         0x0004
 #define AXE_RXCMD_BROADCAST                    0x0008
 #define AXE_RXCMD_MULTICAST                    0x0010
 #define AXE_RXCMD_ENABLE                       0x0080
+#define AXE_178_RXCMD_MFB                      0x0300
 
 #define AXE_NOPHY                              0xE0
+#define AXE_INTPHY                             0x10
 
 #define AXE_TIMEOUT            1000
-#define AXE_BUFSZ              1536
+
+#define AXE_172_BUFSZ          1536
+#define AXE_178_MIN_BUFSZ      2048
+#define AXE_178_MAX_BUFSZ      16384
+
 #define AXE_MIN_FRAMELEN       60
 #define AXE_RX_FRAMES          1
 #define AXE_TX_FRAMES          1
@@ -125,7 +165,8 @@
 struct axe_type {
        struct usb_devno        axe_dev;
        u_int16_t               axe_flags;
-/* XXX No flags so far */
+#define AX178  0x0001          /* AX88178 */
+#define AX772  0x0002          /* AX88772 */
 };
 
 struct axe_softc;
@@ -148,6 +189,11 @@ struct axe_cdata {
        int                     axe_rx_prod;
 };
 
+struct axe_sframe_hdr {
+       u_int16_t               len;
+       u_int16_t               ilen;
+} __packed;
+
 #define AXE_INC(x, y)          (x) = (x + 1) % y
 
 struct axe_softc {
@@ -164,6 +210,7 @@ struct axe_softc {
 
        u_int16_t               axe_vendor;
        u_int16_t               axe_product;
+       u_int16_t               axe_flags;
 
        int                     axe_ed[AXE_ENDPT_MAX];
        usbd_pipe_handle        axe_ep[AXE_ENDPT_MAX];
@@ -183,6 +230,8 @@ struct axe_softc {
        unsigned char           axe_ipgs[3];
        unsigned char           axe_phyaddrs[2];
        struct timeval          axe_rx_notice;
+       int                     axe_bufsz;
+       u_char                  init_eaddr[ETHER_ADDR_LEN];
 };
 
 #if 0


Home | Main Index | Thread Index | Old Index