Call for testers: AXE88x78 support for RELENG_6
Oleksandr Tymoshenko
gonzo at pbxpress.com
Fri Jan 18 08:56:27 PST 2008
Oleksandr Tymoshenko wrote:
> patch atached
Sorry, now it *is* attached.
--
Sincerely,
Oleksandr Tymoshenko
PBXpress Communications, Inc.
http://www.pbxpress.com
Tel./Fax.: +1 866 SIP PBX1 Ext. 7117
-------------- next part --------------
--- dev/usb/if_axe.c.orig 2008-01-18 18:04:09.000000000 +0000
+++ dev/usb/if_axe.c 2008-01-18 18:04:36.000000000 +0000
@@ -31,11 +31,11 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/usb/if_axe.c,v 1.30.2.6 2007/05/21 18:13:11 brueffer Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/usb/if_axe.c,v 1.56 2007/11/10 16:23:38 sam Exp $");
/*
- * ASIX Electronics AX88172 USB 2.0 ethernet driver. Used in the
- * LinkSys USB200M and various other adapters.
+ * ASIX Electronics AX88172/AX88178/AX88778 USB 2.0 ethernet driver.
+ * Used in the LinkSys USB200M and various other adapters.
*
* Manuals available from:
* http://www.asix.com.tw/datasheet/mac/Ax88172.PDF
@@ -69,12 +69,15 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/endian.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
+#include <sys/lock.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/socket.h>
+#include <sys/sx.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -98,51 +101,83 @@
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
-/* "controller miibus0" required. See GENERIC if you get errors here. */
+/* "device miibus" required. See GENERIC if you get errors here. */
#include "miibus_if.h"
+/*
+ * AXE_178_MAX_FRAME_BURST
+ * max frame burst size for Ax88178 and Ax88772
+ * 0 2048 bytes
+ * 1 4096 bytes
+ * 2 8192 bytes
+ * 3 16384 bytes
+ * use the largest your system can handle without usb stalling.
+ *
+ * NB: 88772 parts appear to generate lots of input errors with
+ * a 2K rx buffer and 8K is only slightly faster than 4K on an
+ * EHCI port on a T42 so change at your own risk.
+ */
+#define AXE_178_MAX_FRAME_BURST 1
+
#include <dev/usb/if_axereg.h>
/*
* Various supported device vendors/products.
*/
-Static struct axe_type axe_devs[] = {
- { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88172 },
- { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100 },
- { USB_VENDOR_JVC, USB_PRODUCT_JVC_MP_PRX1 },
- { USB_VENDOR_LINKSYS2, USB_PRODUCT_LINKSYS2_USB200M },
- { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAU2KTX },
- { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA120 },
- { USB_VENDOR_SYSTEMTALKS, USB_PRODUCT_SYSTEMTALKS_SGCX2UL },
- { USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_LN029 },
- { 0, 0 }
+const struct axe_type axe_devs[] = {
+ { { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UF200}, 0 },
+ { { USB_VENDOR_ACERCM, USB_PRODUCT_ACERCM_EP1427X2}, 0 },
+ { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88172}, 0 },
+ { { USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772}, 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_LINKSYS4, USB_PRODUCT_LINKSYS4_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_LINKSYS5, USB_PRODUCT_LINKSYS5_USB1000 }, AX178 },
+ { { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAU2KTX}, 0 },
+ { { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA120}, 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 }
};
-Static int axe_match(device_ptr_t);
-Static int axe_attach(device_ptr_t);
-Static int axe_detach(device_ptr_t);
-
-Static int axe_encap(struct axe_softc *, struct mbuf *, int);
-Static void axe_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
-Static void axe_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
-Static void axe_tick(void *);
-Static void axe_rxstart(struct ifnet *);
-Static void axe_start(struct ifnet *);
-Static int axe_ioctl(struct ifnet *, u_long, caddr_t);
-Static void axe_init(void *);
-Static void axe_stop(struct axe_softc *);
-Static void axe_watchdog(struct ifnet *);
-Static void axe_shutdown(device_ptr_t);
-Static int axe_miibus_readreg(device_ptr_t, int, int);
-Static int axe_miibus_writereg(device_ptr_t, int, int, int);
-Static void axe_miibus_statchg(device_ptr_t);
-Static int axe_cmd(struct axe_softc *, int, int, int, void *);
-Static int axe_ifmedia_upd(struct ifnet *);
-Static void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+#define axe_lookup(v, p) ((const struct axe_type *)usb_lookup(axe_devs, v, p))
+
+static device_probe_t axe_match;
+static device_attach_t axe_attach;
+static device_detach_t axe_detach;
+static device_shutdown_t axe_shutdown;
+static miibus_readreg_t axe_miibus_readreg;
+static miibus_writereg_t axe_miibus_writereg;
+static miibus_statchg_t axe_miibus_statchg;
+
+static int axe_encap(struct axe_softc *, struct mbuf *, int);
+static void axe_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static void axe_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static void axe_tick(void *);
+static void axe_tick_task(void *);
+static void axe_start(struct ifnet *);
+static int axe_ioctl(struct ifnet *, u_long, caddr_t);
+static void axe_init(void *);
+static void axe_stop(struct axe_softc *);
+static void axe_watchdog(struct ifnet *);
+static int axe_cmd(struct axe_softc *, int, int, int, void *);
+static int axe_ifmedia_upd(struct ifnet *);
+static void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
-Static void axe_setmulti(struct axe_softc *);
+static void axe_setmulti(struct axe_softc *);
-Static device_method_t axe_methods[] = {
+static device_method_t axe_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, axe_match),
DEVMETHOD(device_attach, axe_attach),
@@ -161,25 +196,26 @@
{ 0, 0 }
};
-Static driver_t axe_driver = {
+static driver_t axe_driver = {
"axe",
axe_methods,
sizeof(struct axe_softc)
};
-Static devclass_t axe_devclass;
+static devclass_t axe_devclass;
DRIVER_MODULE(axe, uhub, axe_driver, axe_devclass, usbd_driver_load, 0);
DRIVER_MODULE(miibus, axe, miibus_driver, miibus_devclass, 0, 0);
MODULE_DEPEND(axe, usb, 1, 1, 1);
MODULE_DEPEND(axe, miibus, 1, 1, 1);
-Static int
+static int
axe_cmd(struct axe_softc *sc, int cmd, int index, int val, void *buf)
{
usb_device_request_t req;
usbd_status err;
+ AXE_SLEEPLOCKASSERT(sc);
if (sc->axe_dying)
return(0);
@@ -200,16 +236,17 @@
return(0);
}
-Static int
-axe_miibus_readreg(device_ptr_t dev, int phy, int reg)
+static int
+axe_miibus_readreg(device_t dev, int phy, int reg)
{
- struct axe_softc *sc = USBGETSOFTC(dev);
+ struct axe_softc *sc = device_get_softc(dev);
usbd_status err;
u_int16_t val;
if (sc->axe_dying)
return(0);
+ AXE_SLEEPLOCKASSERT(sc);
#ifdef notdef
/*
* The chip tells us the MII address of any supported
@@ -232,7 +269,7 @@
AXE_UNLOCK(sc);
if (err) {
- printf("axe%d: read PHY failed\n", sc->axe_unit);
+ device_printf(sc->axe_dev, "read PHY failed\n");
return(-1);
}
@@ -242,15 +279,16 @@
return (val);
}
-Static int
-axe_miibus_writereg(device_ptr_t dev, int phy, int reg, int val)
+static int
+axe_miibus_writereg(device_t dev, int phy, int reg, int val)
{
- struct axe_softc *sc = USBGETSOFTC(dev);
+ struct axe_softc *sc = device_get_softc(dev);
usbd_status err;
if (sc->axe_dying)
return(0);
+ AXE_SLEEPLOCKASSERT(sc);
AXE_LOCK(sc);
axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL);
err = axe_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, (void *)&val);
@@ -258,29 +296,46 @@
AXE_UNLOCK(sc);
if (err) {
- printf("axe%d: write PHY failed\n", sc->axe_unit);
+ device_printf(sc->axe_dev, "write PHY failed\n");
return(-1);
}
return (0);
}
-Static void
-axe_miibus_statchg(device_ptr_t dev)
+static void
+axe_miibus_statchg(device_t dev)
{
-#ifdef notdef
- struct axe_softc *sc = USBGETSOFTC(dev);
+ struct axe_softc *sc = device_get_softc(dev);
struct mii_data *mii = GET_MII(sc);
-#endif
- /* doesn't seem to be necessary */
+ int val, err;
- return;
+ val = (mii->mii_media_active & IFM_GMASK) == IFM_FDX ?
+ AXE_MEDIA_FULL_DUPLEX : 0;
+ if (sc->axe_flags & (AX178|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;
+ }
+ }
+ err = axe_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL);
+ if (err)
+ device_printf(dev, "media change failed, error %d\n", err);
}
/*
* Set media options.
*/
-Static int
+static int
axe_ifmedia_upd(struct ifnet *ifp)
{
struct axe_softc *sc = ifp->if_softc;
@@ -300,7 +355,7 @@
/*
* Report current media status.
*/
-Static void
+static void
axe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct axe_softc *sc = ifp->if_softc;
@@ -313,7 +368,7 @@
return;
}
-Static void
+static void
axe_setmulti(struct axe_softc *sc)
{
struct ifnet *ifp;
@@ -353,7 +408,94 @@
return;
}
-Static void
+static void
+axe_ax88178_init(struct axe_softc *sc)
+{
+ int gpio0 = 0, phymode = 0;
+ u_int16_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);
+
+ /* 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;
+ }
+
+ 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 {
+ 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, 0, 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);
+ 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 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/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);
+ axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL);
+}
+
+static void
axe_reset(struct axe_softc *sc)
{
if (sc->axe_dying)
@@ -362,8 +504,7 @@
if (usbd_set_config_no(sc->axe_udev, AXE_CONFIG_NO, 1) ||
usbd_device2interface_handle(sc->axe_udev, AXE_IFACE_IDX,
&sc->axe_iface)) {
- printf("axe%d: getting interface handle failed\n",
- sc->axe_unit);
+ device_printf(sc->axe_dev, "getting interface handle failed\n");
}
/* Wait a little while for the chip to get its brains in order. */
@@ -374,71 +515,76 @@
/*
* Probe for a AX88172 chip.
*/
-USB_MATCH(axe)
+static int
+axe_match(device_t self)
{
- USB_MATCH_START(axe, uaa);
- struct axe_type *t;
+ struct usb_attach_arg *uaa = device_get_ivars(self);
if (!uaa->iface)
return(UMATCH_NONE);
-
- t = axe_devs;
- while(t->axe_vid) {
- if (uaa->vendor == t->axe_vid &&
- uaa->product == t->axe_did) {
- return(UMATCH_VENDOR_PRODUCT);
- }
- t++;
- }
-
- return(UMATCH_NONE);
+ return (axe_lookup(uaa->vendor, uaa->product) != NULL ?
+ UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
}
/*
* Attach the interface. Allocate softc structures, do ifmedia
* setup and ethernet/BPF attach.
*/
-USB_ATTACH(axe)
+static int
+axe_attach(device_t self)
{
- USB_ATTACH_START(axe, sc, uaa);
- char devinfo[1024];
+ struct axe_softc *sc = device_get_softc(self);
+ struct usb_attach_arg *uaa = device_get_ivars(self);
+ const struct axe_type *type;
u_char eaddr[ETHER_ADDR_LEN];
struct ifnet *ifp;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
int i;
- bzero(sc, sizeof(struct axe_softc));
sc->axe_udev = uaa->device;
sc->axe_dev = self;
- sc->axe_unit = device_get_unit(self);
+ type = axe_lookup(uaa->vendor, uaa->product);
+ if (type != NULL)
+ sc->axe_flags = type->axe_flags;
if (usbd_set_config_no(sc->axe_udev, AXE_CONFIG_NO, 1)) {
- printf("axe%d: getting interface handle failed\n",
- sc->axe_unit);
- USB_ATTACH_ERROR_RETURN;
+ device_printf(sc->axe_dev, "getting interface handle failed\n");
+ return ENXIO;
}
+ usb_init_task(&sc->axe_tick_task, axe_tick_task, sc);
+
if (usbd_device2interface_handle(uaa->device,
AXE_IFACE_IDX, &sc->axe_iface)) {
- printf("axe%d: getting interface handle failed\n",
- sc->axe_unit);
- USB_ATTACH_ERROR_RETURN;
+ device_printf(sc->axe_dev, "getting interface handle failed\n");
+ return ENXIO;
}
- id = usbd_get_interface_descriptor(sc->axe_iface);
+ sc->axe_boundary = 64;
+ if (sc->axe_flags & (AX178|AX772)) {
+ if (sc->axe_udev->speed == USB_SPEED_HIGH) {
+ sc->axe_bufsz = AXE_178_MAX_BUFSZ;
+ sc->axe_boundary = 512;
+ } else
+ sc->axe_bufsz = AXE_178_MIN_BUFSZ;
+ } else
+ sc->axe_bufsz = AXE_172_BUFSZ;
+{ /* XXX debug */
+device_printf(sc->axe_dev, "%s, bufsz %d, boundary %d\n",
+ sc->axe_flags & AX178 ? "AX88178" :
+ sc->axe_flags & AX772 ? "AX88772" : "AX88172",
+ sc->axe_bufsz, sc->axe_boundary);
+}
- usbd_devinfo(uaa->device, 0, devinfo);
- device_set_desc_copy(self, devinfo);
- printf("%s: %s\n", USBDEVNAME(self), devinfo);
+ id = usbd_get_interface_descriptor(sc->axe_iface);
/* Find endpoints. */
for (i = 0; i < id->bNumEndpoints; i++) {
ed = usbd_interface2endpoint_descriptor(sc->axe_iface, i);
if (!ed) {
- printf("axe%d: couldn't get ep %d\n",
- sc->axe_unit, i);
- USB_ATTACH_ERROR_RETURN;
+ device_printf(sc->axe_dev, "couldn't get ep %d\n", i);
+ return ENXIO;
}
if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
@@ -454,18 +600,30 @@
mtx_init(&sc->axe_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
+ sx_init(&sc->axe_sleeplock, device_get_nameunit(self));
+ AXE_SLEEPLOCK(sc);
AXE_LOCK(sc);
+ /* We need the PHYID for the 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_cmd(sc, AXE_CMD_READ_NODEID, 0, 0, &eaddr);
+ if (sc->axe_flags & (AX178|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.
+ * Fetch IPG values.
*/
axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, (void *)&sc->axe_ipgs);
- axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, (void *)&sc->axe_phyaddrs);
/*
* Work around broken adapters that appear to lie about
@@ -475,13 +633,15 @@
ifp = sc->axe_ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
- printf("axe%d: can not if_alloc()\n", sc->axe_unit);
+ device_printf(sc->axe_dev, "can not if_alloc()\n");
AXE_UNLOCK(sc);
+ AXE_SLEEPUNLOCK(sc);
+ sx_destroy(&sc->axe_sleeplock);
mtx_destroy(&sc->axe_mtx);
- USB_ATTACH_ERROR_RETURN;
+ return ENXIO;
}
ifp->if_softc = sc;
- if_initname(ifp, "axe", sc->axe_unit);
+ if_initname(ifp, "axe", device_get_unit(sc->axe_dev));
ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
IFF_NEEDSGIANT;
@@ -493,16 +653,15 @@
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
IFQ_SET_READY(&ifp->if_snd);
- sc->axe_qdat.ifp = ifp;
- sc->axe_qdat.if_rxstart = axe_rxstart;
-
if (mii_phy_probe(self, &sc->axe_miibus,
axe_ifmedia_upd, axe_ifmedia_sts)) {
- printf("axe%d: MII without any PHY!\n", sc->axe_unit);
+ device_printf(sc->axe_dev, "MII without any PHY!\n");
if_free(ifp);
AXE_UNLOCK(sc);
+ AXE_SLEEPUNLOCK(sc);
+ sx_destroy(&sc->axe_sleeplock);
mtx_destroy(&sc->axe_mtx);
- USB_ATTACH_ERROR_RETURN;
+ return ENXIO;
}
/*
@@ -516,12 +675,13 @@
sc->axe_dying = 0;
AXE_UNLOCK(sc);
+ AXE_SLEEPUNLOCK(sc);
- USB_ATTACH_SUCCESS_RETURN;
+ return 0;
}
-Static int
-axe_detach(device_ptr_t dev)
+static int
+axe_detach(device_t dev)
{
struct axe_softc *sc;
struct ifnet *ifp;
@@ -532,6 +692,8 @@
sc->axe_dying = 1;
untimeout(axe_tick, sc, sc->axe_stat_ch);
+ usb_rem_task(sc->axe_udev, &sc->axe_tick_task);
+
ether_ifdetach(ifp);
if_free(ifp);
@@ -543,55 +705,122 @@
usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
AXE_UNLOCK(sc);
+ sx_destroy(&sc->axe_sleeplock);
mtx_destroy(&sc->axe_mtx);
return(0);
}
-Static void
-axe_rxstart(struct ifnet *ifp)
+static int
+axe_rx_list_init(struct axe_softc *sc)
{
- struct axe_softc *sc;
- struct ue_chain *c;
+ struct axe_cdata *cd;
+ struct axe_chain *c;
+ int i;
- sc = ifp->if_softc;
- AXE_LOCK(sc);
- c = &sc->axe_cdata.ue_rx_chain[sc->axe_cdata.ue_rx_prod];
+ cd = &sc->axe_cdata;
+ for (i = 0; i < AXE_RX_LIST_CNT; i++) {
+ c = &cd->axe_rx_chain[i];
+ c->axe_sc = sc;
+ c->axe_idx = i;
+ c->axe_mbuf = NULL;
+ if (c->axe_xfer == NULL) {
+ 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,
+ sc->axe_bufsz);
+ if (c->axe_buf == NULL) {
+ usbd_free_xfer(c->axe_xfer);
+ return (ENOBUFS);
+ }
+ }
+ }
- c->ue_mbuf = usb_ether_newbuf();
- if (c->ue_mbuf == NULL) {
- printf("%s: no memory for rx list "
- "-- packet dropped!\n", USBDEVNAME(sc->axe_dev));
- ifp->if_ierrors++;
- AXE_UNLOCK(sc);
- return;
+ return (0);
+}
+
+static void
+axe_rx_list_free(struct axe_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < AXE_RX_LIST_CNT; i++) {
+ if (sc->axe_cdata.axe_rx_chain[i].axe_mbuf != NULL) {
+ m_freem(sc->axe_cdata.axe_rx_chain[i].axe_mbuf);
+ sc->axe_cdata.axe_rx_chain[i].axe_mbuf = NULL;
+ }
+ if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL) {
+ usbd_free_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer);
+ sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL;
+ }
}
+}
- /* Setup new transfer. */
- usbd_setup_xfer(c->ue_xfer, sc->axe_ep[AXE_ENDPT_RX],
- c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK,
- USBD_NO_TIMEOUT, axe_rxeof);
- usbd_transfer(c->ue_xfer);
- AXE_UNLOCK(sc);
+static int
+axe_tx_list_init(struct axe_softc *sc)
+{
+ struct axe_cdata *cd;
+ struct axe_chain *c;
+ int i;
- return;
+ cd = &sc->axe_cdata;
+ for (i = 0; i < AXE_TX_LIST_CNT; i++) {
+ c = &cd->axe_tx_chain[i];
+ c->axe_sc = sc;
+ c->axe_idx = i;
+ c->axe_mbuf = NULL;
+ if (c->axe_xfer == NULL) {
+ 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,
+ sc->axe_bufsz);
+ if (c->axe_buf == NULL) {
+ usbd_free_xfer(c->axe_xfer);
+ return (ENOBUFS);
+ }
+ }
+ }
+
+ return (0);
+}
+
+static void
+axe_tx_list_free(struct axe_softc *sc)
+{
+ int i;
+
+ /* Free TX resources. */
+ for (i = 0; i < AXE_TX_LIST_CNT; i++) {
+ if (sc->axe_cdata.axe_tx_chain[i].axe_mbuf != NULL) {
+ m_freem(sc->axe_cdata.axe_tx_chain[i].axe_mbuf);
+ sc->axe_cdata.axe_tx_chain[i].axe_mbuf = NULL;
+ }
+ if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL) {
+ usbd_free_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer);
+ sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL;
+ }
+ }
}
/*
* A frame has been uploaded: pass the resulting mbuf chain up to
* the higher level protocols.
*/
-Static void
+static void
axe_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
{
struct axe_softc *sc;
- struct ue_chain *c;
+ struct axe_chain *c = (struct axe_chain *) priv;
struct mbuf *m;
+ u_char *buf;
struct ifnet *ifp;
+ struct axe_sframe_hdr *hdr;
int total_len = 0;
+ int pktlen = 0;
- c = priv;
- sc = c->ue_sc;
+ sc = c->axe_sc;
AXE_LOCK(sc);
ifp = sc->axe_ifp;
@@ -606,7 +835,7 @@
return;
}
if (usbd_ratecheck(&sc->axe_rx_notice))
- printf("axe%d: usb error on rx: %s\n", sc->axe_unit,
+ device_printf(sc->axe_dev, "usb error on rx: %s\n",
usbd_errstr(status));
if (status == USBD_STALLED)
usbd_clear_endpoint_stall(sc->axe_ep[AXE_ENDPT_RX]);
@@ -615,28 +844,61 @@
usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
- m = c->ue_mbuf;
-
- if (total_len < sizeof(struct ether_header)) {
- ifp->if_ierrors++;
- goto done;
- }
+ buf = c->axe_buf;
- ifp->if_ipackets++;
- m->m_pkthdr.rcvif = (void *)&sc->axe_qdat;
- m->m_pkthdr.len = m->m_len = total_len;
+ do {
+ if (sc->axe_flags & (AX178|AX772)) {
+ if (total_len < sizeof(struct axe_sframe_hdr)) {
+ ifp->if_ierrors++;
+ goto done;
+ }
+ if ((pktlen % 2) != 0)
+ pktlen++;
+ buf += pktlen;
+
+ hdr = (struct axe_sframe_hdr *) buf;
+ total_len -= sizeof(struct axe_sframe_hdr);
+ if ((hdr->len ^ hdr->ilen) != 0xffff) {
+ ifp->if_ierrors++;
+ goto done;
+ }
+ pktlen = le16toh(hdr->len);
+ if (pktlen > total_len) {
+ ifp->if_ierrors++;
+ goto done;
+ }
- /* Put the packet on the special USB input queue. */
- usb_ether_input(m);
- AXE_UNLOCK(sc);
+ buf += sizeof(struct axe_sframe_hdr);
+ total_len -= pktlen + (pktlen % 2);
+ } else {
+ pktlen = total_len;
+ total_len = 0;
+ }
- return;
+ if (pktlen < sizeof(struct ether_header)) {
+ ifp->if_ierrors++;
+ goto done;
+ }
+ m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL) {
+ ifp->if_ierrors++;
+ goto done;
+ }
+ m->m_data += ETHER_ALIGN;
+ memcpy(mtod(m, void *), buf, pktlen);
+ m->m_pkthdr.len = m->m_len = pktlen;
+ m->m_pkthdr.rcvif = ifp;
+
+ ifp->if_input(ifp, m);
+ ifp->if_ipackets++;
+ } while (total_len > 0);
+ /* fall thru... */
done:
/* Setup new transfer. */
- usbd_setup_xfer(c->ue_xfer, sc->axe_ep[AXE_ENDPT_RX],
- c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK,
+ usbd_setup_xfer(xfer, sc->axe_ep[AXE_ENDPT_RX],
+ c, c->axe_buf, sc->axe_bufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY,
USBD_NO_TIMEOUT, axe_rxeof);
- usbd_transfer(c->ue_xfer);
+ usbd_transfer(xfer);
AXE_UNLOCK(sc);
return;
@@ -647,16 +909,16 @@
* the list buffers.
*/
-Static void
+static void
axe_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
{
struct axe_softc *sc;
- struct ue_chain *c;
+ struct axe_chain *c;
struct ifnet *ifp;
usbd_status err;
c = priv;
- sc = c->ue_sc;
+ sc = c->axe_sc;
AXE_LOCK(sc);
ifp = sc->axe_ifp;
@@ -665,7 +927,7 @@
AXE_UNLOCK(sc);
return;
}
- printf("axe%d: usb error on tx: %s\n", sc->axe_unit,
+ device_printf(sc->axe_dev, "usb error on tx: %s\n",
usbd_errstr(status));
if (status == USBD_STALLED)
usbd_clear_endpoint_stall(sc->axe_ep[AXE_ENDPT_TX]);
@@ -675,12 +937,11 @@
ifp->if_timer = 0;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err);
+ usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &err);
- if (c->ue_mbuf != NULL) {
- c->ue_mbuf->m_pkthdr.rcvif = ifp;
- usb_tx_done(c->ue_mbuf);
- c->ue_mbuf = NULL;
+ if (c->axe_mbuf != NULL) {
+ m_freem(c->axe_mbuf);
+ c->axe_mbuf = NULL;
}
if (err)
@@ -690,12 +951,29 @@
AXE_UNLOCK(sc);
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ axe_start(ifp);
+
return;
}
-Static void
+static void
axe_tick(void *xsc)
{
+ struct axe_softc *sc = xsc;
+
+ if (sc == NULL)
+ return;
+ if (sc->axe_dying)
+ return;
+
+ /* Perform periodic stuff in process context */
+ usb_add_task(sc->axe_udev, &sc->axe_tick_task);
+}
+
+static void
+axe_tick_task(void *xsc)
+{
struct axe_softc *sc;
struct ifnet *ifp;
struct mii_data *mii;
@@ -705,12 +983,14 @@
if (sc == NULL)
return;
+ AXE_SLEEPLOCK(sc);
AXE_LOCK(sc);
ifp = sc->axe_ifp;
mii = GET_MII(sc);
if (mii == NULL) {
AXE_UNLOCK(sc);
+ AXE_SLEEPUNLOCK(sc);
return;
}
@@ -725,42 +1005,66 @@
sc->axe_stat_ch = timeout(axe_tick, sc, hz);
AXE_UNLOCK(sc);
+ AXE_SLEEPUNLOCK(sc);
return;
}
-Static int
+static int
axe_encap(struct axe_softc *sc, struct mbuf *m, int idx)
{
- struct ue_chain *c;
+ struct axe_chain *c;
usbd_status err;
+ struct axe_sframe_hdr hdr;
+ int length;
- c = &sc->axe_cdata.ue_tx_chain[idx];
+ c = &sc->axe_cdata.axe_tx_chain[idx];
/*
* 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->ue_buf);
- c->ue_mbuf = m;
+ if (sc->axe_flags & (AX178|AX772)) {
+ 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 % sc->axe_boundary) == 0) {
+ hdr.len = 0;
+ 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->ue_xfer, sc->axe_ep[AXE_ENDPT_TX],
- c, c->ue_buf, m->m_pkthdr.len, USBD_FORCE_SHORT_XFER,
- 10000, axe_txeof);
+ usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_TX],
+ c, c->axe_buf, length, USBD_FORCE_SHORT_XFER, 10000, axe_txeof);
/* Transmit */
- err = usbd_transfer(c->ue_xfer);
+ err = usbd_transfer(c->axe_xfer);
if (err != USBD_IN_PROGRESS) {
+ /* XXX probably don't want to sleep here */
+ AXE_SLEEPLOCK(sc);
axe_stop(sc);
+ AXE_SLEEPUNLOCK(sc);
return(EIO);
}
- sc->axe_cdata.ue_tx_cnt++;
+ sc->axe_cdata.axe_tx_cnt++;
return(0);
}
-Static void
+static void
axe_start(struct ifnet *ifp)
{
struct axe_softc *sc;
@@ -809,12 +1113,12 @@
return;
}
-Static void
+static void
axe_init(void *xsc)
{
struct axe_softc *sc = xsc;
struct ifnet *ifp = sc->axe_ifp;
- struct ue_chain *c;
+ struct axe_chain *c;
usbd_status err;
int i;
int rxmode;
@@ -822,6 +1126,7 @@
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
return;
+ AXE_SLEEPLOCK(sc);
AXE_LOCK(sc);
/*
@@ -832,34 +1137,44 @@
#ifdef notdef
/* Set MAC address */
- axe_mac(sc, IFP2ENADDR(sc->axe_ifp), 1);
+ axe_mac(sc, IF_LLADDR(sc->axe_ifp), 1);
#endif
/* Enable RX logic. */
/* Init TX ring. */
- if (usb_ether_tx_list_init(sc, &sc->axe_cdata,
- sc->axe_udev) == ENOBUFS) {
- printf("axe%d: tx list init failed\n", sc->axe_unit);
+ if (axe_tx_list_init(sc) == ENOBUFS) {
+ device_printf(sc->axe_dev, "tx list init failed\n");
AXE_UNLOCK(sc);
+ AXE_SLEEPUNLOCK(sc);
return;
}
/* Init RX ring. */
- if (usb_ether_rx_list_init(sc, &sc->axe_cdata,
- sc->axe_udev) == ENOBUFS) {
- printf("axe%d: rx list init failed\n", sc->axe_unit);
+ if (axe_rx_list_init(sc) == ENOBUFS) {
+ device_printf(sc->axe_dev, "rx list init failed\n");
AXE_UNLOCK(sc);
+ AXE_SLEEPUNLOCK(sc);
return;
}
/* Set transmitter IPG values */
- 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|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|AX772)) {
+ if (sc->axe_bufsz == AXE_178_MAX_BUFSZ)
+ 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)
@@ -877,41 +1192,45 @@
err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_RX],
USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_RX]);
if (err) {
- printf("axe%d: open rx pipe failed: %s\n",
- sc->axe_unit, usbd_errstr(err));
+ device_printf(sc->axe_dev, "open rx pipe failed: %s\n",
+ usbd_errstr(err));
AXE_UNLOCK(sc);
+ AXE_SLEEPUNLOCK(sc);
return;
}
err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_TX],
USBD_EXCLUSIVE_USE, &sc->axe_ep[AXE_ENDPT_TX]);
if (err) {
- printf("axe%d: open tx pipe failed: %s\n",
- sc->axe_unit, usbd_errstr(err));
+ device_printf(sc->axe_dev, "open tx pipe failed: %s\n",
+ usbd_errstr(err));
AXE_UNLOCK(sc);
+ AXE_SLEEPUNLOCK(sc);
return;
}
/* Start up the receive pipe. */
- for (i = 0; i < UE_RX_LIST_CNT; i++) {
- c = &sc->axe_cdata.ue_rx_chain[i];
- usbd_setup_xfer(c->ue_xfer, sc->axe_ep[AXE_ENDPT_RX],
- c, mtod(c->ue_mbuf, char *), UE_BUFSZ,
- USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, axe_rxeof);
- usbd_transfer(c->ue_xfer);
+ 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, c->axe_buf, sc->axe_bufsz,
+ USBD_SHORT_XFER_OK | USBD_NO_COPY,
+ USBD_NO_TIMEOUT, axe_rxeof);
+ usbd_transfer(c->axe_xfer);
}
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
AXE_UNLOCK(sc);
+ AXE_SLEEPUNLOCK(sc);
sc->axe_stat_ch = timeout(axe_tick, sc, hz);
return;
}
-Static int
+static int
axe_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
struct axe_softc *sc = ifp->if_softc;
@@ -926,6 +1245,7 @@
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
ifp->if_flags & IFF_PROMISC &&
!(sc->axe_if_flags & IFF_PROMISC)) {
+ AXE_SLEEPLOCK(sc);
AXE_LOCK(sc);
axe_cmd(sc, AXE_CMD_RXCTL_READ,
0, 0, (void *)&rxmode);
@@ -934,9 +1254,11 @@
0, rxmode, NULL);
AXE_UNLOCK(sc);
axe_setmulti(sc);
+ AXE_SLEEPUNLOCK(sc);
} else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
!(ifp->if_flags & IFF_PROMISC) &&
sc->axe_if_flags & IFF_PROMISC) {
+ AXE_SLEEPLOCK(sc);
AXE_LOCK(sc);
axe_cmd(sc, AXE_CMD_RXCTL_READ,
0, 0, (void *)&rxmode);
@@ -945,24 +1267,32 @@
0, rxmode, NULL);
AXE_UNLOCK(sc);
axe_setmulti(sc);
+ AXE_SLEEPUNLOCK(sc);
} else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
axe_init(sc);
} else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ AXE_SLEEPLOCK(sc);
axe_stop(sc);
+ AXE_SLEEPUNLOCK(sc);
+ }
}
sc->axe_if_flags = ifp->if_flags;
error = 0;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
+ AXE_SLEEPLOCK(sc);
axe_setmulti(sc);
+ AXE_SLEEPUNLOCK(sc);
error = 0;
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
+ AXE_SLEEPLOCK(sc);
mii = GET_MII(sc);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+ AXE_SLEEPUNLOCK(sc);
break;
default:
@@ -970,27 +1300,25 @@
break;
}
- AXE_UNLOCK(sc);
-
return(error);
}
-Static void
+static void
axe_watchdog(struct ifnet *ifp)
{
struct axe_softc *sc;
- struct ue_chain *c;
+ struct axe_chain *c;
usbd_status stat;
sc = ifp->if_softc;
AXE_LOCK(sc);
ifp->if_oerrors++;
- printf("axe%d: watchdog timeout\n", sc->axe_unit);
+ device_printf(sc->axe_dev, "watchdog timeout\n");
- c = &sc->axe_cdata.ue_tx_chain[0];
- usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &stat);
- axe_txeof(c->ue_xfer, c, stat);
+ c = &sc->axe_cdata.axe_tx_chain[0];
+ usbd_get_xfer_status(c->axe_xfer, NULL, NULL, NULL, &stat);
+ axe_txeof(c->axe_xfer, c, stat);
AXE_UNLOCK(sc);
@@ -1004,12 +1332,13 @@
* Stop the adapter and free any mbufs allocated to the
* RX and TX lists.
*/
-Static void
+static void
axe_stop(struct axe_softc *sc)
{
usbd_status err;
struct ifnet *ifp;
+ AXE_SLEEPLOCKASSERT(sc);
AXE_LOCK(sc);
ifp = sc->axe_ifp;
@@ -1021,13 +1350,13 @@
if (sc->axe_ep[AXE_ENDPT_RX] != NULL) {
err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX]);
if (err) {
- printf("axe%d: abort rx pipe failed: %s\n",
- sc->axe_unit, usbd_errstr(err));
+ device_printf(sc->axe_dev, "abort rx pipe failed: %s\n",
+ usbd_errstr(err));
}
err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_RX]);
if (err) {
- printf("axe%d: close rx pipe failed: %s\n",
- sc->axe_unit, usbd_errstr(err));
+ device_printf(sc->axe_dev, "close rx pipe failed: %s\n",
+ usbd_errstr(err));
}
sc->axe_ep[AXE_ENDPT_RX] = NULL;
}
@@ -1035,13 +1364,13 @@
if (sc->axe_ep[AXE_ENDPT_TX] != NULL) {
err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX]);
if (err) {
- printf("axe%d: abort tx pipe failed: %s\n",
- sc->axe_unit, usbd_errstr(err));
+ device_printf(sc->axe_dev, "abort tx pipe failed: %s\n",
+ usbd_errstr(err));
}
err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_TX]);
if (err) {
- printf("axe%d: close tx pipe failed: %s\n",
- sc->axe_unit, usbd_errstr(err));
+ device_printf(sc->axe_dev, "close tx pipe failed: %s\n",
+ usbd_errstr(err));
}
sc->axe_ep[AXE_ENDPT_TX] = NULL;
}
@@ -1049,13 +1378,13 @@
if (sc->axe_ep[AXE_ENDPT_INTR] != NULL) {
err = usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
if (err) {
- printf("axe%d: abort intr pipe failed: %s\n",
- sc->axe_unit, usbd_errstr(err));
+ device_printf(sc->axe_dev,
+ "abort intr pipe failed: %s\n", usbd_errstr(err));
}
err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_INTR]);
if (err) {
- printf("axe%d: close intr pipe failed: %s\n",
- sc->axe_unit, usbd_errstr(err));
+ device_printf(sc->axe_dev,
+ "close intr pipe failed: %s\n", usbd_errstr(err));
}
sc->axe_ep[AXE_ENDPT_INTR] = NULL;
}
@@ -1063,9 +1392,9 @@
axe_reset(sc);
/* Free RX resources. */
- usb_ether_rx_list_free(&sc->axe_cdata);
+ axe_rx_list_free(sc);
/* Free TX resources. */
- usb_ether_tx_list_free(&sc->axe_cdata);
+ axe_tx_list_free(sc);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->axe_link = 0;
@@ -1078,14 +1407,16 @@
* Stop all chip I/O so that the kernel's probe routines don't
* get confused by errant DMAs when rebooting.
*/
-Static void
-axe_shutdown(device_ptr_t dev)
+static int
+axe_shutdown(device_t dev)
{
struct axe_softc *sc;
sc = device_get_softc(dev);
+ AXE_SLEEPLOCK(sc);
axe_stop(sc);
+ AXE_SLEEPUNLOCK(sc);
- return;
+ return (0);
}
--- dev/usb/if_axereg.h.orig 2008-01-18 18:04:21.000000000 +0000
+++ dev/usb/if_axereg.h 2008-01-18 18:04:36.000000000 +0000
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/usb/if_axereg.h,v 1.8.2.1 2007/05/21 18:10:48 brueffer Exp $
+ * $FreeBSD: src/sys/dev/usb/if_axereg.h,v 1.17 2007/11/10 16:23:38 sam Exp $
*/
/*
@@ -53,9 +53,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 0x8002
+#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
@@ -68,35 +70,115 @@
#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_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/88772 documentation says to always write 1 to bit 2 */
+#define AXE_178_MEDIA_MAGIC 0x0004
+/* AX88772 documentation says to always write 0 to bit 3 */
+#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_178_RXCMD_AP 0x0020
#define AXE_RXCMD_ENABLE 0x0080
+#define AXE_178_RXCMD_MFB_2048 0x0000 /* 2K max frame burst */
+#define AXE_178_RXCMD_MFB_4096 0x0100 /* 4K max frame burst */
+#define AXE_178_RXCMD_MFB_8192 0x0200 /* 8K max frame burst */
+#define AXE_178_RXCMD_MFB_16384 0x0300 /* 16K max frame burst*/
#define AXE_NOPHY 0xE0
+#define AXE_INTPHY 0x10
#define AXE_TIMEOUT 1000
+#define AXE_172_BUFSZ 1536
+#define AXE_178_MIN_BUFSZ 2048
#define AXE_MIN_FRAMELEN 60
#define AXE_RX_FRAMES 1
#define AXE_TX_FRAMES 1
+#if AXE_178_MAX_FRAME_BURST == 0
+#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_2048
+#define AXE_178_MAX_BUFSZ 2048
+#elif AXE_178_MAX_FRAME_BURST == 1
+#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_4096
+#define AXE_178_MAX_BUFSZ 4096
+#elif AXE_178_MAX_FRAME_BURST == 2
+#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_8192
+#define AXE_178_MAX_BUFSZ 8192
+#else
+#define AXE_178_RXCMD_MFB AXE_178_RXCMD_MFB_16384
+#define AXE_178_MAX_BUFSZ 16384
+#endif
+
+#define AXE_RX_LIST_CNT 1
+#define AXE_TX_LIST_CNT 1
+
+struct axe_chain {
+ struct axe_softc *axe_sc;
+ usbd_xfer_handle axe_xfer;
+ char *axe_buf;
+ struct mbuf *axe_mbuf;
+ int axe_accum;
+ int axe_idx;
+};
+
+struct axe_cdata {
+ struct axe_chain axe_tx_chain[AXE_TX_LIST_CNT];
+ struct axe_chain axe_rx_chain[AXE_RX_LIST_CNT];
+ int axe_tx_prod;
+ int axe_tx_cons;
+ int axe_tx_cnt;
+ int axe_rx_prod;
+};
+
#define AXE_CTL_READ 0x01
#define AXE_CTL_WRITE 0x02
@@ -112,9 +194,17 @@
#define AXE_ENDPT_INTR 0x2
#define AXE_ENDPT_MAX 0x3
+struct axe_sframe_hdr {
+ uint16_t len;
+ uint16_t ilen;
+} __packed;
+
struct axe_type {
- u_int16_t axe_vid;
- u_int16_t axe_did;
+ struct usb_devno axe_dev;
+ uint32_t axe_flags;
+#define AX172 0x0000 /* AX88172 */
+#define AX178 0x0001 /* AX88178 */
+#define AX772 0x0002 /* AX88772 */
};
#define AXE_INC(x, y) (x) = (x + 1) % y
@@ -132,19 +222,24 @@
device_t axe_dev;
usbd_device_handle axe_udev;
usbd_interface_handle axe_iface;
+ 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];
- int axe_unit;
int axe_if_flags;
- struct ue_cdata axe_cdata;
+ struct axe_cdata axe_cdata;
struct callout_handle axe_stat_ch;
struct mtx axe_mtx;
+ struct sx axe_sleeplock;
char axe_dying;
int axe_link;
unsigned char axe_ipgs[3];
unsigned char axe_phyaddrs[2];
struct timeval axe_rx_notice;
- struct usb_qdat axe_qdat;
+ struct usb_task axe_tick_task;
+ int axe_bufsz;
+ int axe_boundary;
};
#if 0
@@ -154,3 +249,6 @@
#define AXE_LOCK(_sc)
#define AXE_UNLOCK(_sc)
#endif
+#define AXE_SLEEPLOCK(_sc) sx_xlock(&(_sc)->axe_sleeplock)
+#define AXE_SLEEPUNLOCK(_sc) sx_xunlock(&(_sc)->axe_sleeplock)
+#define AXE_SLEEPLOCKASSERT(_sc) sx_assert(&(_sc)->axe_sleeplock, SX_XLOCKED)
--- dev/usb/usbdevs.orig 2008-01-18 18:04:29.000000000 +0000
+++ dev/usb/usbdevs 2008-01-18 18:14:44.000000000 +0000
@@ -481,6 +481,7 @@
vendor ACDC 0x0d7e ACDC
vendor ABC 0x0d8c ABC
vendor MSI 0x0db0 Micro Star International
+vendor SITECOMEU 0x0df6 Sitecom Europe
vendor HAWKING 0x0e66 Hawking
vendor GMATE 0x0e7e G.Mate, Inc
vendor OTI 0x0ea0 Ours
@@ -518,16 +519,20 @@
vendor RALINK 0x148f Ralink Technology
vendor IMAGINATION 0x149a Imagination Technologies
vendor CONCEPTRONIC 0x14b2 Conceptronic
+vendor PLANEX3 0x14ea Planex Communications
vendor SILICONPORTALS 0x1527 Silicon Portals
vendor UBIQUAM 0x1529 UBIQUAM Co., Ltd.
vendor PNY 0x154b PNY
+vendor OQO 0x1557 OQO
vendor SOHOWARE 0x15e8 SOHOware
vendor UMAX 0x1606 UMAX
vendor INSIDEOUT 0x1608 Inside Out Networks
+vendor GOODWAY 0x1631 Good Way Technology
vendor ENTREGA 0x1645 Entrega
vendor ACTIONTEC 0x1668 Actiontec
vendor ANYDATA 0x16d5 AnyData Corporation
vendor CMOTECH 0x16d8 CMOTECH CO., LTD.
+vendor LINKSYS5 0x1737 Linksys
vendor LINKSYS3 0x1915 Linksys
vendor DLINK 0x2001 D-Link
vendor ERICSSON 0x2282 Ericsson
@@ -584,6 +589,7 @@
product ABOCOM XX7 0x400c XX7
product ABOCOM XX8 0x4102 XX8
product ABOCOM XX9 0x4104 XX9
+product ABOCOM UF200 0x420a UF200 Ethernet
product ABOCOM XX10 0xabc1 XX10
/* Accton products */
@@ -593,6 +599,9 @@
/* Aceeca products */
product ACEECA MEZ1000 0x0001 Aceeca Mez1000 RDA
+/* Acer Communications & Multimedia (oemd by Surecom) */
+product ACERCM EP1427X2 0x0893 EP-1427X-2 Ethernet Adapter
+
/* Acer Peripherals, Inc. products */
product ACERP ACERSCAN_C310U 0x12a6 Acerscan C310U
product ACERP ACERSCAN_320U 0x2022 Acerscan 320U
@@ -694,6 +703,8 @@
/* ASIX Electronics products */
product ASIX AX88172 0x1720 10/100 ethernet
+product ASIX AX88178 0x1780 AX88178
+product ASIX AX88772 0x7720 AX88772
/* ASUS products */
product ASUS WL167G 0x1707 WL-167g wireless adapter
@@ -701,6 +712,8 @@
/* ATen products */
product ATEN UC1284 0x2001 Parallel printer
product ATEN UC10T 0x2002 10Mbps ethernet
+product ATEN UC110T 0x2007 UC-110T Ethernet
+product ATEN UC210T 0x2009 UC-210T Ethernet
product ATEN UC232A 0x2008 Serial
/* Atmel Comp. products */
@@ -726,6 +739,7 @@
product BELKIN F5U409 0x0409 F5U409 Serial
product BELKIN F6C550AVR 0x0551 F6C550-AVR UPS
product BELKIN F5U120 0x1203 F5U120-PC Hub
+product BELKIN F5D5055 0x5055 F5D5055
product BELKIN F5D7050 0x7050 F5D7050 wireless adapter
/* Billionton products */
@@ -733,6 +747,7 @@
product BILLIONTON USBLP100 0x0987 USB100LP
product BILLIONTON USBEL100 0x0988 USB100EL
product BILLIONTON USBE100 0x8511 USBE100
+product BILLIONTON USB2AR 0x90ff USB2AR Ethernet
/* Broadcom products */
product BROADCOM BCM2033 0x2033 BCM2033 Bluetooth USB dongle
@@ -790,6 +805,7 @@
product COREGA ETHER_USB_T 0x0001 Ether USB-T
product COREGA FETHER_USB_TX 0x0004 FEther USB-TX
product COREGA FETHER_USB_TXS 0x000d FEther USB-TXS
+product COREGA FETHER_USB2_TX 0x0017 FEther USB2-TX
product COREGA FETHER_USB_TXC 0x9601 FEther USB-TXC
/* Creative products */
@@ -850,6 +866,7 @@
product DLINK DUBE100 0x1a00 10/100 ethernet
product DLINK DSB650TX4 0x200c 10/100 ethernet
product DLINK DWLG122 0x3c00 DWL-G122 b1 wireless adapter
+product DLINK DUBE100B1 0x3c05 DUB-E100 rev B1
product DLINK DSB650C 0x4000 10Mbps ethernet
product DLINK DSB650TX1 0x4001 10/100 ethernet
product DLINK DSB650TX 0x4002 10/100 ethernet
@@ -931,6 +948,9 @@
/* GoHubs products */
product GOHUBS GOCOM232 0x1001 GoCOM232 Serial
+/* Good Way Technology products */
+product GOODWAY GWUSB2E 0x6200 GWUSB2E
+
/* Gravis products */
product GRAVIS GAMEPADPRO 0x4001 GamePad Pro
@@ -1078,6 +1098,7 @@
product IODATA USBETT 0x0901 USB ETT
product IODATA USBETTX 0x0904 USB ETTX
product IODATA USBETTXS 0x0913 USB ETTX
+product IODATA ETGUS2 0x0930 ETG-US2
product IODATA USBRSAQ 0x0a03 Serial USB-RSAQ1
/* Iomega products */
@@ -1184,7 +1205,10 @@
product LINKSYS3 WUSB11v28 0x2233 WUSB11 v2.8 wireless adapter
product LINKSYS4 WUSB54G 0x000d WUSB54G wireless adapter
product LINKSYS4 WUSB54GP 0x0011 WUSB54GP wireless adapter
+product LINKSYS4 USB200MV2 0x0018 USB200M v2
product LINKSYS4 HU200TS 0x001a HU200TS wireless adapter
+product LINKSYS5 USB1000 0x0039 USB1000
+
/* Logitech products */
product LOGITECH M2452 0x0203 M2452 keyboard
@@ -1370,6 +1394,9 @@
/* OnSpec Electronic, Inc. */
product ONSPEC UCF100 0xa400 FlashLink UCF-100 CompactFlash Reader
+/* OQO */
+product OQO ETHER01PLUS 0x7720 model 01+ Ethernet
+
/* Palm Computing, Inc. product */
product PALM SERIAL 0x0080 USB Serial
product PALM M500 0x0001 Palm m500
@@ -1412,6 +1439,9 @@
/* P.I. Engineering products */
product PIENGINEERING PS2USB 0x020b PS2 to Mac USB Adapter
+/* Planex Communications products */
+product PLANEX3 GU1000T 0xab11 GU-1000T
+
/* Plextor Corp. */
product PLEXTOR 40_12_40U 0x0011 PlexWriter 40/12/40U
@@ -1561,6 +1591,9 @@
product SITECOM LN029 0x182d USB 2.0 Ethernet
product SITECOM SERIAL 0x2068 USB to serial cable (v2)
+/* Sitecom Europe products */
+product SITECOMEU LN028 0x061c LN-028
+
/* SmartBridges products */
product SMARTBRIDGES SMARTLINK 0x0001 SmartLink USB ethernet
product SMARTBRIDGES SMARTNIC 0x0003 smartNIC 2 PnP ethernet
More information about the freebsd-usb
mailing list