if_axe.c revision 192502
11573Srgrimes/*- 21573Srgrimes * Copyright (c) 1997, 1998, 1999, 2000-2003 31573Srgrimes * Bill Paul <wpaul@windriver.com>. All rights reserved. 41573Srgrimes * 51573Srgrimes * Redistribution and use in source and binary forms, with or without 61573Srgrimes * modification, are permitted provided that the following conditions 71573Srgrimes * are met: 81573Srgrimes * 1. Redistributions of source code must retain the above copyright 91573Srgrimes * notice, this list of conditions and the following disclaimer. 101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111573Srgrimes * notice, this list of conditions and the following disclaimer in the 121573Srgrimes * documentation and/or other materials provided with the distribution. 131573Srgrimes * 3. All advertising materials mentioning features or use of this software 141573Srgrimes * must display the following acknowledgement: 151573Srgrimes * This product includes software developed by Bill Paul. 161573Srgrimes * 4. Neither the name of the author nor the names of any co-contributors 171573Srgrimes * may be used to endorse or promote products derived from this software 181573Srgrimes * without specific prior written permission. 191573Srgrimes * 201573Srgrimes * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 241573Srgrimes * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 251573Srgrimes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 261573Srgrimes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 271573Srgrimes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2854770Sgreen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2954770Sgreen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 301573Srgrimes * THE POSSIBILITY OF SUCH DAMAGE. 311573Srgrimes */ 32129184Sbde 331573Srgrimes#include <sys/cdefs.h> 3423668Speter__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_axe.c 192502 2009-05-21 01:48:42Z thompsa $"); 351573Srgrimes 36129184Sbde/* 37129184Sbde * ASIX Electronics AX88172/AX88178/AX88778 USB 2.0 ethernet driver. 3890045Sobrien * Used in the LinkSys USB200M and various other adapters. 3990045Sobrien * 401573Srgrimes * Manuals available from: 4171579Sdeischen * http://www.asix.com.tw/datasheet/mac/Ax88172.PDF 421573Srgrimes * Note: you need the manual for the AX88170 chip (USB 1.x ethernet 43129161Speadar * controller) to find the definitions for the RX control register. 441573Srgrimes * http://www.asix.com.tw/datasheet/mac/Ax88170.PDF 451573Srgrimes * 461573Srgrimes * Written by Bill Paul <wpaul@windriver.com> 471573Srgrimes * Senior Engineer 481573Srgrimes * Wind River Systems 491573Srgrimes */ 501573Srgrimes 511573Srgrimes/* 52175688Syar * The AX88172 provides USB ethernet supports at 10 and 100Mbps. 5371579Sdeischen * It uses an external PHY (reference designs use a RealTek chip), 541573Srgrimes * and has a 64-bit multicast hash filter. There is some information 55235647Sgleb * missing from the manual which one needs to know in order to make 56235647Sgleb * the chip function: 57175688Syar * 58175688Syar * - You must set bit 7 in the RX control register, otherwise the 59175688Syar * chip won't receive any packets. 60175688Syar * - You must initialize all 3 IPG registers, or you won't be able 61175688Syar * to send any packets. 62175688Syar * 63175688Syar * Note that this device appears to only support loading the station 64175688Syar * address via autload from the EEPROM (i.e. there's no way to manaully 65175688Syar * set it). 66175688Syar * 6790045Sobrien * (Adam Weinberger wanted me to name this driver if_gir.c.) 6890045Sobrien */ 6990045Sobrien 7090045Sobrien/* 7190045Sobrien * Ax88178 and Ax88772 support backported from the OpenBSD driver. 7290045Sobrien * 2007/02/12, J.R. Oldroyd, fbsd@opal.com 7390045Sobrien * 7490045Sobrien * Manual here: 7590045Sobrien * http://www.asix.com.tw/FrootAttach/datasheet/AX88178_datasheet_Rev10.pdf 7690045Sobrien * http://www.asix.com.tw/FrootAttach/datasheet/AX88772_datasheet_Rev10.pdf 77129161Speadar */ 781573Srgrimes 7928913Simp#include "usbdevs.h" 801573Srgrimes#include <dev/usb/usb.h> 8128913Simp#include <dev/usb/usb_mfunc.h> 8228913Simp#include <dev/usb/usb_error.h> 8328913Simp 841573Srgrimes#define USB_DEBUG_VAR axe_debug 851573Srgrimes 861573Srgrimes#include <dev/usb/usb_core.h> 871573Srgrimes#include <dev/usb/usb_lookup.h> 881573Srgrimes#include <dev/usb/usb_process.h> 891573Srgrimes#include <dev/usb/usb_debug.h> 901573Srgrimes#include <dev/usb/usb_request.h> 911573Srgrimes#include <dev/usb/usb_busdma.h> 92129052Speadar#include <dev/usb/usb_util.h> 93129161Speadar 94129161Speadar#include <dev/usb/net/usb_ethernet.h> 95129161Speadar#include <dev/usb/net/if_axereg.h> 96129052Speadar 97129052Speadar/* 98129161Speadar * AXE_178_MAX_FRAME_BURST 99129161Speadar * max frame burst size for Ax88178 and Ax88772 100129161Speadar * 0 2048 bytes 101129161Speadar * 1 4096 bytes 102129052Speadar * 2 8192 bytes 103129052Speadar * 3 16384 bytes 104129052Speadar * use the largest your system can handle without USB stalling. 105129161Speadar * 106129161Speadar * NB: 88772 parts appear to generate lots of input errors with 107129161Speadar * a 2K rx buffer and 8K is only slightly faster than 4K on an 108129161Speadar * EHCI port on a T42 so change at your own risk. 109129161Speadar */ 110129161Speadar#define AXE_178_MAX_FRAME_BURST 1 111129052Speadar 112129052Speadar#if USB_DEBUG 113129052Speadarstatic int axe_debug = 0; 114129052Speadar 115219696SpjdSYSCTL_NODE(_hw_usb, OID_AUTO, axe, CTLFLAG_RW, 0, "USB axe"); 116129052SpeadarSYSCTL_INT(_hw_usb_axe, OID_AUTO, debug, CTLFLAG_RW, &axe_debug, 0, 117129052Speadar "Debug level"); 118129052Speadar#endif 119129052Speadar 120129052Speadar/* 121129052Speadar * Various supported device vendors/products. 1221573Srgrimes */ 123175688Syarstatic const struct usb2_device_id axe_devs[] = { 1241573Srgrimes {USB_VPI(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UF200, 0)}, 12590045Sobrien {USB_VPI(USB_VENDOR_ACERCM, USB_PRODUCT_ACERCM_EP1427X2, 0)}, 126103726Swollman {USB_VPI(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_ETHERNET, AXE_FLAG_772)}, 1271573Srgrimes {USB_VPI(USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88172, 0)}, 128129052Speadar {USB_VPI(USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88178, AXE_FLAG_178)}, 12990045Sobrien {USB_VPI(USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772, AXE_FLAG_772)}, 13090045Sobrien {USB_VPI(USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC210T, 0)}, 13190045Sobrien {USB_VPI(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D5055, AXE_FLAG_178)}, 1321573Srgrimes {USB_VPI(USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USB2AR, 0)}, 1331573Srgrimes {USB_VPI(USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_USB200MV2, AXE_FLAG_772)}, 1341573Srgrimes {USB_VPI(USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB2_TX, 0)}, 1351573Srgrimes {USB_VPI(USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100, 0)}, 1361573Srgrimes {USB_VPI(USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100B1, AXE_FLAG_772)}, 1371573Srgrimes {USB_VPI(USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_GWUSB2E, 0)}, 1381573Srgrimes {USB_VPI(USB_VENDOR_IODATA, USB_PRODUCT_IODATA_ETGUS2, AXE_FLAG_178)}, 1391573Srgrimes {USB_VPI(USB_VENDOR_JVC, USB_PRODUCT_JVC_MP_PRX1, 0)}, 1401573Srgrimes {USB_VPI(USB_VENDOR_LINKSYS2, USB_PRODUCT_LINKSYS2_USB200M, 0)}, 141129184Sbde {USB_VPI(USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_USB1000, AXE_FLAG_178)}, 142129161Speadar {USB_VPI(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAU2KTX, 0)}, 1431573Srgrimes {USB_VPI(USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA120, 0)}, 144129161Speadar {USB_VPI(USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01PLUS, AXE_FLAG_772)}, 145129052Speadar {USB_VPI(USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GU1000T, AXE_FLAG_178)}, 1461573Srgrimes {USB_VPI(USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_LN029, 0)}, 1471573Srgrimes {USB_VPI(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN028, AXE_FLAG_178)}, 1481573Srgrimes {USB_VPI(USB_VENDOR_SYSTEMTALKS, USB_PRODUCT_SYSTEMTALKS_SGCX2UL, 0)}, 14954770Sgreen}; 15054770Sgreen 15154770Sgreenstatic device_probe_t axe_probe; 1521573Srgrimesstatic device_attach_t axe_attach; 1531573Srgrimesstatic device_detach_t axe_detach; 1541573Srgrimes 1551573Srgrimesstatic usb2_callback_t axe_intr_callback; 1561573Srgrimesstatic usb2_callback_t axe_bulk_read_callback; 1571573Srgrimesstatic usb2_callback_t axe_bulk_write_callback; 1581573Srgrimes 1591573Srgrimesstatic miibus_readreg_t axe_miibus_readreg; 1601573Srgrimesstatic miibus_writereg_t axe_miibus_writereg; 1611573Srgrimesstatic miibus_statchg_t axe_miibus_statchg; 1621573Srgrimes 1631573Srgrimesstatic usb2_ether_fn_t axe_attach_post; 1641573Srgrimesstatic usb2_ether_fn_t axe_init; 1651573Srgrimesstatic usb2_ether_fn_t axe_stop; 1661573Srgrimesstatic usb2_ether_fn_t axe_start; 1671573Srgrimesstatic usb2_ether_fn_t axe_tick; 1681573Srgrimesstatic usb2_ether_fn_t axe_setmulti; 16964740Sgreenstatic usb2_ether_fn_t axe_setpromisc; 1701573Srgrimes 1711573Srgrimesstatic int axe_ifmedia_upd(struct ifnet *); 1721573Srgrimesstatic void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *); 1731573Srgrimesstatic int axe_cmd(struct axe_softc *, int, int, int, void *); 1741573Srgrimesstatic void axe_ax88178_init(struct axe_softc *); 1751573Srgrimesstatic void axe_ax88772_init(struct axe_softc *); 1761573Srgrimesstatic int axe_get_phyno(struct axe_softc *, int); 1771573Srgrimes 1781573Srgrimesstatic const struct usb2_config axe_config[AXE_N_TRANSFER] = { 1791573Srgrimes 1801573Srgrimes [AXE_BULK_DT_WR] = { 1811573Srgrimes .type = UE_BULK, 1821573Srgrimes .endpoint = UE_ADDR_ANY, 1831573Srgrimes .direction = UE_DIR_OUT, 1841573Srgrimes .bufsize = AXE_BULK_BUF_SIZE, 1851573Srgrimes .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 1861573Srgrimes .callback = axe_bulk_write_callback, 1871573Srgrimes .timeout = 10000, /* 10 seconds */ 1881573Srgrimes }, 1891573Srgrimes 1901573Srgrimes [AXE_BULK_DT_RD] = { 1911573Srgrimes .type = UE_BULK, 1921573Srgrimes .endpoint = UE_ADDR_ANY, 1931573Srgrimes .direction = UE_DIR_IN, 1941573Srgrimes#if (MCLBYTES < 2048) 1951573Srgrimes#error "(MCLBYTES < 2048)" 1961573Srgrimes#endif 1971573Srgrimes .bufsize = MCLBYTES, 1981573Srgrimes .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 1991573Srgrimes .callback = axe_bulk_read_callback, 2001573Srgrimes .timeout = 0, /* no timeout */ 2011573Srgrimes }, 2021573Srgrimes 2031573Srgrimes [AXE_INTR_DT_RD] = { 2041573Srgrimes .type = UE_INTERRUPT, 2051573Srgrimes .endpoint = UE_ADDR_ANY, 2061573Srgrimes .direction = UE_DIR_IN, 2071573Srgrimes .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 2081573Srgrimes .bufsize = 0, /* use wMaxPacketSize */ 2091573Srgrimes .callback = axe_intr_callback, 2101573Srgrimes }, 2111573Srgrimes}; 2121573Srgrimes 2131573Srgrimesstatic device_method_t axe_methods[] = { 2141573Srgrimes /* Device interface */ 2151573Srgrimes DEVMETHOD(device_probe, axe_probe), 2161573Srgrimes DEVMETHOD(device_attach, axe_attach), 21754770Sgreen DEVMETHOD(device_detach, axe_detach), 2181573Srgrimes 2191573Srgrimes /* bus interface */ 2201573Srgrimes DEVMETHOD(bus_print_child, bus_generic_print_child), 2211573Srgrimes DEVMETHOD(bus_driver_added, bus_generic_driver_added), 2221573Srgrimes 223241010Sjilles /* MII interface */ 224241010Sjilles DEVMETHOD(miibus_readreg, axe_miibus_readreg), 2251573Srgrimes DEVMETHOD(miibus_writereg, axe_miibus_writereg), 2261573Srgrimes DEVMETHOD(miibus_statchg, axe_miibus_statchg), 2271573Srgrimes 2281573Srgrimes {0, 0} 2291573Srgrimes}; 2301573Srgrimes 2311573Srgrimesstatic driver_t axe_driver = { 2321573Srgrimes .name = "axe", 2331573Srgrimes .methods = axe_methods, 2341573Srgrimes .size = sizeof(struct axe_softc), 2351573Srgrimes}; 2361573Srgrimes 2371573Srgrimesstatic devclass_t axe_devclass; 2381573Srgrimes 23990045SobrienDRIVER_MODULE(axe, uhub, axe_driver, axe_devclass, NULL, 0); 2401573SrgrimesDRIVER_MODULE(miibus, axe, miibus_driver, miibus_devclass, 0, 0); 24190045SobrienMODULE_DEPEND(axe, uether, 1, 1, 1); 24290045SobrienMODULE_DEPEND(axe, usb, 1, 1, 1); 2431573SrgrimesMODULE_DEPEND(axe, ether, 1, 1, 1); 2441573SrgrimesMODULE_DEPEND(axe, miibus, 1, 1, 1); 2451573Srgrimes 2461573Srgrimesstatic const struct usb2_ether_methods axe_ue_methods = { 2471573Srgrimes .ue_attach_post = axe_attach_post, 2481573Srgrimes .ue_start = axe_start, 2491573Srgrimes .ue_init = axe_init, 2501573Srgrimes .ue_stop = axe_stop, 2511573Srgrimes .ue_tick = axe_tick, 2521573Srgrimes .ue_setmulti = axe_setmulti, 2531573Srgrimes .ue_setpromisc = axe_setpromisc, 2541573Srgrimes .ue_mii_upd = axe_ifmedia_upd, 2551573Srgrimes .ue_mii_sts = axe_ifmedia_sts, 2561573Srgrimes}; 2571573Srgrimes 2581573Srgrimesstatic int 2591573Srgrimesaxe_cmd(struct axe_softc *sc, int cmd, int index, int val, void *buf) 2601573Srgrimes{ 2611573Srgrimes struct usb2_device_request req; 2621573Srgrimes usb2_error_t err; 263175688Syar 2641573Srgrimes AXE_LOCK_ASSERT(sc, MA_OWNED); 2651573Srgrimes 26690045Sobrien req.bmRequestType = (AXE_CMD_IS_WRITE(cmd) ? 2671573Srgrimes UT_WRITE_VENDOR_DEVICE : 2681573Srgrimes UT_READ_VENDOR_DEVICE); 2691573Srgrimes req.bRequest = AXE_CMD_CMD(cmd); 2701573Srgrimes USETW(req.wValue, val); 2711573Srgrimes USETW(req.wIndex, index); 2721573Srgrimes USETW(req.wLength, AXE_CMD_LEN(cmd)); 2731573Srgrimes 2741573Srgrimes err = usb2_ether_do_request(&sc->sc_ue, &req, buf, 1000); 2751573Srgrimes 2761573Srgrimes return (err); 27764740Sgreen} 2781573Srgrimes 2791573Srgrimesstatic int 2801573Srgrimesaxe_miibus_readreg(device_t dev, int phy, int reg) 2811573Srgrimes{ 2821573Srgrimes struct axe_softc *sc = device_get_softc(dev); 2831573Srgrimes uint16_t val; 2841573Srgrimes int locked; 2851573Srgrimes 2861573Srgrimes if (sc->sc_phyno != phy) 2871573Srgrimes return (0); 2881573Srgrimes 2891573Srgrimes locked = mtx_owned(&sc->sc_mtx); 2901573Srgrimes if (!locked) 2911573Srgrimes AXE_LOCK(sc); 2921573Srgrimes 29356698Sjasone axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); 29454770Sgreen axe_cmd(sc, AXE_CMD_MII_READ_REG, reg, phy, &val); 29554770Sgreen axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL); 29654770Sgreen 29754770Sgreen val = le16toh(val); 29854770Sgreen if ((sc->sc_flags & AXE_FLAG_772) != 0 && reg == MII_BMSR) { 29954770Sgreen /* 30054770Sgreen * BMSR of AX88772 indicates that it supports extended 30154770Sgreen * capability but the extended status register is 3021573Srgrimes * revered for embedded ethernet PHY. So clear the 3031573Srgrimes * extended capability bit of BMSR. 30437349Sphk */ 30537349Sphk val &= ~BMSR_EXTCAP; 3061573Srgrimes } 3071573Srgrimes 3081573Srgrimes if (!locked) 3091573Srgrimes AXE_UNLOCK(sc); 31028913Simp return (val); 31128913Simp} 3121573Srgrimes 3131573Srgrimesstatic int 31428913Simpaxe_miibus_writereg(device_t dev, int phy, int reg, int val) 31528913Simp{ 3161573Srgrimes struct axe_softc *sc = device_get_softc(dev); 3171573Srgrimes int locked; 318175688Syar 31990045Sobrien val = htole32(val); 3201573Srgrimes 32190045Sobrien if (sc->sc_phyno != phy) 32290045Sobrien return (0); 32390045Sobrien 3241573Srgrimes locked = mtx_owned(&sc->sc_mtx); 3251573Srgrimes if (!locked) 3261573Srgrimes AXE_LOCK(sc); 3271573Srgrimes 3281573Srgrimes axe_cmd(sc, AXE_CMD_MII_OPMODE_SW, 0, 0, NULL); 3291573Srgrimes axe_cmd(sc, AXE_CMD_MII_WRITE_REG, reg, phy, &val); 3301573Srgrimes axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL); 3311573Srgrimes 3321573Srgrimes if (!locked) 3331573Srgrimes AXE_UNLOCK(sc); 3341573Srgrimes return (0); 3351573Srgrimes} 3361573Srgrimes 3371573Srgrimesstatic void 3381573Srgrimesaxe_miibus_statchg(device_t dev) 3391573Srgrimes{ 3401573Srgrimes struct axe_softc *sc = device_get_softc(dev); 3411573Srgrimes struct mii_data *mii = GET_MII(sc); 3421573Srgrimes struct ifnet *ifp; 3431573Srgrimes uint16_t val; 3441573Srgrimes int err, locked; 3451573Srgrimes 3461573Srgrimes locked = mtx_owned(&sc->sc_mtx); 3471573Srgrimes if (!locked) 3481573Srgrimes AXE_LOCK(sc); 3491573Srgrimes 3501573Srgrimes ifp = usb2_ether_getifp(&sc->sc_ue); 3511573Srgrimes if (mii == NULL || ifp == NULL || 35254770Sgreen (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 353241010Sjilles goto done; 354241010Sjilles 3551573Srgrimes sc->sc_flags &= ~AXE_FLAG_LINK; 3561573Srgrimes if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 3571573Srgrimes (IFM_ACTIVE | IFM_AVALID)) { 3581573Srgrimes switch (IFM_SUBTYPE(mii->mii_media_active)) { 35954770Sgreen case IFM_10_T: 3601573Srgrimes case IFM_100_TX: 3611573Srgrimes sc->sc_flags |= AXE_FLAG_LINK; 3621573Srgrimes break; 3631573Srgrimes case IFM_1000_T: 3641573Srgrimes if ((sc->sc_flags & AXE_FLAG_178) == 0) 3651573Srgrimes break; 3661573Srgrimes sc->sc_flags |= AXE_FLAG_LINK; 36728913Simp break; 3681573Srgrimes default: 36956698Sjasone break; 3701573Srgrimes } 3711573Srgrimes } 3721573Srgrimes 3731573Srgrimes /* Lost link, do nothing. */ 3741573Srgrimes if ((sc->sc_flags & AXE_FLAG_LINK) == 0) 3751573Srgrimes goto done; 3768870Srgrimes 3771573Srgrimes val = 0; 3781573Srgrimes if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) 37964740Sgreen val |= AXE_MEDIA_FULL_DUPLEX; 38028913Simp if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772)) { 3811573Srgrimes val |= AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC; 3821573Srgrimes if ((sc->sc_flags & AXE_FLAG_178) != 0) 3831573Srgrimes val |= AXE_178_MEDIA_ENCK; 3841573Srgrimes switch (IFM_SUBTYPE(mii->mii_media_active)) { 3851573Srgrimes case IFM_1000_T: 3861573Srgrimes val |= AXE_178_MEDIA_GMII | AXE_178_MEDIA_ENCK; 3871573Srgrimes break; 3881573Srgrimes case IFM_100_TX: 3891573Srgrimes val |= AXE_178_MEDIA_100TX; 3901573Srgrimes break; 3911573Srgrimes case IFM_10_T: 3921573Srgrimes /* doesn't need to be handled */ 3931573Srgrimes break; 3941573Srgrimes } 3951573Srgrimes } 3961573Srgrimes err = axe_cmd(sc, AXE_CMD_WRITE_MEDIA, 0, val, NULL); 39764740Sgreen if (err) 39877599Skris device_printf(dev, "media change failed, error %d\n", err); 3991573Srgrimesdone: 4001573Srgrimes if (!locked) 401129184Sbde AXE_UNLOCK(sc); 40264740Sgreen} 4031573Srgrimes 4041573Srgrimes/* 4051573Srgrimes * Set media options. 4061573Srgrimes */ 4071573Srgrimesstatic int 4081573Srgrimesaxe_ifmedia_upd(struct ifnet *ifp) 4091573Srgrimes{ 4101573Srgrimes struct axe_softc *sc = ifp->if_softc; 4111573Srgrimes struct mii_data *mii = GET_MII(sc); 4121573Srgrimes int error; 4131573Srgrimes 4141573Srgrimes AXE_LOCK_ASSERT(sc, MA_OWNED); 4151573Srgrimes 4161573Srgrimes if (mii->mii_instance) { 4171573Srgrimes struct mii_softc *miisc; 41864740Sgreen 4191573Srgrimes LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 4201573Srgrimes mii_phy_reset(miisc); 4211573Srgrimes } 42254770Sgreen error = mii_mediachg(mii); 42354770Sgreen return (error); 4241573Srgrimes} 4251573Srgrimes 42628913Simp/* 4271573Srgrimes * Report current media status. 4281573Srgrimes */ 4291573Srgrimesstatic void 4301573Srgrimesaxe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 4311573Srgrimes{ 4321573Srgrimes struct axe_softc *sc = ifp->if_softc; 4331573Srgrimes struct mii_data *mii = GET_MII(sc); 4341573Srgrimes 4351573Srgrimes AXE_LOCK(sc); 4361573Srgrimes mii_pollstat(mii); 4371573Srgrimes AXE_UNLOCK(sc); 4381573Srgrimes ifmr->ifm_active = mii->mii_media_active; 4391573Srgrimes ifmr->ifm_status = mii->mii_media_status; 4401573Srgrimes} 4411573Srgrimes 4421573Srgrimesstatic void 44354770Sgreenaxe_setmulti(struct usb2_ether *ue) 4441573Srgrimes{ 445241010Sjilles struct axe_softc *sc = usb2_ether_getsc(ue); 4461573Srgrimes struct ifnet *ifp = usb2_ether_getifp(ue); 4471573Srgrimes struct ifmultiaddr *ifma; 4481573Srgrimes uint32_t h = 0; 4491573Srgrimes uint16_t rxmode; 45054770Sgreen uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 4511573Srgrimes 4521573Srgrimes AXE_LOCK_ASSERT(sc, MA_OWNED); 4531573Srgrimes 4541573Srgrimes axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, &rxmode); 4551573Srgrimes rxmode = le16toh(rxmode); 4561573Srgrimes 4571573Srgrimes if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) { 4581573Srgrimes rxmode |= AXE_RXCMD_ALLMULTI; 4591573Srgrimes axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); 4601573Srgrimes return; 4611573Srgrimes } 4621573Srgrimes rxmode &= ~AXE_RXCMD_ALLMULTI; 4631573Srgrimes 4641573Srgrimes IF_ADDR_LOCK(ifp); 4651573Srgrimes TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) 4661573Srgrimes { 4671573Srgrimes if (ifma->ifma_addr->sa_family != AF_LINK) 4681573Srgrimes continue; 4691573Srgrimes h = ether_crc32_be(LLADDR((struct sockaddr_dl *) 4701573Srgrimes ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; 4711573Srgrimes hashtbl[h / 8] |= 1 << (h % 8); 4721573Srgrimes } 4731573Srgrimes IF_ADDR_UNLOCK(ifp); 47454770Sgreen 4751573Srgrimes axe_cmd(sc, AXE_CMD_WRITE_MCAST, 0, 0, (void *)&hashtbl); 4761573Srgrimes axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); 4771573Srgrimes} 4781573Srgrimes 4791573Srgrimesstatic int 4801573Srgrimesaxe_get_phyno(struct axe_softc *sc, int sel) 4811573Srgrimes{ 4821573Srgrimes int phyno; 48328913Simp 4841573Srgrimes switch (AXE_PHY_TYPE(sc->sc_phyaddrs[sel])) { 4851573Srgrimes case PHY_TYPE_100_HOME: 4861573Srgrimes case PHY_TYPE_GIG: 4871573Srgrimes phyno = AXE_PHY_NO(sc->sc_phyaddrs[sel]); 4881573Srgrimes break; 4891573Srgrimes case PHY_TYPE_SPECIAL: 49056698Sjasone /* FALLTHROUGH */ 4911573Srgrimes case PHY_TYPE_RSVD: 4921573Srgrimes /* FALLTHROUGH */ 4931573Srgrimes case PHY_TYPE_NON_SUP: 4941573Srgrimes /* FALLTHROUGH */ 49556698Sjasone default: 49677497Skris phyno = -1; 497129184Sbde break; 49877599Skris } 49977599Skris 5001573Srgrimes return (phyno); 5011573Srgrimes} 5021573Srgrimes 5031573Srgrimesstatic void 5041573Srgrimesaxe_ax88178_init(struct axe_softc *sc) 5051573Srgrimes{ 5061573Srgrimes int gpio0 = 0, phymode = 0; 5071573Srgrimes uint16_t eeprom; 5081573Srgrimes 5091573Srgrimes axe_cmd(sc, AXE_CMD_SROM_WR_ENABLE, 0, 0, NULL); 5101573Srgrimes /* XXX magic */ 5111573Srgrimes axe_cmd(sc, AXE_CMD_SROM_READ, 0, 0x0017, &eeprom); 5121573Srgrimes eeprom = le16toh(eeprom); 513175688Syar axe_cmd(sc, AXE_CMD_SROM_WR_DISABLE, 0, 0, NULL); 5141573Srgrimes 5151573Srgrimes /* if EEPROM is invalid we have to use to GPIO0 */ 5161573Srgrimes if (eeprom == 0xffff) { 5171573Srgrimes phymode = 0; 51864740Sgreen gpio0 = 1; 5191573Srgrimes } else { 5201573Srgrimes phymode = eeprom & 7; 5211573Srgrimes gpio0 = (eeprom & 0x80) ? 0 : 1; 5221573Srgrimes } 5231573Srgrimes 5241573Srgrimes axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x008c, NULL); 5251573Srgrimes usb2_ether_pause(&sc->sc_ue, hz / 16); 5261573Srgrimes 5271573Srgrimes if ((eeprom >> 8) != 0x01) { 528175688Syar axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL); 52990045Sobrien usb2_ether_pause(&sc->sc_ue, hz / 32); 5301573Srgrimes 5311573Srgrimes axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x001c, NULL); 53290045Sobrien usb2_ether_pause(&sc->sc_ue, hz / 3); 5331573Srgrimes 5341573Srgrimes axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x003c, NULL); 53564740Sgreen usb2_ether_pause(&sc->sc_ue, hz / 32); 5361573Srgrimes } else { 5371573Srgrimes axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x0004, NULL); 5381573Srgrimes usb2_ether_pause(&sc->sc_ue, hz / 32); 5391573Srgrimes 5401573Srgrimes axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x000c, NULL); 5411573Srgrimes usb2_ether_pause(&sc->sc_ue, hz / 32); 5421573Srgrimes } 5431573Srgrimes 5441573Srgrimes /* soft reset */ 5451573Srgrimes axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL); 5461573Srgrimes usb2_ether_pause(&sc->sc_ue, hz / 4); 5471573Srgrimes 5481573Srgrimes axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 5491573Srgrimes AXE_SW_RESET_PRL | AXE_178_RESET_MAGIC, NULL); 5501573Srgrimes usb2_ether_pause(&sc->sc_ue, hz / 4); 5511573Srgrimes /* Enable MII/GMII/RGMII interface to work with external PHY. */ 5521573Srgrimes axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0, NULL); 5531573Srgrimes usb2_ether_pause(&sc->sc_ue, hz / 4); 5541573Srgrimes 5551573Srgrimes axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); 5561573Srgrimes} 5571573Srgrimes 5581573Srgrimesstatic void 5591573Srgrimesaxe_ax88772_init(struct axe_softc *sc) 5601573Srgrimes{ 5611573Srgrimes axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, 0x00b0, NULL); 5621573Srgrimes usb2_ether_pause(&sc->sc_ue, hz / 16); 5631573Srgrimes 5641573Srgrimes if (sc->sc_phyno == AXE_772_PHY_NO_EPHY) { 5651573Srgrimes /* ask for the embedded PHY */ 56664740Sgreen axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x01, NULL); 5671573Srgrimes usb2_ether_pause(&sc->sc_ue, hz / 64); 5681573Srgrimes 5691573Srgrimes /* power down and reset state, pin reset state */ 57028913Simp axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 5711573Srgrimes AXE_SW_RESET_CLEAR, NULL); 5728870Srgrimes usb2_ether_pause(&sc->sc_ue, hz / 16); 5731573Srgrimes 5741573Srgrimes /* power down/reset state, pin operating state */ 5751573Srgrimes axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 5761573Srgrimes AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL); 5771573Srgrimes usb2_ether_pause(&sc->sc_ue, hz / 4); 5781573Srgrimes 5791573Srgrimes /* power up, reset */ 5801573Srgrimes axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_PRL, NULL); 5811573Srgrimes 5821573Srgrimes /* power up, operating */ 5831573Srgrimes axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 5841573Srgrimes AXE_SW_RESET_IPRL | AXE_SW_RESET_PRL, NULL); 5851573Srgrimes } else { 586241010Sjilles /* ask for external PHY */ 5871573Srgrimes axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, 0x00, NULL); 5881573Srgrimes usb2_ether_pause(&sc->sc_ue, hz / 64); 5891573Srgrimes 5901573Srgrimes /* power down internal PHY */ 59156698Sjasone axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, 5921573Srgrimes AXE_SW_RESET_IPPD | AXE_SW_RESET_PRL, NULL); 5931573Srgrimes } 5941573Srgrimes 595103726Swollman usb2_ether_pause(&sc->sc_ue, hz / 4); 596103726Swollman axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); 597103726Swollman} 598103726Swollman 599103726Swollmanstatic void 600175688Syaraxe_reset(struct axe_softc *sc) 601103726Swollman{ 602103726Swollman struct usb2_config_descriptor *cd; 603103726Swollman usb2_error_t err; 604103726Swollman 605103726Swollman cd = usb2_get_config_descriptor(sc->sc_ue.ue_udev); 606103726Swollman 607103726Swollman err = usb2_req_set_config(sc->sc_ue.ue_udev, &sc->sc_mtx, 608103726Swollman cd->bConfigurationValue); 609103726Swollman if (err) 610103726Swollman DPRINTF("reset failed (ignored)\n"); 611175688Syar 612103726Swollman /* Wait a little while for the chip to get its brains in order. */ 613103726Swollman usb2_ether_pause(&sc->sc_ue, hz / 100); 614103726Swollman} 615103726Swollman 616103726Swollmanstatic void 617175688Syaraxe_attach_post(struct usb2_ether *ue) 618103726Swollman{ 619103726Swollman struct axe_softc *sc = usb2_ether_getsc(ue); 620103726Swollman 621103726Swollman /* 622103726Swollman * Load PHY indexes first. Needed by axe_xxx_init(). 6231573Srgrimes */ 6241573Srgrimes axe_cmd(sc, AXE_CMD_READ_PHYID, 0, 0, sc->sc_phyaddrs); 6251573Srgrimes#if 1 6261573Srgrimes device_printf(sc->sc_ue.ue_dev, "PHYADDR 0x%02x:0x%02x\n", 6271573Srgrimes sc->sc_phyaddrs[0], sc->sc_phyaddrs[1]); 6281573Srgrimes#endif 6291573Srgrimes sc->sc_phyno = axe_get_phyno(sc, AXE_PHY_SEL_PRI); 6301573Srgrimes if (sc->sc_phyno == -1) 6311573Srgrimes sc->sc_phyno = axe_get_phyno(sc, AXE_PHY_SEL_SEC); 6321573Srgrimes if (sc->sc_phyno == -1) { 6331573Srgrimes device_printf(sc->sc_ue.ue_dev, 6341573Srgrimes "no valid PHY address found, assuming PHY address 0\n"); 6351573Srgrimes sc->sc_phyno = 0; 6361573Srgrimes } 6371573Srgrimes 6381573Srgrimes if (sc->sc_flags & AXE_FLAG_178) 63990045Sobrien axe_ax88178_init(sc); 6401573Srgrimes else if (sc->sc_flags & AXE_FLAG_772) 6411573Srgrimes axe_ax88772_init(sc); 64290045Sobrien 64390045Sobrien /* 64490045Sobrien * Get station address. 6451573Srgrimes */ 6461573Srgrimes if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772)) 64754770Sgreen axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, ue->ue_eaddr); 648128946Skientzle else 64954770Sgreen axe_cmd(sc, AXE_172_CMD_READ_NODEID, 0, 0, ue->ue_eaddr); 65054770Sgreen 6511573Srgrimes /* 6521573Srgrimes * Fetch IPG values. 6531573Srgrimes */ 6541573Srgrimes axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->sc_ipgs); 6551573Srgrimes} 6561573Srgrimes 6571573Srgrimes/* 6581573Srgrimes * Probe for a AX88172 chip. 6591573Srgrimes */ 66023668Speterstatic int 66123668Speteraxe_probe(device_t dev) 662129184Sbde{ 66323668Speter struct usb2_attach_arg *uaa = device_get_ivars(dev); 664129184Sbde 66523668Speter if (uaa->usb_mode != USB_MODE_HOST) 66623668Speter return (ENXIO); 66723668Speter if (uaa->info.bConfigIndex != AXE_CONFIG_IDX) 66823668Speter return (ENXIO); 6691573Srgrimes if (uaa->info.bIfaceIndex != AXE_IFACE_IDX) 6701573Srgrimes return (ENXIO); 6711573Srgrimes 6721573Srgrimes return (usb2_lookup_id_by_uaa(axe_devs, sizeof(axe_devs), uaa)); 6731573Srgrimes} 6741573Srgrimes 6751573Srgrimes/* 6761573Srgrimes * Attach the interface. Allocate softc structures, do ifmedia 6771573Srgrimes * setup and ethernet/BPF attach. 6781573Srgrimes */ 6791573Srgrimesstatic int 6801573Srgrimesaxe_attach(device_t dev) 68154770Sgreen{ 6821573Srgrimes struct usb2_attach_arg *uaa = device_get_ivars(dev); 68354770Sgreen struct axe_softc *sc = device_get_softc(dev); 68454770Sgreen struct usb2_ether *ue = &sc->sc_ue; 68554770Sgreen uint8_t iface_index; 686129052Speadar int error; 687129052Speadar 688129052Speadar sc->sc_flags = USB_GET_DRIVER_INFO(uaa); 689129052Speadar 69054770Sgreen device_set_usb2_desc(dev); 69154770Sgreen 6921573Srgrimes mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 69354770Sgreen 69454770Sgreen iface_index = AXE_IFACE_IDX; 6951573Srgrimes error = usb2_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, 6961573Srgrimes axe_config, AXE_N_TRANSFER, sc, &sc->sc_mtx); 6971573Srgrimes if (error) { 6981573Srgrimes device_printf(dev, "allocating USB transfers failed!\n"); 6991573Srgrimes goto detach; 7001573Srgrimes } 7011573Srgrimes 7021573Srgrimes ue->ue_sc = sc; 7031573Srgrimes ue->ue_dev = dev; 7041573Srgrimes ue->ue_udev = uaa->device; 7051573Srgrimes ue->ue_mtx = &sc->sc_mtx; 7061573Srgrimes ue->ue_methods = &axe_ue_methods; 7071573Srgrimes 7081573Srgrimes error = usb2_ether_ifattach(ue); 7091573Srgrimes if (error) { 7101573Srgrimes device_printf(dev, "could not attach interface\n"); 7111573Srgrimes goto detach; 7121573Srgrimes } 7131573Srgrimes return (0); /* success */ 7141573Srgrimes 7151573Srgrimesdetach: 7161573Srgrimes axe_detach(dev); 71754770Sgreen return (ENXIO); /* failure */ 718235647Sgleb} 7191573Srgrimes 7201573Srgrimesstatic int 7211573Srgrimesaxe_detach(device_t dev) 7221573Srgrimes{ 7231573Srgrimes struct axe_softc *sc = device_get_softc(dev); 7241573Srgrimes struct usb2_ether *ue = &sc->sc_ue; 7251573Srgrimes 72654770Sgreen usb2_transfer_unsetup(sc->sc_xfer, AXE_N_TRANSFER); 7271573Srgrimes usb2_ether_ifdetach(ue); 7281573Srgrimes mtx_destroy(&sc->sc_mtx); 7291573Srgrimes 7301573Srgrimes return (0); 7311573Srgrimes} 7321573Srgrimes 7331573Srgrimesstatic void 7341573Srgrimesaxe_intr_callback(struct usb2_xfer *xfer) 7351573Srgrimes{ 7361573Srgrimes switch (USB_GET_STATE(xfer)) { 7371573Srgrimes case USB_ST_TRANSFERRED: 7381573Srgrimes case USB_ST_SETUP: 7391573Srgrimestr_setup: 7401573Srgrimes xfer->frlengths[0] = xfer->max_data_length; 7411573Srgrimes usb2_start_hardware(xfer); 7421573Srgrimes return; 74354770Sgreen 74454770Sgreen default: /* Error */ 74554770Sgreen if (xfer->error != USB_ERR_CANCELLED) { 7461573Srgrimes /* try to clear stall first */ 74754770Sgreen xfer->flags.stall_pipe = 1; 74854770Sgreen goto tr_setup; 7491573Srgrimes } 7501573Srgrimes return; 7511573Srgrimes } 7521573Srgrimes} 75354770Sgreen 75428913Simp#if (AXE_BULK_BUF_SIZE >= 0x10000) 755128946Skientzle#error "Please update axe_bulk_read_callback()!" 7561573Srgrimes#endif 7571573Srgrimes 7581573Srgrimesstatic void 759128946Skientzleaxe_bulk_read_callback(struct usb2_xfer *xfer) 7601573Srgrimes{ 761128946Skientzle struct axe_softc *sc = xfer->priv_sc; 76254770Sgreen struct usb2_ether *ue = &sc->sc_ue; 763128946Skientzle struct ifnet *ifp = usb2_ether_getifp(ue); 7641573Srgrimes struct axe_sframe_hdr hdr; 7651573Srgrimes int error, pos, len, adjust; 7661573Srgrimes 7671573Srgrimes switch (USB_GET_STATE(xfer)) { 7681573Srgrimes case USB_ST_TRANSFERRED: 7691573Srgrimes pos = 0; 7701573Srgrimes while (1) { 7711573Srgrimes if (sc->sc_flags & (AXE_FLAG_772 | AXE_FLAG_178)) { 7721573Srgrimes if (xfer->actlen < sizeof(hdr)) { 7731573Srgrimes /* too little data */ 7741573Srgrimes break; 7751573Srgrimes } 77654770Sgreen usb2_copy_out(xfer->frbuffers, pos, &hdr, sizeof(hdr)); 7771573Srgrimes 7781573Srgrimes if ((hdr.len ^ hdr.ilen) != 0xFFFF) { 77954770Sgreen /* we lost sync */ 78054770Sgreen break; 78154770Sgreen } 78254770Sgreen xfer->actlen -= sizeof(hdr); 78354770Sgreen pos += sizeof(hdr); 78454770Sgreen 78554770Sgreen len = le16toh(hdr.len); 7861573Srgrimes if (len > xfer->actlen) { 7871573Srgrimes /* invalid length */ 788128946Skientzle break; 78954770Sgreen } 79054770Sgreen adjust = (len & 1); 79154770Sgreen 79254770Sgreen } else { 79354770Sgreen len = xfer->actlen; 79454770Sgreen adjust = 0; 79554770Sgreen } 79654770Sgreen error = usb2_ether_rxbuf(ue, xfer->frbuffers, pos, len); 79754770Sgreen if (error) 79854770Sgreen break; 79954770Sgreen 80054770Sgreen pos += len; 80154770Sgreen xfer->actlen -= len; 80254770Sgreen 80354770Sgreen if (xfer->actlen <= adjust) { 8041573Srgrimes /* we are finished */ 805128946Skientzle goto tr_setup; 8061573Srgrimes } 80723668Speter pos += adjust; 80823668Speter xfer->actlen -= adjust; 80923668Speter } 81023668Speter 81123668Speter /* count an error */ 8121573Srgrimes ifp->if_ierrors++; 8131573Srgrimes 8141573Srgrimes /* FALLTHROUGH */ 8151573Srgrimes case USB_ST_SETUP: 8161573Srgrimestr_setup: 8171573Srgrimes xfer->frlengths[0] = xfer->max_data_length; 8181573Srgrimes usb2_start_hardware(xfer); 8191573Srgrimes usb2_ether_rxflush(ue); 8201573Srgrimes return; 82154770Sgreen 82217141Sjkh default: /* Error */ 8231573Srgrimes DPRINTF("bulk read error, %s\n", 8241573Srgrimes usb2_errstr(xfer->error)); 8251573Srgrimes 8261573Srgrimes if (xfer->error != USB_ERR_CANCELLED) { 8271573Srgrimes /* try to clear stall first */ 8281573Srgrimes xfer->flags.stall_pipe = 1; 8291573Srgrimes goto tr_setup; 8301573Srgrimes } 8311573Srgrimes return; 8321573Srgrimes 8331573Srgrimes } 8341573Srgrimes} 8351573Srgrimes 8361573Srgrimes#if ((AXE_BULK_BUF_SIZE >= 0x10000) || (AXE_BULK_BUF_SIZE < (MCLBYTES+4))) 8371573Srgrimes#error "Please update axe_bulk_write_callback()!" 8381573Srgrimes#endif 8391573Srgrimes 8401573Srgrimesstatic void 8411573Srgrimesaxe_bulk_write_callback(struct usb2_xfer *xfer) 8421573Srgrimes{ 8431573Srgrimes struct axe_softc *sc = xfer->priv_sc; 8441573Srgrimes struct axe_sframe_hdr hdr; 8451573Srgrimes struct ifnet *ifp = usb2_ether_getifp(&sc->sc_ue); 8461573Srgrimes struct mbuf *m; 8471573Srgrimes int pos; 8481573Srgrimes 8491573Srgrimes switch (USB_GET_STATE(xfer)) { 8501573Srgrimes case USB_ST_TRANSFERRED: 8511573Srgrimes DPRINTFN(11, "transfer complete\n"); 8521573Srgrimes ifp->if_opackets++; 8531573Srgrimes /* FALLTHROUGH */ 85428913Simp case USB_ST_SETUP: 85528913Simptr_setup: 8561573Srgrimes if ((sc->sc_flags & AXE_FLAG_LINK) == 0) { 8571573Srgrimes /* 85854770Sgreen * don't send anything if there is no link ! 85954770Sgreen */ 8601573Srgrimes return; 86154770Sgreen } 86254770Sgreen pos = 0; 8631573Srgrimes 8641573Srgrimes while (1) { 8651573Srgrimes 8661573Srgrimes IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 8671573Srgrimes 8681573Srgrimes if (m == NULL) { 86954770Sgreen if (pos > 0) 8701573Srgrimes break; /* send out data */ 8711573Srgrimes return; 8721573Srgrimes } 8731573Srgrimes if (m->m_pkthdr.len > MCLBYTES) { 8741573Srgrimes m->m_pkthdr.len = MCLBYTES; 8751573Srgrimes } 8761573Srgrimes if (sc->sc_flags & (AXE_FLAG_772 | AXE_FLAG_178)) { 8771573Srgrimes 8781573Srgrimes hdr.len = htole16(m->m_pkthdr.len); 8791573Srgrimes hdr.ilen = ~hdr.len; 8801573Srgrimes 8811573Srgrimes usb2_copy_in(xfer->frbuffers, pos, &hdr, sizeof(hdr)); 8821573Srgrimes 88377599Skris pos += sizeof(hdr); 88477599Skris 8851573Srgrimes /* 8861573Srgrimes * NOTE: Some drivers force a short packet 8871573Srgrimes * by appending a dummy header with zero 8881573Srgrimes * length at then end of the USB transfer. 8891573Srgrimes * This driver uses the 8901573Srgrimes * USB_FORCE_SHORT_XFER flag instead. 8911573Srgrimes */ 8921573Srgrimes } 8931573Srgrimes usb2_m_copy_in(xfer->frbuffers, pos, 8941573Srgrimes m, 0, m->m_pkthdr.len); 8951573Srgrimes 8961573Srgrimes pos += m->m_pkthdr.len; 8971573Srgrimes 8981573Srgrimes /* 8991573Srgrimes * if there's a BPF listener, bounce a copy 9001573Srgrimes * of this frame to him: 9011573Srgrimes */ 9021573Srgrimes BPF_MTAP(ifp, m); 9031573Srgrimes 9041573Srgrimes m_freem(m); 9051573Srgrimes 90690045Sobrien if (sc->sc_flags & (AXE_FLAG_772 | AXE_FLAG_178)) { 9071573Srgrimes if (pos > (AXE_BULK_BUF_SIZE - MCLBYTES - sizeof(hdr))) { 9081573Srgrimes /* send out frame(s) */ 90990045Sobrien break; 91090045Sobrien } 91190045Sobrien } else { 9121573Srgrimes /* send out frame */ 9131573Srgrimes break; 9141573Srgrimes } 9151573Srgrimes } 9161573Srgrimes 9178870Srgrimes xfer->frlengths[0] = pos; 91823668Speter usb2_start_hardware(xfer); 919129184Sbde return; 92023668Speter 92123668Speter default: /* Error */ 922129184Sbde DPRINTFN(11, "transfer error, %s\n", 92323668Speter usb2_errstr(xfer->error)); 92423668Speter 92523668Speter ifp->if_oerrors++; 92623668Speter 92723668Speter if (xfer->error != USB_ERR_CANCELLED) { 92823668Speter /* try to clear stall first */ 9291573Srgrimes xfer->flags.stall_pipe = 1; 9301573Srgrimes goto tr_setup; 9311573Srgrimes } 9321573Srgrimes return; 9331573Srgrimes 9341573Srgrimes } 9351573Srgrimes} 9361573Srgrimes 9371573Srgrimesstatic void 9381573Srgrimesaxe_tick(struct usb2_ether *ue) 9391573Srgrimes{ 9408870Srgrimes struct axe_softc *sc = usb2_ether_getsc(ue); 9411573Srgrimes struct mii_data *mii = GET_MII(sc); 9421573Srgrimes 9431573Srgrimes AXE_LOCK_ASSERT(sc, MA_OWNED); 9441573Srgrimes 9451573Srgrimes mii_tick(mii); 9461573Srgrimes if ((sc->sc_flags & AXE_FLAG_LINK) == 0) { 9471573Srgrimes axe_miibus_statchg(ue->ue_dev); 9481573Srgrimes if ((sc->sc_flags & AXE_FLAG_LINK) != 0) 9491573Srgrimes axe_start(ue); 9501573Srgrimes } 9511573Srgrimes} 9521573Srgrimes 9531573Srgrimesstatic void 9541573Srgrimesaxe_start(struct usb2_ether *ue) 9551573Srgrimes{ 9561573Srgrimes struct axe_softc *sc = usb2_ether_getsc(ue); 9571573Srgrimes 9581573Srgrimes /* 9591573Srgrimes * start the USB transfers, if not already started: 9601573Srgrimes */ 9611573Srgrimes usb2_transfer_start(sc->sc_xfer[AXE_INTR_DT_RD]); 9621573Srgrimes usb2_transfer_start(sc->sc_xfer[AXE_BULK_DT_RD]); 9631573Srgrimes usb2_transfer_start(sc->sc_xfer[AXE_BULK_DT_WR]); 9641573Srgrimes} 9651573Srgrimes 9661573Srgrimesstatic void 9671573Srgrimesaxe_init(struct usb2_ether *ue) 9681573Srgrimes{ 9691573Srgrimes struct axe_softc *sc = usb2_ether_getsc(ue); 9701573Srgrimes struct ifnet *ifp = usb2_ether_getifp(ue); 9711573Srgrimes uint16_t rxmode; 9721573Srgrimes 9731573Srgrimes AXE_LOCK_ASSERT(sc, MA_OWNED); 9741573Srgrimes 9751573Srgrimes /* Cancel pending I/O */ 9761573Srgrimes axe_stop(ue); 9771573Srgrimes 9781573Srgrimes#ifdef notdef 9791573Srgrimes /* Set MAC address */ 9801573Srgrimes axe_mac(sc, IF_LLADDR(ifp), 1); 9811573Srgrimes#endif 9821573Srgrimes 9831573Srgrimes /* Set transmitter IPG values */ 9841573Srgrimes if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772)) { 9851573Srgrimes axe_cmd(sc, AXE_178_CMD_WRITE_IPG012, sc->sc_ipgs[2], 986103726Swollman (sc->sc_ipgs[1] << 8) | (sc->sc_ipgs[0]), NULL); 987103726Swollman } else { 988103726Swollman axe_cmd(sc, AXE_172_CMD_WRITE_IPG0, 0, sc->sc_ipgs[0], NULL); 989103726Swollman axe_cmd(sc, AXE_172_CMD_WRITE_IPG1, 0, sc->sc_ipgs[1], NULL); 990103726Swollman axe_cmd(sc, AXE_172_CMD_WRITE_IPG2, 0, sc->sc_ipgs[2], NULL); 991103726Swollman } 992103726Swollman 993103726Swollman /* Enable receiver, set RX mode */ 994103726Swollman rxmode = (AXE_RXCMD_MULTICAST | AXE_RXCMD_ENABLE); 995103726Swollman if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772)) { 996103726Swollman rxmode |= AXE_178_RXCMD_MFB_2048; /* chip default */ 997103726Swollman } else { 998103726Swollman rxmode |= AXE_172_RXCMD_UNICAST; 999103726Swollman } 1000103726Swollman 10011573Srgrimes /* If we want promiscuous mode, set the allframes bit. */ 10021573Srgrimes if (ifp->if_flags & IFF_PROMISC) 10031573Srgrimes rxmode |= AXE_RXCMD_PROMISC; 10041573Srgrimes 100590045Sobrien if (ifp->if_flags & IFF_BROADCAST) 10061573Srgrimes rxmode |= AXE_RXCMD_BROADCAST; 100790045Sobrien 10081573Srgrimes axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); 10091573Srgrimes 10101573Srgrimes /* Load the multicast filter. */ 10111573Srgrimes axe_setmulti(ue); 10121573Srgrimes 10131573Srgrimes usb2_transfer_set_stall(sc->sc_xfer[AXE_BULK_DT_WR]); 10141573Srgrimes 10151573Srgrimes ifp->if_drv_flags |= IFF_DRV_RUNNING; 10161573Srgrimes axe_start(ue); 10171573Srgrimes} 101864740Sgreen 101954770Sgreenstatic void 10201573Srgrimesaxe_setpromisc(struct usb2_ether *ue) 10211573Srgrimes{ 10221573Srgrimes struct axe_softc *sc = usb2_ether_getsc(ue); 10231573Srgrimes struct ifnet *ifp = usb2_ether_getifp(ue); 10241573Srgrimes uint16_t rxmode; 10251573Srgrimes 1026103726Swollman axe_cmd(sc, AXE_CMD_RXCTL_READ, 0, 0, &rxmode); 10271573Srgrimes 10281573Srgrimes rxmode = le16toh(rxmode); 10291573Srgrimes 10301573Srgrimes if (ifp->if_flags & IFF_PROMISC) { 10311573Srgrimes rxmode |= AXE_RXCMD_PROMISC; 10321573Srgrimes } else { 10331573Srgrimes rxmode &= ~AXE_RXCMD_PROMISC; 10341573Srgrimes } 10351573Srgrimes 10361573Srgrimes axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL); 103790045Sobrien 10381573Srgrimes axe_setmulti(ue); 103990045Sobrien} 10401573Srgrimes 10411573Srgrimesstatic void 1042103726Swollmanaxe_stop(struct usb2_ether *ue) 1043103726Swollman{ 1044103726Swollman struct axe_softc *sc = usb2_ether_getsc(ue); 1045103726Swollman struct ifnet *ifp = usb2_ether_getifp(ue); 1046103726Swollman 10471573Srgrimes AXE_LOCK_ASSERT(sc, MA_OWNED); 10481573Srgrimes 10491573Srgrimes ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 10501573Srgrimes sc->sc_flags &= ~AXE_FLAG_LINK; 1051103726Swollman 10521573Srgrimes /* 1053103726Swollman * stop all the transfers, if not already stopped: 1054103726Swollman */ 1055103726Swollman usb2_transfer_stop(sc->sc_xfer[AXE_BULK_DT_WR]); 1056103726Swollman usb2_transfer_stop(sc->sc_xfer[AXE_BULK_DT_RD]); 1057103726Swollman usb2_transfer_stop(sc->sc_xfer[AXE_INTR_DT_RD]); 10581573Srgrimes 10591573Srgrimes axe_reset(sc); 10601573Srgrimes} 1061103726Swollman