Date: Fri, 18 Jan 2008 18:40:57 +0200 From: Oleksandr Tymoshenko <gonzo@pbxpress.com> To: freebsd-usb@freebsd.org Subject: Re: Call for testers: AXE88x78 support for RELENG_6 Message-ID: <4790D699.9000403@pbxpress.com> In-Reply-To: <4790D5E3.40008@pbxpress.com> References: <4790D5E3.40008@pbxpress.com>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------010506070101090909000909 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 --------------010506070101090909000909 Content-Type: text/plain; name="if_axe.88x78.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="if_axe.88x78.diff" --- 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 --------------010506070101090909000909--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4790D699.9000403>