1139825Simp/*- 21541Srgrimes * Copyright (c) 2001-2003, Shunsuke Akiyama <akiyama@FreeBSD.org>. 31541Srgrimes * Copyright (c) 1997, 1998, 1999, 2000 Bill Paul <wpaul@ee.columbia.edu>. 41541Srgrimes * All rights reserved. 51541Srgrimes * 61541Srgrimes * Redistribution and use in source and binary forms, with or without 71541Srgrimes * modification, are permitted provided that the following conditions 81541Srgrimes * are met: 91541Srgrimes * 1. Redistributions of source code must retain the above copyright 101541Srgrimes * notice, this list of conditions and the following disclaimer. 111541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121541Srgrimes * notice, this list of conditions and the following disclaimer in the 131541Srgrimes * documentation and/or other materials provided with the distribution. 141541Srgrimes * 151541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 161541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 171541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 181541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 191541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 201541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 211541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 221541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 231541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 241541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 251541Srgrimes * SUCH DAMAGE. 261541Srgrimes */ 271541Srgrimes/*- 281541Srgrimes * Copyright (c) 1997, 1998, 1999, 2000 2922521Sdyson * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved. 3050477Speter * 311541Srgrimes * Redistribution and use in source and binary forms, with or without 321541Srgrimes * modification, are permitted provided that the following conditions 332176Spaul * are met: 34262779Spfg * 1. Redistributions of source code must retain the above copyright 352176Spaul * notice, this list of conditions and the following disclaimer. 36243245Strasz * 2. Redistributions in binary form must reproduce the above copyright 37243250Strasz * notice, this list of conditions and the following disclaimer in the 38243245Strasz * documentation and/or other materials provided with the distribution. 391541Srgrimes * 3. All advertising materials mentioning features or use of this software 4096755Strhodes * must display the following acknowledgement: 4196755Strhodes * This product includes software developed by Bill Paul. 421541Srgrimes * 4. Neither the name of the author nor the names of any co-contributors 431541Srgrimes * may be used to endorse or promote products derived from this software 4496755Strhodes * without specific prior written permission. 451541Srgrimes * 461541Srgrimes * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 471541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 481541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 491541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 501541Srgrimes * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 5196755Strhodes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 521541Srgrimes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 531541Srgrimes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 541541Srgrimes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 551541Srgrimes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 561541Srgrimes * THE POSSIBILITY OF SUCH DAMAGE. 571541Srgrimes */ 581541Srgrimes 591541Srgrimes#include <sys/cdefs.h> 6098542Smckusick__FBSDID("$FreeBSD$"); 6198542Smckusick 6298542Smckusick/* 6398542Smckusick * RealTek RTL8150 USB to fast ethernet controller driver. 6498542Smckusick * Datasheet is available from 6598542Smckusick * ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/. 6698542Smckusick */ 6798542Smckusick 6898542Smckusick#include <sys/stdint.h> 6998542Smckusick#include <sys/stddef.h> 701541Srgrimes#include <sys/param.h> 71262779Spfg#include <sys/queue.h> 72262779Spfg#include <sys/types.h> 73262779Spfg#include <sys/systm.h> 74262779Spfg#include <sys/kernel.h> 75262779Spfg#include <sys/bus.h> 76262779Spfg#include <sys/module.h> 7798542Smckusick#include <sys/lock.h> 781541Srgrimes#include <sys/mutex.h> 7998542Smckusick#include <sys/condvar.h> 8098542Smckusick#include <sys/sysctl.h> 8198542Smckusick#include <sys/sx.h> 82262779Spfg#include <sys/unistd.h> 8398542Smckusick#include <sys/callout.h> 841541Srgrimes#include <sys/malloc.h> 851541Srgrimes#include <sys/priv.h> 868876Srgrimes 871541Srgrimes#include <dev/usb/usb.h> 8813765Smpp#include <dev/usb/usbdi.h> 891541Srgrimes#include <dev/usb/usbdi_util.h> 901541Srgrimes#include "usbdevs.h" 911541Srgrimes 921541Srgrimes#define USB_DEBUG_VAR rue_debug 931541Srgrimes#include <dev/usb/usb_debug.h> 9496755Strhodes#include <dev/usb/usb_process.h> 951541Srgrimes 961541Srgrimes#include <dev/usb/net/usb_ethernet.h> 971541Srgrimes#include <dev/usb/net/if_ruereg.h> 981541Srgrimes 9996755Strhodes#ifdef USB_DEBUG 1001541Srgrimesstatic int rue_debug = 0; 1011541Srgrimes 1021541Srgrimesstatic SYSCTL_NODE(_hw_usb, OID_AUTO, rue, CTLFLAG_RW, 0, "USB rue"); 1031541SrgrimesSYSCTL_INT(_hw_usb_rue, OID_AUTO, debug, CTLFLAG_RW, 1041541Srgrimes &rue_debug, 0, "Debug level"); 1051541Srgrimes#endif 1061541Srgrimes 1071541Srgrimes/* 1081541Srgrimes * Various supported device vendors/products. 109179295Srodrigc */ 110179295Srodrigc 1111541Srgrimesstatic const STRUCT_USB_HOST_ID rue_devs[] = { 112262779Spfg {USB_VPI(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX, 0)}, 1131541Srgrimes {USB_VPI(USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_USBKR100, 0)}, 1141541Srgrimes {USB_VPI(USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01, 0)}, 11596755Strhodes}; 1168876Srgrimes 1171541Srgrimes/* prototypes */ 11822521Sdyson 119262779Spfgstatic device_probe_t rue_probe; 12022521Sdysonstatic device_attach_t rue_attach; 12122521Sdysonstatic device_detach_t rue_detach; 122108970Sgordon 123108970Sgordonstatic miibus_readreg_t rue_miibus_readreg; 124108970Sgordonstatic miibus_writereg_t rue_miibus_writereg; 125262779Spfgstatic miibus_statchg_t rue_miibus_statchg; 126108970Sgordon 127108970Sgordonstatic usb_callback_t rue_intr_callback; 12871073Siedowsestatic usb_callback_t rue_bulk_read_callback; 12971073Siedowsestatic usb_callback_t rue_bulk_write_callback; 13088025Siedowse 13171073Siedowsestatic uether_fn_t rue_attach_post; 13271073Siedowsestatic uether_fn_t rue_init; 13371073Siedowsestatic uether_fn_t rue_stop; 13471073Siedowsestatic uether_fn_t rue_start; 13571073Siedowsestatic uether_fn_t rue_tick; 13675377Smckusickstatic uether_fn_t rue_setmulti; 13775377Smckusickstatic uether_fn_t rue_setpromisc; 13888025Siedowse 13988025Siedowsestatic int rue_read_mem(struct rue_softc *, uint16_t, void *, int); 14088025Siedowsestatic int rue_write_mem(struct rue_softc *, uint16_t, void *, int); 1411541Srgrimesstatic uint8_t rue_csr_read_1(struct rue_softc *, uint16_t); 14288025Siedowsestatic uint16_t rue_csr_read_2(struct rue_softc *, uint16_t); 1431541Srgrimesstatic int rue_csr_write_1(struct rue_softc *, uint16_t, uint8_t); 1441541Srgrimesstatic int rue_csr_write_2(struct rue_softc *, uint16_t, uint16_t); 1451541Srgrimesstatic int rue_csr_write_4(struct rue_softc *, int, uint32_t); 1461541Srgrimes 1471541Srgrimesstatic void rue_reset(struct rue_softc *); 1481541Srgrimesstatic int rue_ifmedia_upd(struct ifnet *); 1491541Srgrimesstatic void rue_ifmedia_sts(struct ifnet *, struct ifmediareq *); 150262779Spfg 1511541Srgrimesstatic const struct usb_config rue_config[RUE_N_TRANSFER] = { 1521541Srgrimes 15396755Strhodes [RUE_BULK_DT_WR] = { 1541541Srgrimes .type = UE_BULK, 1551541Srgrimes .endpoint = UE_ADDR_ANY, 1561541Srgrimes .direction = UE_DIR_OUT, 15796755Strhodes .bufsize = MCLBYTES, 1581541Srgrimes .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 1591541Srgrimes .callback = rue_bulk_write_callback, 1601541Srgrimes .timeout = 10000, /* 10 seconds */ 1611541Srgrimes }, 1621541Srgrimes 1631541Srgrimes [RUE_BULK_DT_RD] = { 164262779Spfg .type = UE_BULK, 165262779Spfg .endpoint = UE_ADDR_ANY, 1661541Srgrimes .direction = UE_DIR_IN, 1671541Srgrimes .bufsize = (MCLBYTES + 4), 16875377Smckusick .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 16975377Smckusick .callback = rue_bulk_read_callback, 17075377Smckusick .timeout = 0, /* no timeout */ 17175377Smckusick }, 17275377Smckusick 17375377Smckusick [RUE_INTR_DT_RD] = { 174129895Skrion .type = UE_INTERRUPT, 17575377Smckusick .endpoint = UE_ADDR_ANY, 176262779Spfg .direction = UE_DIR_IN, 177262779Spfg .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 17875377Smckusick .bufsize = 0, /* use wMaxPacketSize */ 17975377Smckusick .callback = rue_intr_callback, 18062553Smckusick }, 18162553Smckusick}; 18262553Smckusick 18362553Smckusickstatic device_method_t rue_methods[] = { 18462553Smckusick /* Device interface */ 18562553Smckusick DEVMETHOD(device_probe, rue_probe), 18662553Smckusick DEVMETHOD(device_attach, rue_attach), 187262779Spfg DEVMETHOD(device_detach, rue_detach), 18862553Smckusick 18962553Smckusick /* MII interface */ 19062553Smckusick DEVMETHOD(miibus_readreg, rue_miibus_readreg), 19162553Smckusick DEVMETHOD(miibus_writereg, rue_miibus_writereg), 19262553Smckusick DEVMETHOD(miibus_statchg, rue_miibus_statchg), 19362553Smckusick 19462553Smckusick DEVMETHOD_END 19562553Smckusick}; 19662553Smckusick 19762553Smckusickstatic driver_t rue_driver = { 19862553Smckusick .name = "rue", 19962553Smckusick .methods = rue_methods, 200262779Spfg .size = sizeof(struct rue_softc), 201262779Spfg}; 20262553Smckusick 20362553Smckusickstatic devclass_t rue_devclass; 20474548Smckusick 20574548SmckusickDRIVER_MODULE_ORDERED(rue, uhub, rue_driver, rue_devclass, NULL, NULL, 20674548Smckusick SI_ORDER_ANY); 20774548SmckusickDRIVER_MODULE(miibus, rue, miibus_driver, miibus_devclass, NULL, NULL); 20874548SmckusickMODULE_DEPEND(rue, uether, 1, 1, 1); 20974548SmckusickMODULE_DEPEND(rue, usb, 1, 1, 1); 21074548SmckusickMODULE_DEPEND(rue, ether, 1, 1, 1); 21174548SmckusickMODULE_DEPEND(rue, miibus, 1, 1, 1); 212142123SdelphijMODULE_VERSION(rue, 1); 213142123Sdelphij 214142123Sdelphijstatic const struct usb_ether_methods rue_ue_methods = { 215142123Sdelphij .ue_attach_post = rue_attach_post, 216142123Sdelphij .ue_start = rue_start, 217262779Spfg .ue_init = rue_init, 218202113Smckusick .ue_stop = rue_stop, 219202113Smckusick .ue_tick = rue_tick, 220224061Smckusick .ue_setmulti = rue_setmulti, 221224061Smckusick .ue_setpromisc = rue_setpromisc, 222224061Smckusick .ue_mii_upd = rue_ifmedia_upd, 22374548Smckusick .ue_mii_sts = rue_ifmedia_sts, 22474548Smckusick}; 22574548Smckusick 22674548Smckusick#define RUE_SETBIT(sc, reg, x) \ 22798542Smckusick rue_csr_write_1(sc, reg, rue_csr_read_1(sc, reg) | (x)) 22874548Smckusick 22998542Smckusick#define RUE_CLRBIT(sc, reg, x) \ 23098542Smckusick rue_csr_write_1(sc, reg, rue_csr_read_1(sc, reg) & ~(x)) 23198542Smckusick 23298542Smckusickstatic int 23398542Smckusickrue_read_mem(struct rue_softc *sc, uint16_t addr, void *buf, int len) 23474548Smckusick{ 23574548Smckusick struct usb_device_request req; 23674548Smckusick 237322860Smckusick req.bmRequestType = UT_READ_VENDOR_DEVICE; 238322860Smckusick req.bRequest = UR_SET_ADDRESS; 239322860Smckusick USETW(req.wValue, addr); 240322860Smckusick USETW(req.wIndex, 0); 241322860Smckusick USETW(req.wLength, len); 242322860Smckusick 243322860Smckusick return (uether_do_request(&sc->sc_ue, &req, buf, 1000)); 244322860Smckusick} 245322860Smckusick 246322860Smckusickstatic int 247322860Smckusickrue_write_mem(struct rue_softc *sc, uint16_t addr, void *buf, int len) 248322860Smckusick{ 249322860Smckusick struct usb_device_request req; 250322860Smckusick 2511541Srgrimes req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 2521541Srgrimes req.bRequest = UR_SET_ADDRESS; 2531541Srgrimes USETW(req.wValue, addr); 2541541Srgrimes USETW(req.wIndex, 0); 2551541Srgrimes USETW(req.wLength, len); 2561541Srgrimes 25722521Sdyson return (uether_do_request(&sc->sc_ue, &req, buf, 1000)); 25822521Sdyson} 25922521Sdyson 26022521Sdysonstatic uint8_t 2611541Srgrimesrue_csr_read_1(struct rue_softc *sc, uint16_t reg) 26298542Smckusick{ 26398542Smckusick uint8_t val; 26498542Smckusick 26598542Smckusick rue_read_mem(sc, reg, &val, 1); 26698542Smckusick return (val); 26798542Smckusick} 26898542Smckusick 26998542Smckusickstatic uint16_t 2701541Srgrimesrue_csr_read_2(struct rue_softc *sc, uint16_t reg) 2711541Srgrimes{ 27296755Strhodes uint8_t val[2]; 2731541Srgrimes 2741541Srgrimes rue_read_mem(sc, reg, &val, 2); 27596755Strhodes return (UGETW(val)); 27622521Sdyson} 27798542Smckusick 27898542Smckusickstatic int 27998542Smckusickrue_csr_write_1(struct rue_softc *sc, uint16_t reg, uint8_t val) 28098542Smckusick{ 28198542Smckusick return (rue_write_mem(sc, reg, &val, 1)); 28298542Smckusick} 28398542Smckusick 28498542Smckusickstatic int 28598542Smckusickrue_csr_write_2(struct rue_softc *sc, uint16_t reg, uint16_t val) 286203763Smckusick{ 28722521Sdyson uint8_t temp[2]; 28822521Sdyson 28922521Sdyson USETW(temp, val); 2901541Srgrimes return (rue_write_mem(sc, reg, &temp, 2)); 29122521Sdyson} 29298542Smckusick 29398542Smckusickstatic int 2941541Srgrimesrue_csr_write_4(struct rue_softc *sc, int reg, uint32_t val) 29522521Sdyson{ 29622521Sdyson uint8_t temp[4]; 29722521Sdyson 29822521Sdyson USETDW(temp, val); 2991541Srgrimes return (rue_write_mem(sc, reg, &temp, 4)); 30022521Sdyson} 30122521Sdyson 3021541Srgrimesstatic int 30322521Sdysonrue_miibus_readreg(device_t dev, int phy, int reg) 30422521Sdyson{ 30522521Sdyson struct rue_softc *sc = device_get_softc(dev); 30698542Smckusick uint16_t rval; 30798542Smckusick uint16_t ruereg; 30822521Sdyson int locked; 309203784Smckusick 31098542Smckusick if (phy != 0) /* RTL8150 supports PHY == 0, only */ 3111541Srgrimes return (0); 31222521Sdyson 31398542Smckusick locked = mtx_owned(&sc->sc_mtx); 31498542Smckusick if (!locked) 31598542Smckusick RUE_LOCK(sc); 31624171Sbde 3171541Srgrimes switch (reg) { 31898542Smckusick case MII_BMCR: 31922521Sdyson ruereg = RUE_BMCR; 32022521Sdyson break; 32198542Smckusick case MII_BMSR: 32298542Smckusick ruereg = RUE_BMSR; 32398542Smckusick break; 32498542Smckusick case MII_ANAR: 32598542Smckusick ruereg = RUE_ANAR; 326203763Smckusick break; 32798542Smckusick case MII_ANER: 3281541Srgrimes ruereg = RUE_AER; 32998542Smckusick break; 3301541Srgrimes case MII_ANLPAR: 33122521Sdyson ruereg = RUE_ANLP; 33296755Strhodes break; 33322521Sdyson case MII_PHYIDR1: 334107294Smckusick case MII_PHYIDR2: 33522521Sdyson rval = 0; 336108970Sgordon goto done; 337109034Sgordon default: 338109053Smarcel if (RUE_REG_MIN <= reg && reg <= RUE_REG_MAX) { 3391541Srgrimes rval = rue_csr_read_1(sc, reg); 34022521Sdyson goto done; 34171073Siedowse } 342140702Sjeff device_printf(sc->sc_ue.ue_dev, "bad phy register\n"); 343140702Sjeff rval = 0; 344140702Sjeff goto done; 345140702Sjeff } 34698542Smckusick 34798542Smckusick rval = rue_csr_read_2(sc, ruereg); 348163841Spjddone: 349242379Strasz if (!locked) 350248623Smckusick RUE_UNLOCK(sc); 351248623Smckusick return (rval); 352107294Smckusick} 353140702Sjeff 35498542Smckusickstatic int 35598542Smckusickrue_miibus_writereg(device_t dev, int phy, int reg, int data) 35698542Smckusick{ 35798542Smckusick struct rue_softc *sc = device_get_softc(dev); 358140702Sjeff uint16_t ruereg; 359203763Smckusick int locked; 360227382Sgleb 361203763Smckusick if (phy != 0) /* RTL8150 supports PHY == 0, only */ 362203763Smckusick return (0); 36398542Smckusick 364207141Sjeff locked = mtx_owned(&sc->sc_mtx); 365207141Sjeff if (!locked) 366207141Sjeff RUE_LOCK(sc); 367107294Smckusick 36822521Sdyson switch (reg) { 36922521Sdyson case MII_BMCR: 37098542Smckusick ruereg = RUE_BMCR; 37122521Sdyson break; 37222521Sdyson case MII_BMSR: 37322521Sdyson ruereg = RUE_BMSR; 37422521Sdyson break; 37598542Smckusick case MII_ANAR: 37698542Smckusick ruereg = RUE_ANAR; 37798542Smckusick break; 37898542Smckusick case MII_ANER: 37922521Sdyson ruereg = RUE_AER; 3801541Srgrimes break; 38122521Sdyson case MII_ANLPAR: 382109053Smarcel ruereg = RUE_ANLP; 383109053Smarcel break; 384109053Smarcel case MII_PHYIDR1: 385109053Smarcel case MII_PHYIDR2: 386109053Smarcel goto done; 3871541Srgrimes default: 38813765Smpp if (RUE_REG_MIN <= reg && reg <= RUE_REG_MAX) { 3891541Srgrimes rue_csr_write_1(sc, reg, data); 39098542Smckusick goto done; 39198542Smckusick } 392134011Sjhb device_printf(sc->sc_ue.ue_dev, " bad phy register\n"); 3931541Srgrimes goto done; 394262779Spfg } 395262779Spfg rue_csr_write_2(sc, ruereg, data); 39634266Sjuliandone: 3971541Srgrimes if (!locked) 3981541Srgrimes RUE_UNLOCK(sc); 3991541Srgrimes return (0); 400262779Spfg} 401262779Spfg 4021541Srgrimesstatic void 4031541Srgrimesrue_miibus_statchg(device_t dev) 40434266Sjulian{ 40575503Smckusick /* 40698542Smckusick * When the code below is enabled the card starts doing weird 40798542Smckusick * things after link going from UP to DOWN and back UP. 40898542Smckusick * 40975503Smckusick * Looks like some of register writes below messes up PHY 41075503Smckusick * interface. 41175503Smckusick * 41275503Smckusick * No visible regressions were found after commenting this code 41375503Smckusick * out, so that disable it for good. 41475503Smckusick */ 41575503Smckusick#if 0 41698542Smckusick struct rue_softc *sc = device_get_softc(dev); 41798542Smckusick struct mii_data *mii = GET_MII(sc); 41898542Smckusick uint16_t bmcr; 41998542Smckusick int locked; 42098542Smckusick 421105112Srwatson locked = mtx_owned(&sc->sc_mtx); 422200796Strasz if (!locked) 423200796Strasz RUE_LOCK(sc); 424105112Srwatson 425200796Strasz RUE_CLRBIT(sc, RUE_CR, (RUE_CR_RE | RUE_CR_TE)); 426200796Strasz 427200796Strasz bmcr = rue_csr_read_2(sc, RUE_BMCR); 428200796Strasz 429200796Strasz if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) 43034266Sjulian bmcr |= RUE_BMCR_SPD_SET; 431262779Spfg else 432262779Spfg bmcr &= ~RUE_BMCR_SPD_SET; 433262779Spfg 434207141Sjeff if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) 435262779Spfg bmcr |= RUE_BMCR_DUPLEX; 436262779Spfg else 437262779Spfg bmcr &= ~RUE_BMCR_DUPLEX; 438262779Spfg 439262779Spfg rue_csr_write_2(sc, RUE_BMCR, bmcr); 440262779Spfg 441216796Skib RUE_SETBIT(sc, RUE_CR, (RUE_CR_RE | RUE_CR_TE)); 44234266Sjulian 44334266Sjulian if (!locked) 44488138Smckusick RUE_UNLOCK(sc); 44588138Smckusick#endif 44688138Smckusick} 44789450Smckusick 448140702Sjeffstatic void 449140702Sjeffrue_setpromisc(struct usb_ether *ue) 450140702Sjeff{ 451140702Sjeff struct rue_softc *sc = uether_getsc(ue); 452140702Sjeff struct ifnet *ifp = uether_getifp(ue); 453140702Sjeff 454140702Sjeff RUE_LOCK_ASSERT(sc, MA_OWNED); 455140702Sjeff 45688138Smckusick /* If we want promiscuous mode, set the allframes bit. */ 45788138Smckusick if (ifp->if_flags & IFF_PROMISC) 4581541Srgrimes RUE_SETBIT(sc, RUE_RCR, RUE_RCR_AAP); 4591541Srgrimes else 4608876Srgrimes RUE_CLRBIT(sc, RUE_RCR, RUE_RCR_AAP); 4611541Srgrimes} 4621541Srgrimes 463262779Spfg/* 46422521Sdyson * Program the 64-bit multicast hash filter. 46598542Smckusick */ 46698542Smckusickstatic void 4671541Srgrimesrue_setmulti(struct usb_ether *ue) 46898542Smckusick{ 4691541Srgrimes struct rue_softc *sc = uether_getsc(ue); 47022521Sdyson struct ifnet *ifp = uether_getifp(ue); 47198542Smckusick uint16_t rxcfg; 4721541Srgrimes int h = 0; 4731541Srgrimes uint32_t hashes[2] = { 0, 0 }; 47498542Smckusick struct ifmultiaddr *ifma; 47598542Smckusick int mcnt = 0; 476262779Spfg 47798542Smckusick RUE_LOCK_ASSERT(sc, MA_OWNED); 47898542Smckusick 4791541Srgrimes rxcfg = rue_csr_read_2(sc, RUE_RCR); 4801541Srgrimes 481262779Spfg if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 4821541Srgrimes rxcfg |= (RUE_RCR_AAM | RUE_RCR_AAP); 4831541Srgrimes rxcfg &= ~RUE_RCR_AM; 48496755Strhodes rue_csr_write_2(sc, RUE_RCR, rxcfg); 4851541Srgrimes rue_csr_write_4(sc, RUE_MAR0, 0xFFFFFFFF); 4861541Srgrimes rue_csr_write_4(sc, RUE_MAR4, 0xFFFFFFFF); 48722521Sdyson return; 48822521Sdyson } 48922521Sdyson 49098542Smckusick /* first, zot all the existing hash bits */ 491203763Smckusick rue_csr_write_4(sc, RUE_MAR0, 0); 49298542Smckusick rue_csr_write_4(sc, RUE_MAR4, 0); 49398542Smckusick 494203763Smckusick /* now program new ones */ 495203763Smckusick if_maddr_rlock(ifp); 496203763Smckusick TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) 497203763Smckusick { 498203763Smckusick if (ifma->ifma_addr->sa_family != AF_LINK) 499203763Smckusick continue; 50098542Smckusick h = ether_crc32_be(LLADDR((struct sockaddr_dl *) 50198542Smckusick ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; 502203763Smckusick if (h < 32) 503203763Smckusick hashes[0] |= (1 << h); 504203763Smckusick else 505203763Smckusick hashes[1] |= (1 << (h - 32)); 506203763Smckusick mcnt++; 507203763Smckusick } 508203763Smckusick if_maddr_runlock(ifp); 509203763Smckusick 510203763Smckusick if (mcnt) 511163841Spjd rxcfg |= RUE_RCR_AM; 51298542Smckusick else 51398542Smckusick rxcfg &= ~RUE_RCR_AM; 51422521Sdyson 5151541Srgrimes rxcfg &= ~(RUE_RCR_AAM | RUE_RCR_AAP); 5161541Srgrimes 51722521Sdyson rue_csr_write_2(sc, RUE_RCR, rxcfg); 5181541Srgrimes rue_csr_write_4(sc, RUE_MAR0, hashes[0]); 5191541Srgrimes rue_csr_write_4(sc, RUE_MAR4, hashes[1]); 5201541Srgrimes} 521262779Spfg 522262779Spfgstatic void 52398542Smckusickrue_reset(struct rue_softc *sc) 524262779Spfg{ 52598542Smckusick int i; 526262779Spfg 52722521Sdyson rue_csr_write_1(sc, RUE_CR, RUE_CR_SOFT_RST); 528262779Spfg 529127818Smux for (i = 0; i != RUE_TIMEOUT; i++) { 5301541Srgrimes if (uether_pause(&sc->sc_ue, hz / 1000)) 5311541Srgrimes break; 53296755Strhodes if (!(rue_csr_read_1(sc, RUE_CR) & RUE_CR_SOFT_RST)) 53396755Strhodes break; 5341541Srgrimes } 535136336Snjl if (i == RUE_TIMEOUT) 5361541Srgrimes device_printf(sc->sc_ue.ue_dev, "reset never completed\n"); 5371541Srgrimes 5381541Srgrimes uether_pause(&sc->sc_ue, hz / 100); 5391541Srgrimes} 54096755Strhodes 5411541Srgrimesstatic void 542111238Smckusickrue_attach_post(struct usb_ether *ue) 543248623Smckusick{ 544248623Smckusick struct rue_softc *sc = uether_getsc(ue); 5451541Srgrimes 5461541Srgrimes /* reset the adapter */ 5471541Srgrimes rue_reset(sc); 5481541Srgrimes 549262779Spfg /* get station address from the EEPROM */ 55098542Smckusick rue_read_mem(sc, RUE_EEPROM_IDR0, ue->ue_eaddr, ETHER_ADDR_LEN); 55198542Smckusick} 5521541Srgrimes 5531541Srgrimes/* 5541541Srgrimes * Probe for a RTL8150 chip. 55596755Strhodes */ 5561541Srgrimesstatic int 55796755Strhodesrue_probe(device_t dev) 5581541Srgrimes{ 559203763Smckusick struct usb_attach_arg *uaa = device_get_ivars(dev); 5601541Srgrimes 561203763Smckusick if (uaa->usb_mode != USB_MODE_HOST) 562203763Smckusick return (ENXIO); 563203763Smckusick if (uaa->info.bConfigIndex != RUE_CONFIG_IDX) 5641541Srgrimes return (ENXIO); 5651541Srgrimes if (uaa->info.bIfaceIndex != RUE_IFACE_IDX) 56696755Strhodes return (ENXIO); 56796755Strhodes 5681541Srgrimes return (usbd_lookup_id_by_uaa(rue_devs, sizeof(rue_devs), uaa)); 5691541Srgrimes} 5701541Srgrimes 5711541Srgrimes/* 5721541Srgrimes * Attach the interface. Allocate softc structures, do ifmedia 5731541Srgrimes * setup and ethernet/BPF attach. 5741541Srgrimes */ 5751541Srgrimesstatic int 576262779Spfgrue_attach(device_t dev) 5771541Srgrimes{ 5781541Srgrimes struct usb_attach_arg *uaa = device_get_ivars(dev); 5791541Srgrimes struct rue_softc *sc = device_get_softc(dev); 5801541Srgrimes struct usb_ether *ue = &sc->sc_ue; 5811541Srgrimes uint8_t iface_index; 5821541Srgrimes int error; 5831541Srgrimes 584262779Spfg device_set_usb_desc(dev); 5851541Srgrimes mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 586262779Spfg 5871541Srgrimes iface_index = RUE_IFACE_IDX; 588262779Spfg error = usbd_transfer_setup(uaa->device, &iface_index, 589111238Smckusick sc->sc_xfer, rue_config, RUE_N_TRANSFER, 590262779Spfg sc, &sc->sc_mtx); 591111238Smckusick if (error) { 59218899Sbde device_printf(dev, "allocating USB transfers failed\n"); 593262779Spfg goto detach; 5941541Srgrimes } 595262779Spfg 5961541Srgrimes ue->ue_sc = sc; 597262779Spfg ue->ue_dev = dev; 5981541Srgrimes ue->ue_udev = uaa->device; 599262779Spfg ue->ue_mtx = &sc->sc_mtx; 6001541Srgrimes ue->ue_methods = &rue_ue_methods; 601262779Spfg 6021541Srgrimes error = uether_ifattach(ue); 603262779Spfg if (error) { 6041541Srgrimes device_printf(dev, "could not attach interface\n"); 605262779Spfg goto detach; 6061541Srgrimes } 607262779Spfg return (0); /* success */ 6081541Srgrimes 609262779Spfgdetach: 6101541Srgrimes rue_detach(dev); 6111541Srgrimes return (ENXIO); /* failure */ 6121541Srgrimes} 6131541Srgrimes 61422521Sdysonstatic int 6151541Srgrimesrue_detach(device_t dev) 616262779Spfg{ 6171541Srgrimes struct rue_softc *sc = device_get_softc(dev); 61858155Smckusick struct usb_ether *ue = &sc->sc_ue; 619111238Smckusick 6201541Srgrimes usbd_transfer_unsetup(sc->sc_xfer, RUE_N_TRANSFER); 6211541Srgrimes uether_ifdetach(ue); 62296755Strhodes mtx_destroy(&sc->sc_mtx); 6231541Srgrimes 624262779Spfg return (0); 62518899Sbde} 6261541Srgrimes 6271541Srgrimesstatic void 628262779Spfgrue_intr_callback(struct usb_xfer *xfer, usb_error_t error) 62934266Sjulian{ 63034266Sjulian struct rue_softc *sc = usbd_xfer_softc(xfer); 63134266Sjulian struct ifnet *ifp = uether_getifp(&sc->sc_ue); 6321541Srgrimes struct rue_intrpkt pkt; 6331541Srgrimes struct usb_page_cache *pc; 634215113Skib int actlen; 635215113Skib 636215113Skib usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 637215113Skib 638215113Skib switch (USB_GET_STATE(xfer)) { 639207141Sjeff case USB_ST_TRANSFERRED: 640207141Sjeff 641207141Sjeff if (ifp && (ifp->if_drv_flags & IFF_DRV_RUNNING) && 642207141Sjeff actlen >= (int)sizeof(pkt)) { 643207141Sjeff 644207141Sjeff pc = usbd_xfer_get_frame(xfer, 0); 645207141Sjeff usbd_copy_out(pc, 0, &pkt, sizeof(pkt)); 646207141Sjeff 647207141Sjeff ifp->if_ierrors += pkt.rue_rxlost_cnt; 648207141Sjeff ifp->if_ierrors += pkt.rue_crcerr_cnt; 649207141Sjeff ifp->if_collisions += pkt.rue_col_cnt; 650207141Sjeff } 651207141Sjeff /* FALLTHROUGH */ 652207141Sjeff case USB_ST_SETUP: 653207141Sjefftr_setup: 654207141Sjeff usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 655207141Sjeff usbd_transfer_submit(xfer); 656207141Sjeff return; 657207141Sjeff 658207141Sjeff default: /* Error */ 659207141Sjeff if (error != USB_ERR_CANCELLED) { 660207141Sjeff /* try to clear stall first */ 661207141Sjeff usbd_xfer_set_stall(xfer); 662207141Sjeff goto tr_setup; 663215113Skib } 664215113Skib return; 665215113Skib } 666215113Skib} 667215113Skib 668215113Skibstatic void 669215113Skibrue_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 670215113Skib{ 671215113Skib struct rue_softc *sc = usbd_xfer_softc(xfer); 672215113Skib struct usb_ether *ue = &sc->sc_ue; 673215113Skib struct ifnet *ifp = uether_getifp(ue); 674207141Sjeff struct usb_page_cache *pc; 67522521Sdyson uint16_t status; 6761541Srgrimes int actlen; 6771541Srgrimes 6781541Srgrimes usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 6791541Srgrimes 6801541Srgrimes switch (USB_GET_STATE(xfer)) { 681207141Sjeff case USB_ST_TRANSFERRED: 682207141Sjeff 683207141Sjeff if (actlen < 4) { 684207141Sjeff ifp->if_ierrors++; 685207141Sjeff goto tr_setup; 686207141Sjeff } 687207141Sjeff pc = usbd_xfer_get_frame(xfer, 0); 688207141Sjeff usbd_copy_out(pc, actlen - 4, &status, sizeof(status)); 689207141Sjeff actlen -= 4; 690222958Sjeff 691207141Sjeff /* check recieve packet was valid or not */ 692207141Sjeff status = le16toh(status); 693207141Sjeff if ((status & RUE_RXSTAT_VALID) == 0) { 694207141Sjeff ifp->if_ierrors++; 695207141Sjeff goto tr_setup; 696207141Sjeff } 697207141Sjeff uether_rxbuf(ue, pc, 0, actlen); 698207141Sjeff /* FALLTHROUGH */ 699207141Sjeff case USB_ST_SETUP: 700212617Smckusicktr_setup: 701207141Sjeff usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 702207141Sjeff usbd_transfer_submit(xfer); 703207141Sjeff uether_rxflush(ue); 704207141Sjeff return; 705207141Sjeff 706207141Sjeff default: /* Error */ 707207141Sjeff DPRINTF("bulk read error, %s\n", 708207141Sjeff usbd_errstr(error)); 709218602Skib 710207141Sjeff if (error != USB_ERR_CANCELLED) { 711207141Sjeff /* try to clear stall first */ 712207141Sjeff usbd_xfer_set_stall(xfer); 713207141Sjeff goto tr_setup; 714207141Sjeff } 715207141Sjeff return; 716207141Sjeff } 717207141Sjeff} 718207141Sjeff 719227382Sglebstatic void 720227382Sglebrue_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 721207141Sjeff{ 722207141Sjeff struct rue_softc *sc = usbd_xfer_softc(xfer); 723227382Sgleb struct ifnet *ifp = uether_getifp(&sc->sc_ue); 724207141Sjeff struct usb_page_cache *pc; 725207141Sjeff struct mbuf *m; 726207141Sjeff int temp_len; 727207141Sjeff 728207141Sjeff switch (USB_GET_STATE(xfer)) { 729207141Sjeff case USB_ST_TRANSFERRED: 730207141Sjeff DPRINTFN(11, "transfer complete\n"); 731207141Sjeff ifp->if_opackets++; 732207141Sjeff 733227382Sgleb /* FALLTHROUGH */ 734227382Sgleb case USB_ST_SETUP: 735207141Sjefftr_setup: 736227382Sgleb if ((sc->sc_flags & RUE_FLAG_LINK) == 0) { 737227382Sgleb /* 738207141Sjeff * don't send anything if there is no link ! 739207141Sjeff */ 740207141Sjeff return; 741207141Sjeff } 742207141Sjeff IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 743207141Sjeff 744207141Sjeff if (m == NULL) 745207141Sjeff return; 746207141Sjeff if (m->m_pkthdr.len > MCLBYTES) 747207141Sjeff m->m_pkthdr.len = MCLBYTES; 748207141Sjeff temp_len = m->m_pkthdr.len; 749207141Sjeff 750207141Sjeff pc = usbd_xfer_get_frame(xfer, 0); 751207141Sjeff usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len); 752207141Sjeff 753207141Sjeff /* 754207141Sjeff * This is an undocumented behavior. 755207141Sjeff * RTL8150 chip doesn't send frame length smaller than 756222958Sjeff * RUE_MIN_FRAMELEN (60) byte packet. 757207141Sjeff */ 758207141Sjeff if (temp_len < RUE_MIN_FRAMELEN) { 759207141Sjeff usbd_frame_zero(pc, temp_len, 760207141Sjeff RUE_MIN_FRAMELEN - temp_len); 761227382Sgleb temp_len = RUE_MIN_FRAMELEN; 762207141Sjeff } 763207141Sjeff usbd_xfer_set_frame_len(xfer, 0, temp_len); 764207141Sjeff 765207141Sjeff /* 766207141Sjeff * if there's a BPF listener, bounce a copy 767207141Sjeff * of this frame to him: 768207141Sjeff */ 769207141Sjeff BPF_MTAP(ifp, m); 770207141Sjeff 771207141Sjeff m_freem(m); 772207141Sjeff 773207141Sjeff usbd_transfer_submit(xfer); 774207141Sjeff 775207141Sjeff return; 776207141Sjeff 777207141Sjeff default: /* Error */ 778207141Sjeff DPRINTFN(11, "transfer error, %s\n", 779207141Sjeff usbd_errstr(error)); 780207141Sjeff 781207141Sjeff ifp->if_oerrors++; 782207141Sjeff 7831541Srgrimes if (error != USB_ERR_CANCELLED) { 7841541Srgrimes /* try to clear stall first */ 7852176Spaul usbd_xfer_set_stall(xfer); 786243245Strasz goto tr_setup; 787243245Strasz } 788243245Strasz return; 789243245Strasz } 790243245Strasz} 791243245Strasz 7922176Spaulstatic void 793rue_tick(struct usb_ether *ue) 794{ 795 struct rue_softc *sc = uether_getsc(ue); 796 struct mii_data *mii = GET_MII(sc); 797 798 RUE_LOCK_ASSERT(sc, MA_OWNED); 799 800 mii_tick(mii); 801 if ((sc->sc_flags & RUE_FLAG_LINK) == 0 802 && mii->mii_media_status & IFM_ACTIVE && 803 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 804 sc->sc_flags |= RUE_FLAG_LINK; 805 rue_start(ue); 806 } 807} 808 809static void 810rue_start(struct usb_ether *ue) 811{ 812 struct rue_softc *sc = uether_getsc(ue); 813 814 /* 815 * start the USB transfers, if not already started: 816 */ 817 usbd_transfer_start(sc->sc_xfer[RUE_INTR_DT_RD]); 818 usbd_transfer_start(sc->sc_xfer[RUE_BULK_DT_RD]); 819 usbd_transfer_start(sc->sc_xfer[RUE_BULK_DT_WR]); 820} 821 822static void 823rue_init(struct usb_ether *ue) 824{ 825 struct rue_softc *sc = uether_getsc(ue); 826 struct ifnet *ifp = uether_getifp(ue); 827 828 RUE_LOCK_ASSERT(sc, MA_OWNED); 829 830 /* 831 * Cancel pending I/O 832 */ 833 rue_reset(sc); 834 835 /* Set MAC address */ 836 rue_write_mem(sc, RUE_IDR0, IF_LLADDR(ifp), ETHER_ADDR_LEN); 837 838 rue_stop(ue); 839 840 /* 841 * Set the initial TX and RX configuration. 842 */ 843 rue_csr_write_1(sc, RUE_TCR, RUE_TCR_CONFIG); 844 rue_csr_write_2(sc, RUE_RCR, RUE_RCR_CONFIG|RUE_RCR_AB); 845 846 /* Load the multicast filter */ 847 rue_setpromisc(ue); 848 /* Load the multicast filter. */ 849 rue_setmulti(ue); 850 851 /* Enable RX and TX */ 852 rue_csr_write_1(sc, RUE_CR, (RUE_CR_TE | RUE_CR_RE | RUE_CR_EP3CLREN)); 853 854 usbd_xfer_set_stall(sc->sc_xfer[RUE_BULK_DT_WR]); 855 856 ifp->if_drv_flags |= IFF_DRV_RUNNING; 857 rue_start(ue); 858} 859 860/* 861 * Set media options. 862 */ 863static int 864rue_ifmedia_upd(struct ifnet *ifp) 865{ 866 struct rue_softc *sc = ifp->if_softc; 867 struct mii_data *mii = GET_MII(sc); 868 struct mii_softc *miisc; 869 int error; 870 871 RUE_LOCK_ASSERT(sc, MA_OWNED); 872 873 sc->sc_flags &= ~RUE_FLAG_LINK; 874 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 875 PHY_RESET(miisc); 876 error = mii_mediachg(mii); 877 return (error); 878} 879 880/* 881 * Report current media status. 882 */ 883static void 884rue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 885{ 886 struct rue_softc *sc = ifp->if_softc; 887 struct mii_data *mii = GET_MII(sc); 888 889 RUE_LOCK(sc); 890 mii_pollstat(mii); 891 ifmr->ifm_active = mii->mii_media_active; 892 ifmr->ifm_status = mii->mii_media_status; 893 RUE_UNLOCK(sc); 894} 895 896static void 897rue_stop(struct usb_ether *ue) 898{ 899 struct rue_softc *sc = uether_getsc(ue); 900 struct ifnet *ifp = uether_getifp(ue); 901 902 RUE_LOCK_ASSERT(sc, MA_OWNED); 903 904 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 905 sc->sc_flags &= ~RUE_FLAG_LINK; 906 907 /* 908 * stop all the transfers, if not already stopped: 909 */ 910 usbd_transfer_stop(sc->sc_xfer[RUE_BULK_DT_WR]); 911 usbd_transfer_stop(sc->sc_xfer[RUE_BULK_DT_RD]); 912 usbd_transfer_stop(sc->sc_xfer[RUE_INTR_DT_RD]); 913 914 rue_csr_write_1(sc, RUE_CR, 0x00); 915 916 rue_reset(sc); 917} 918