1e1b74f21SKevin Lo /*- 2a24d62b5SKevin Lo * Copyright (c) 2015-2016 Kevin Lo <kevlo@FreeBSD.org> 3e1b74f21SKevin Lo * All rights reserved. 4e1b74f21SKevin Lo * 5e1b74f21SKevin Lo * Redistribution and use in source and binary forms, with or without 6e1b74f21SKevin Lo * modification, are permitted provided that the following conditions 7e1b74f21SKevin Lo * are met: 8e1b74f21SKevin Lo * 1. Redistributions of source code must retain the above copyright 9e1b74f21SKevin Lo * notice, this list of conditions and the following disclaimer. 10e1b74f21SKevin Lo * 2. Redistributions in binary form must reproduce the above copyright 11e1b74f21SKevin Lo * notice, this list of conditions and the following disclaimer in the 12e1b74f21SKevin Lo * documentation and/or other materials provided with the distribution. 13e1b74f21SKevin Lo * 14e1b74f21SKevin Lo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15e1b74f21SKevin Lo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16e1b74f21SKevin Lo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17e1b74f21SKevin Lo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18e1b74f21SKevin Lo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19e1b74f21SKevin Lo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20e1b74f21SKevin Lo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21e1b74f21SKevin Lo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22e1b74f21SKevin Lo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23e1b74f21SKevin Lo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24e1b74f21SKevin Lo * SUCH DAMAGE. 25e1b74f21SKevin Lo */ 26e1b74f21SKevin Lo 27e1b74f21SKevin Lo #include <sys/cdefs.h> 28e1b74f21SKevin Lo __FBSDID("$FreeBSD$"); 29e1b74f21SKevin Lo 30e1b74f21SKevin Lo #include <sys/param.h> 31e1b74f21SKevin Lo #include <sys/systm.h> 32e1b74f21SKevin Lo #include <sys/bus.h> 33e1b74f21SKevin Lo #include <sys/condvar.h> 34e1b74f21SKevin Lo #include <sys/kernel.h> 35e1b74f21SKevin Lo #include <sys/lock.h> 36e1b74f21SKevin Lo #include <sys/module.h> 37e1b74f21SKevin Lo #include <sys/mutex.h> 38e1b74f21SKevin Lo #include <sys/socket.h> 39e1b74f21SKevin Lo #include <sys/sysctl.h> 40e1b74f21SKevin Lo #include <sys/unistd.h> 41e1b74f21SKevin Lo 42e1b74f21SKevin Lo #include <net/if.h> 43e1b74f21SKevin Lo #include <net/if_var.h> 44e1b74f21SKevin Lo 45e1b74f21SKevin Lo #include <dev/usb/usb.h> 46e1b74f21SKevin Lo #include <dev/usb/usbdi.h> 47e1b74f21SKevin Lo #include <dev/usb/usbdi_util.h> 48e1b74f21SKevin Lo #include "usbdevs.h" 49e1b74f21SKevin Lo 50e1b74f21SKevin Lo #define USB_DEBUG_VAR ure_debug 51e1b74f21SKevin Lo #include <dev/usb/usb_debug.h> 52e1b74f21SKevin Lo #include <dev/usb/usb_process.h> 53e1b74f21SKevin Lo 54e1b74f21SKevin Lo #include <dev/usb/net/usb_ethernet.h> 55e1b74f21SKevin Lo #include <dev/usb/net/if_urereg.h> 56e1b74f21SKevin Lo 57e1b74f21SKevin Lo #ifdef USB_DEBUG 58e1b74f21SKevin Lo static int ure_debug = 0; 59e1b74f21SKevin Lo 60e1b74f21SKevin Lo static SYSCTL_NODE(_hw_usb, OID_AUTO, ure, CTLFLAG_RW, 0, "USB ure"); 61e1b74f21SKevin Lo SYSCTL_INT(_hw_usb_ure, OID_AUTO, debug, CTLFLAG_RWTUN, &ure_debug, 0, 62e1b74f21SKevin Lo "Debug level"); 63e1b74f21SKevin Lo #endif 64e1b74f21SKevin Lo 65e1b74f21SKevin Lo /* 66e1b74f21SKevin Lo * Various supported device vendors/products. 67e1b74f21SKevin Lo */ 68e1b74f21SKevin Lo static const STRUCT_USB_HOST_ID ure_devs[] = { 69a24d62b5SKevin Lo #define URE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } 70*21d36c96SKevin Lo URE_DEV(LENOVO, RTL8153, 0), 71a24d62b5SKevin Lo URE_DEV(REALTEK, RTL8152, URE_FLAG_8152), 72a24d62b5SKevin Lo URE_DEV(REALTEK, RTL8153, 0), 73e1b74f21SKevin Lo #undef URE_DEV 74e1b74f21SKevin Lo }; 75e1b74f21SKevin Lo 76e1b74f21SKevin Lo static device_probe_t ure_probe; 77e1b74f21SKevin Lo static device_attach_t ure_attach; 78e1b74f21SKevin Lo static device_detach_t ure_detach; 79e1b74f21SKevin Lo 80e1b74f21SKevin Lo static usb_callback_t ure_bulk_read_callback; 81e1b74f21SKevin Lo static usb_callback_t ure_bulk_write_callback; 82e1b74f21SKevin Lo 83e1b74f21SKevin Lo static miibus_readreg_t ure_miibus_readreg; 84e1b74f21SKevin Lo static miibus_writereg_t ure_miibus_writereg; 85e1b74f21SKevin Lo static miibus_statchg_t ure_miibus_statchg; 86e1b74f21SKevin Lo 87e1b74f21SKevin Lo static uether_fn_t ure_attach_post; 88e1b74f21SKevin Lo static uether_fn_t ure_init; 89e1b74f21SKevin Lo static uether_fn_t ure_stop; 90e1b74f21SKevin Lo static uether_fn_t ure_start; 91e1b74f21SKevin Lo static uether_fn_t ure_tick; 92a24d62b5SKevin Lo static uether_fn_t ure_rxfilter; 93e1b74f21SKevin Lo 94e1b74f21SKevin Lo static int ure_ctl(struct ure_softc *, uint8_t, uint16_t, uint16_t, 95e1b74f21SKevin Lo void *, int); 96e1b74f21SKevin Lo static int ure_read_mem(struct ure_softc *, uint16_t, uint16_t, void *, 97e1b74f21SKevin Lo int); 98e1b74f21SKevin Lo static int ure_write_mem(struct ure_softc *, uint16_t, uint16_t, void *, 99e1b74f21SKevin Lo int); 100e1b74f21SKevin Lo static uint8_t ure_read_1(struct ure_softc *, uint16_t, uint16_t); 101e1b74f21SKevin Lo static uint16_t ure_read_2(struct ure_softc *, uint16_t, uint16_t); 102e1b74f21SKevin Lo static uint32_t ure_read_4(struct ure_softc *, uint16_t, uint16_t); 103e1b74f21SKevin Lo static int ure_write_1(struct ure_softc *, uint16_t, uint16_t, uint32_t); 104e1b74f21SKevin Lo static int ure_write_2(struct ure_softc *, uint16_t, uint16_t, uint32_t); 105e1b74f21SKevin Lo static int ure_write_4(struct ure_softc *, uint16_t, uint16_t, uint32_t); 106e1b74f21SKevin Lo static uint16_t ure_ocp_reg_read(struct ure_softc *, uint16_t); 107e1b74f21SKevin Lo static void ure_ocp_reg_write(struct ure_softc *, uint16_t, uint16_t); 108e1b74f21SKevin Lo 109e1b74f21SKevin Lo static void ure_read_chipver(struct ure_softc *); 110e1b74f21SKevin Lo static int ure_attach_post_sub(struct usb_ether *); 111e1b74f21SKevin Lo static void ure_reset(struct ure_softc *); 112e1b74f21SKevin Lo static int ure_ifmedia_upd(struct ifnet *); 113e1b74f21SKevin Lo static void ure_ifmedia_sts(struct ifnet *, struct ifmediareq *); 114e1b74f21SKevin Lo static int ure_ioctl(struct ifnet *, u_long, caddr_t); 115e1b74f21SKevin Lo static void ure_rtl8152_init(struct ure_softc *); 116a24d62b5SKevin Lo static void ure_rtl8153_init(struct ure_softc *); 117e1b74f21SKevin Lo static void ure_disable_teredo(struct ure_softc *); 118e1b74f21SKevin Lo static void ure_init_fifo(struct ure_softc *); 119e1b74f21SKevin Lo 120e1b74f21SKevin Lo static const struct usb_config ure_config[URE_N_TRANSFER] = { 121e1b74f21SKevin Lo [URE_BULK_DT_WR] = { 122e1b74f21SKevin Lo .type = UE_BULK, 123e1b74f21SKevin Lo .endpoint = UE_ADDR_ANY, 124e1b74f21SKevin Lo .direction = UE_DIR_OUT, 125e1b74f21SKevin Lo .bufsize = MCLBYTES, 126e1b74f21SKevin Lo .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 127e1b74f21SKevin Lo .callback = ure_bulk_write_callback, 128e1b74f21SKevin Lo .timeout = 10000, /* 10 seconds */ 129e1b74f21SKevin Lo }, 130e1b74f21SKevin Lo [URE_BULK_DT_RD] = { 131e1b74f21SKevin Lo .type = UE_BULK, 132e1b74f21SKevin Lo .endpoint = UE_ADDR_ANY, 133e1b74f21SKevin Lo .direction = UE_DIR_IN, 134a24d62b5SKevin Lo .bufsize = 16384, 135e1b74f21SKevin Lo .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 136e1b74f21SKevin Lo .callback = ure_bulk_read_callback, 137e1b74f21SKevin Lo .timeout = 0, /* no timeout */ 138e1b74f21SKevin Lo }, 139e1b74f21SKevin Lo }; 140e1b74f21SKevin Lo 141e1b74f21SKevin Lo static device_method_t ure_methods[] = { 142e1b74f21SKevin Lo /* Device interface. */ 143e1b74f21SKevin Lo DEVMETHOD(device_probe, ure_probe), 144e1b74f21SKevin Lo DEVMETHOD(device_attach, ure_attach), 145e1b74f21SKevin Lo DEVMETHOD(device_detach, ure_detach), 146e1b74f21SKevin Lo 147e1b74f21SKevin Lo /* MII interface. */ 148e1b74f21SKevin Lo DEVMETHOD(miibus_readreg, ure_miibus_readreg), 149e1b74f21SKevin Lo DEVMETHOD(miibus_writereg, ure_miibus_writereg), 150e1b74f21SKevin Lo DEVMETHOD(miibus_statchg, ure_miibus_statchg), 151e1b74f21SKevin Lo 152e1b74f21SKevin Lo DEVMETHOD_END 153e1b74f21SKevin Lo }; 154e1b74f21SKevin Lo 155e1b74f21SKevin Lo static driver_t ure_driver = { 156e1b74f21SKevin Lo .name = "ure", 157e1b74f21SKevin Lo .methods = ure_methods, 158e1b74f21SKevin Lo .size = sizeof(struct ure_softc), 159e1b74f21SKevin Lo }; 160e1b74f21SKevin Lo 161e1b74f21SKevin Lo static devclass_t ure_devclass; 162e1b74f21SKevin Lo 163e1b74f21SKevin Lo DRIVER_MODULE(ure, uhub, ure_driver, ure_devclass, NULL, NULL); 164e1b74f21SKevin Lo DRIVER_MODULE(miibus, ure, miibus_driver, miibus_devclass, NULL, NULL); 165e1b74f21SKevin Lo MODULE_DEPEND(ure, uether, 1, 1, 1); 166e1b74f21SKevin Lo MODULE_DEPEND(ure, usb, 1, 1, 1); 167e1b74f21SKevin Lo MODULE_DEPEND(ure, ether, 1, 1, 1); 168e1b74f21SKevin Lo MODULE_DEPEND(ure, miibus, 1, 1, 1); 169e1b74f21SKevin Lo MODULE_VERSION(ure, 1); 170e1b74f21SKevin Lo 171e1b74f21SKevin Lo static const struct usb_ether_methods ure_ue_methods = { 172e1b74f21SKevin Lo .ue_attach_post = ure_attach_post, 173e1b74f21SKevin Lo .ue_attach_post_sub = ure_attach_post_sub, 174e1b74f21SKevin Lo .ue_start = ure_start, 175e1b74f21SKevin Lo .ue_init = ure_init, 176e1b74f21SKevin Lo .ue_stop = ure_stop, 177e1b74f21SKevin Lo .ue_tick = ure_tick, 178a24d62b5SKevin Lo .ue_setmulti = ure_rxfilter, 179a24d62b5SKevin Lo .ue_setpromisc = ure_rxfilter, 180e1b74f21SKevin Lo .ue_mii_upd = ure_ifmedia_upd, 181e1b74f21SKevin Lo .ue_mii_sts = ure_ifmedia_sts, 182e1b74f21SKevin Lo }; 183e1b74f21SKevin Lo 184e1b74f21SKevin Lo static int 185e1b74f21SKevin Lo ure_ctl(struct ure_softc *sc, uint8_t rw, uint16_t val, uint16_t index, 186e1b74f21SKevin Lo void *buf, int len) 187e1b74f21SKevin Lo { 188e1b74f21SKevin Lo struct usb_device_request req; 189e1b74f21SKevin Lo 190e1b74f21SKevin Lo URE_LOCK_ASSERT(sc, MA_OWNED); 191e1b74f21SKevin Lo 192e1b74f21SKevin Lo if (rw == URE_CTL_WRITE) 193e1b74f21SKevin Lo req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 194e1b74f21SKevin Lo else 195e1b74f21SKevin Lo req.bmRequestType = UT_READ_VENDOR_DEVICE; 196e1b74f21SKevin Lo req.bRequest = UR_SET_ADDRESS; 197e1b74f21SKevin Lo USETW(req.wValue, val); 198e1b74f21SKevin Lo USETW(req.wIndex, index); 199e1b74f21SKevin Lo USETW(req.wLength, len); 200e1b74f21SKevin Lo 201e1b74f21SKevin Lo return (uether_do_request(&sc->sc_ue, &req, buf, 1000)); 202e1b74f21SKevin Lo } 203e1b74f21SKevin Lo 204e1b74f21SKevin Lo static int 205e1b74f21SKevin Lo ure_read_mem(struct ure_softc *sc, uint16_t addr, uint16_t index, 206e1b74f21SKevin Lo void *buf, int len) 207e1b74f21SKevin Lo { 208e1b74f21SKevin Lo 209e1b74f21SKevin Lo return (ure_ctl(sc, URE_CTL_READ, addr, index, buf, len)); 210e1b74f21SKevin Lo } 211e1b74f21SKevin Lo 212e1b74f21SKevin Lo static int 213e1b74f21SKevin Lo ure_write_mem(struct ure_softc *sc, uint16_t addr, uint16_t index, 214e1b74f21SKevin Lo void *buf, int len) 215e1b74f21SKevin Lo { 216e1b74f21SKevin Lo 217e1b74f21SKevin Lo return (ure_ctl(sc, URE_CTL_WRITE, addr, index, buf, len)); 218e1b74f21SKevin Lo } 219e1b74f21SKevin Lo 220e1b74f21SKevin Lo static uint8_t 221e1b74f21SKevin Lo ure_read_1(struct ure_softc *sc, uint16_t reg, uint16_t index) 222e1b74f21SKevin Lo { 223e1b74f21SKevin Lo uint32_t val; 224e1b74f21SKevin Lo uint8_t temp[4]; 225e1b74f21SKevin Lo uint8_t shift; 226e1b74f21SKevin Lo 227e1b74f21SKevin Lo shift = (reg & 3) << 3; 228e1b74f21SKevin Lo reg &= ~3; 229e1b74f21SKevin Lo 230e1b74f21SKevin Lo ure_read_mem(sc, reg, index, &temp, 4); 231e1b74f21SKevin Lo val = UGETDW(temp); 232e1b74f21SKevin Lo val >>= shift; 233e1b74f21SKevin Lo 234e1b74f21SKevin Lo return (val & 0xff); 235e1b74f21SKevin Lo } 236e1b74f21SKevin Lo 237e1b74f21SKevin Lo static uint16_t 238e1b74f21SKevin Lo ure_read_2(struct ure_softc *sc, uint16_t reg, uint16_t index) 239e1b74f21SKevin Lo { 240e1b74f21SKevin Lo uint32_t val; 241e1b74f21SKevin Lo uint8_t temp[4]; 242e1b74f21SKevin Lo uint8_t shift; 243e1b74f21SKevin Lo 244e1b74f21SKevin Lo shift = (reg & 2) << 3; 245e1b74f21SKevin Lo reg &= ~3; 246e1b74f21SKevin Lo 247e1b74f21SKevin Lo ure_read_mem(sc, reg, index, &temp, 4); 248e1b74f21SKevin Lo val = UGETDW(temp); 249e1b74f21SKevin Lo val >>= shift; 250e1b74f21SKevin Lo 251e1b74f21SKevin Lo return (val & 0xffff); 252e1b74f21SKevin Lo } 253e1b74f21SKevin Lo 254e1b74f21SKevin Lo static uint32_t 255e1b74f21SKevin Lo ure_read_4(struct ure_softc *sc, uint16_t reg, uint16_t index) 256e1b74f21SKevin Lo { 257e1b74f21SKevin Lo uint8_t temp[4]; 258e1b74f21SKevin Lo 259e1b74f21SKevin Lo ure_read_mem(sc, reg, index, &temp, 4); 260e1b74f21SKevin Lo return (UGETDW(temp)); 261e1b74f21SKevin Lo } 262e1b74f21SKevin Lo 263e1b74f21SKevin Lo static int 264e1b74f21SKevin Lo ure_write_1(struct ure_softc *sc, uint16_t reg, uint16_t index, uint32_t val) 265e1b74f21SKevin Lo { 266e1b74f21SKevin Lo uint16_t byen; 267e1b74f21SKevin Lo uint8_t temp[4]; 268e1b74f21SKevin Lo uint8_t shift; 269e1b74f21SKevin Lo 270e1b74f21SKevin Lo byen = URE_BYTE_EN_BYTE; 271e1b74f21SKevin Lo shift = reg & 3; 272e1b74f21SKevin Lo val &= 0xff; 273e1b74f21SKevin Lo 274e1b74f21SKevin Lo if (reg & 3) { 275e1b74f21SKevin Lo byen <<= shift; 276e1b74f21SKevin Lo val <<= (shift << 3); 277e1b74f21SKevin Lo reg &= ~3; 278e1b74f21SKevin Lo } 279e1b74f21SKevin Lo 280e1b74f21SKevin Lo USETDW(temp, val); 281e1b74f21SKevin Lo return (ure_write_mem(sc, reg, index | byen, &temp, 4)); 282e1b74f21SKevin Lo } 283e1b74f21SKevin Lo 284e1b74f21SKevin Lo static int 285e1b74f21SKevin Lo ure_write_2(struct ure_softc *sc, uint16_t reg, uint16_t index, uint32_t val) 286e1b74f21SKevin Lo { 287e1b74f21SKevin Lo uint16_t byen; 288e1b74f21SKevin Lo uint8_t temp[4]; 289e1b74f21SKevin Lo uint8_t shift; 290e1b74f21SKevin Lo 291e1b74f21SKevin Lo byen = URE_BYTE_EN_WORD; 292e1b74f21SKevin Lo shift = reg & 2; 293e1b74f21SKevin Lo val &= 0xffff; 294e1b74f21SKevin Lo 295e1b74f21SKevin Lo if (reg & 2) { 296e1b74f21SKevin Lo byen <<= shift; 297e1b74f21SKevin Lo val <<= (shift << 3); 298e1b74f21SKevin Lo reg &= ~3; 299e1b74f21SKevin Lo } 300e1b74f21SKevin Lo 301e1b74f21SKevin Lo USETDW(temp, val); 302e1b74f21SKevin Lo return (ure_write_mem(sc, reg, index | byen, &temp, 4)); 303e1b74f21SKevin Lo } 304e1b74f21SKevin Lo 305e1b74f21SKevin Lo static int 306e1b74f21SKevin Lo ure_write_4(struct ure_softc *sc, uint16_t reg, uint16_t index, uint32_t val) 307e1b74f21SKevin Lo { 308e1b74f21SKevin Lo uint8_t temp[4]; 309e1b74f21SKevin Lo 310e1b74f21SKevin Lo USETDW(temp, val); 311e1b74f21SKevin Lo return (ure_write_mem(sc, reg, index | URE_BYTE_EN_DWORD, &temp, 4)); 312e1b74f21SKevin Lo } 313e1b74f21SKevin Lo 314e1b74f21SKevin Lo static uint16_t 315e1b74f21SKevin Lo ure_ocp_reg_read(struct ure_softc *sc, uint16_t addr) 316e1b74f21SKevin Lo { 317e1b74f21SKevin Lo uint16_t reg; 318e1b74f21SKevin Lo 319e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_OCP_GPHY_BASE, URE_MCU_TYPE_PLA, addr & 0xf000); 320e1b74f21SKevin Lo reg = (addr & 0x0fff) | 0xb000; 321e1b74f21SKevin Lo 322e1b74f21SKevin Lo return (ure_read_2(sc, reg, URE_MCU_TYPE_PLA)); 323e1b74f21SKevin Lo } 324e1b74f21SKevin Lo 325e1b74f21SKevin Lo static void 326e1b74f21SKevin Lo ure_ocp_reg_write(struct ure_softc *sc, uint16_t addr, uint16_t data) 327e1b74f21SKevin Lo { 328e1b74f21SKevin Lo uint16_t reg; 329e1b74f21SKevin Lo 330e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_OCP_GPHY_BASE, URE_MCU_TYPE_PLA, addr & 0xf000); 331e1b74f21SKevin Lo reg = (addr & 0x0fff) | 0xb000; 332e1b74f21SKevin Lo 333e1b74f21SKevin Lo ure_write_2(sc, reg, URE_MCU_TYPE_PLA, data); 334e1b74f21SKevin Lo } 335e1b74f21SKevin Lo 336e1b74f21SKevin Lo static int 337e1b74f21SKevin Lo ure_miibus_readreg(device_t dev, int phy, int reg) 338e1b74f21SKevin Lo { 339e1b74f21SKevin Lo struct ure_softc *sc; 340e1b74f21SKevin Lo uint16_t val; 341e1b74f21SKevin Lo int locked; 342e1b74f21SKevin Lo 343e1b74f21SKevin Lo sc = device_get_softc(dev); 344e1b74f21SKevin Lo locked = mtx_owned(&sc->sc_mtx); 345e1b74f21SKevin Lo if (!locked) 346e1b74f21SKevin Lo URE_LOCK(sc); 347e1b74f21SKevin Lo 348a24d62b5SKevin Lo /* Let the rgephy driver read the URE_GMEDIASTAT register. */ 349a24d62b5SKevin Lo if (reg == URE_GMEDIASTAT) { 350a24d62b5SKevin Lo if (!locked) 351a24d62b5SKevin Lo URE_UNLOCK(sc); 352a24d62b5SKevin Lo return (ure_read_1(sc, URE_GMEDIASTAT, URE_MCU_TYPE_PLA)); 353a24d62b5SKevin Lo } 354a24d62b5SKevin Lo 355e1b74f21SKevin Lo val = ure_ocp_reg_read(sc, URE_OCP_BASE_MII + reg * 2); 356e1b74f21SKevin Lo 357e1b74f21SKevin Lo if (!locked) 358e1b74f21SKevin Lo URE_UNLOCK(sc); 359e1b74f21SKevin Lo return (val); 360e1b74f21SKevin Lo } 361e1b74f21SKevin Lo 362e1b74f21SKevin Lo static int 363e1b74f21SKevin Lo ure_miibus_writereg(device_t dev, int phy, int reg, int val) 364e1b74f21SKevin Lo { 365e1b74f21SKevin Lo struct ure_softc *sc; 366e1b74f21SKevin Lo int locked; 367e1b74f21SKevin Lo 368e1b74f21SKevin Lo sc = device_get_softc(dev); 369e1b74f21SKevin Lo if (sc->sc_phyno != phy) 370e1b74f21SKevin Lo return (0); 371e1b74f21SKevin Lo 372e1b74f21SKevin Lo locked = mtx_owned(&sc->sc_mtx); 373e1b74f21SKevin Lo if (!locked) 374e1b74f21SKevin Lo URE_LOCK(sc); 375e1b74f21SKevin Lo 376e1b74f21SKevin Lo ure_ocp_reg_write(sc, URE_OCP_BASE_MII + reg * 2, val); 377e1b74f21SKevin Lo 378e1b74f21SKevin Lo if (!locked) 379e1b74f21SKevin Lo URE_UNLOCK(sc); 380e1b74f21SKevin Lo return (0); 381e1b74f21SKevin Lo } 382e1b74f21SKevin Lo 383e1b74f21SKevin Lo static void 384e1b74f21SKevin Lo ure_miibus_statchg(device_t dev) 385e1b74f21SKevin Lo { 386e1b74f21SKevin Lo struct ure_softc *sc; 387e1b74f21SKevin Lo struct mii_data *mii; 388e1b74f21SKevin Lo struct ifnet *ifp; 389e1b74f21SKevin Lo int locked; 390e1b74f21SKevin Lo 391e1b74f21SKevin Lo sc = device_get_softc(dev); 392e1b74f21SKevin Lo mii = GET_MII(sc); 393e1b74f21SKevin Lo locked = mtx_owned(&sc->sc_mtx); 394e1b74f21SKevin Lo if (!locked) 395e1b74f21SKevin Lo URE_LOCK(sc); 396e1b74f21SKevin Lo 397e1b74f21SKevin Lo ifp = uether_getifp(&sc->sc_ue); 398e1b74f21SKevin Lo if (mii == NULL || ifp == NULL || 399e1b74f21SKevin Lo (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 400e1b74f21SKevin Lo goto done; 401e1b74f21SKevin Lo 402e1b74f21SKevin Lo sc->sc_flags &= ~URE_FLAG_LINK; 403e1b74f21SKevin Lo if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 404e1b74f21SKevin Lo (IFM_ACTIVE | IFM_AVALID)) { 405e1b74f21SKevin Lo switch (IFM_SUBTYPE(mii->mii_media_active)) { 406e1b74f21SKevin Lo case IFM_10_T: 407e1b74f21SKevin Lo case IFM_100_TX: 408e1b74f21SKevin Lo sc->sc_flags |= URE_FLAG_LINK; 409e1b74f21SKevin Lo break; 410a24d62b5SKevin Lo case IFM_1000_T: 411a24d62b5SKevin Lo if ((sc->sc_flags & URE_FLAG_8152) != 0) 412a24d62b5SKevin Lo break; 413a24d62b5SKevin Lo sc->sc_flags |= URE_FLAG_LINK; 414a24d62b5SKevin Lo break; 415e1b74f21SKevin Lo default: 416e1b74f21SKevin Lo break; 417e1b74f21SKevin Lo } 418e1b74f21SKevin Lo } 419e1b74f21SKevin Lo 420e1b74f21SKevin Lo /* Lost link, do nothing. */ 421e1b74f21SKevin Lo if ((sc->sc_flags & URE_FLAG_LINK) == 0) 422e1b74f21SKevin Lo goto done; 423e1b74f21SKevin Lo done: 424e1b74f21SKevin Lo if (!locked) 425e1b74f21SKevin Lo URE_UNLOCK(sc); 426e1b74f21SKevin Lo } 427e1b74f21SKevin Lo 428e1b74f21SKevin Lo /* 429a24d62b5SKevin Lo * Probe for a RTL8152/RTL8153 chip. 430e1b74f21SKevin Lo */ 431e1b74f21SKevin Lo static int 432e1b74f21SKevin Lo ure_probe(device_t dev) 433e1b74f21SKevin Lo { 434e1b74f21SKevin Lo struct usb_attach_arg *uaa; 435e1b74f21SKevin Lo 43674b8d63dSPedro F. Giffuni uaa = device_get_ivars(dev); 437e1b74f21SKevin Lo if (uaa->usb_mode != USB_MODE_HOST) 438e1b74f21SKevin Lo return (ENXIO); 439e1b74f21SKevin Lo if (uaa->info.bConfigIndex != URE_CONFIG_IDX) 440e1b74f21SKevin Lo return (ENXIO); 441e1b74f21SKevin Lo if (uaa->info.bIfaceIndex != URE_IFACE_IDX) 442e1b74f21SKevin Lo return (ENXIO); 443e1b74f21SKevin Lo 444e1b74f21SKevin Lo return (usbd_lookup_id_by_uaa(ure_devs, sizeof(ure_devs), uaa)); 445e1b74f21SKevin Lo } 446e1b74f21SKevin Lo 447e1b74f21SKevin Lo /* 448e1b74f21SKevin Lo * Attach the interface. Allocate softc structures, do ifmedia 449e1b74f21SKevin Lo * setup and ethernet/BPF attach. 450e1b74f21SKevin Lo */ 451e1b74f21SKevin Lo static int 452e1b74f21SKevin Lo ure_attach(device_t dev) 453e1b74f21SKevin Lo { 454e1b74f21SKevin Lo struct usb_attach_arg *uaa = device_get_ivars(dev); 455e1b74f21SKevin Lo struct ure_softc *sc = device_get_softc(dev); 456e1b74f21SKevin Lo struct usb_ether *ue = &sc->sc_ue; 457e1b74f21SKevin Lo uint8_t iface_index; 458e1b74f21SKevin Lo int error; 459e1b74f21SKevin Lo 460a24d62b5SKevin Lo sc->sc_flags = USB_GET_DRIVER_INFO(uaa); 461e1b74f21SKevin Lo device_set_usb_desc(dev); 462e1b74f21SKevin Lo mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 463e1b74f21SKevin Lo 464e1b74f21SKevin Lo iface_index = URE_IFACE_IDX; 465e1b74f21SKevin Lo error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, 466e1b74f21SKevin Lo ure_config, URE_N_TRANSFER, sc, &sc->sc_mtx); 467e1b74f21SKevin Lo if (error != 0) { 468e1b74f21SKevin Lo device_printf(dev, "allocating USB transfers failed\n"); 469e1b74f21SKevin Lo goto detach; 470e1b74f21SKevin Lo } 471e1b74f21SKevin Lo 472e1b74f21SKevin Lo ue->ue_sc = sc; 473e1b74f21SKevin Lo ue->ue_dev = dev; 474e1b74f21SKevin Lo ue->ue_udev = uaa->device; 475e1b74f21SKevin Lo ue->ue_mtx = &sc->sc_mtx; 476e1b74f21SKevin Lo ue->ue_methods = &ure_ue_methods; 477e1b74f21SKevin Lo 478e1b74f21SKevin Lo error = uether_ifattach(ue); 479e1b74f21SKevin Lo if (error != 0) { 480e1b74f21SKevin Lo device_printf(dev, "could not attach interface\n"); 481e1b74f21SKevin Lo goto detach; 482e1b74f21SKevin Lo } 483e1b74f21SKevin Lo return (0); /* success */ 484e1b74f21SKevin Lo 485e1b74f21SKevin Lo detach: 486e1b74f21SKevin Lo ure_detach(dev); 487e1b74f21SKevin Lo return (ENXIO); /* failure */ 488e1b74f21SKevin Lo } 489e1b74f21SKevin Lo 490e1b74f21SKevin Lo static int 491e1b74f21SKevin Lo ure_detach(device_t dev) 492e1b74f21SKevin Lo { 493e1b74f21SKevin Lo struct ure_softc *sc = device_get_softc(dev); 494e1b74f21SKevin Lo struct usb_ether *ue = &sc->sc_ue; 495e1b74f21SKevin Lo 496e1b74f21SKevin Lo usbd_transfer_unsetup(sc->sc_xfer, URE_N_TRANSFER); 497e1b74f21SKevin Lo uether_ifdetach(ue); 498e1b74f21SKevin Lo mtx_destroy(&sc->sc_mtx); 499e1b74f21SKevin Lo 500e1b74f21SKevin Lo return (0); 501e1b74f21SKevin Lo } 502e1b74f21SKevin Lo 503e1b74f21SKevin Lo static void 504e1b74f21SKevin Lo ure_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 505e1b74f21SKevin Lo { 506e1b74f21SKevin Lo struct ure_softc *sc = usbd_xfer_softc(xfer); 507e1b74f21SKevin Lo struct usb_ether *ue = &sc->sc_ue; 508e1b74f21SKevin Lo struct ifnet *ifp = uether_getifp(ue); 509e1b74f21SKevin Lo struct usb_page_cache *pc; 510e1b74f21SKevin Lo struct ure_rxpkt pkt; 511e1b74f21SKevin Lo int actlen, len; 512e1b74f21SKevin Lo 513e1b74f21SKevin Lo usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 514e1b74f21SKevin Lo 515e1b74f21SKevin Lo switch (USB_GET_STATE(xfer)) { 516e1b74f21SKevin Lo case USB_ST_TRANSFERRED: 517e1b74f21SKevin Lo if (actlen < (int)(sizeof(pkt))) { 518e1b74f21SKevin Lo if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 519e1b74f21SKevin Lo goto tr_setup; 520e1b74f21SKevin Lo } 521e1b74f21SKevin Lo pc = usbd_xfer_get_frame(xfer, 0); 522e1b74f21SKevin Lo usbd_copy_out(pc, 0, &pkt, sizeof(pkt)); 523e1b74f21SKevin Lo len = le32toh(pkt.ure_pktlen) & URE_RXPKT_LEN_MASK; 524e1b74f21SKevin Lo len -= ETHER_CRC_LEN; 525e1b74f21SKevin Lo if (actlen < (int)(len + sizeof(pkt))) { 526e1b74f21SKevin Lo if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 527e1b74f21SKevin Lo goto tr_setup; 528e1b74f21SKevin Lo } 529e1b74f21SKevin Lo 530e1b74f21SKevin Lo uether_rxbuf(ue, pc, sizeof(pkt), len); 531e1b74f21SKevin Lo /* FALLTHROUGH */ 532e1b74f21SKevin Lo case USB_ST_SETUP: 533e1b74f21SKevin Lo tr_setup: 534e1b74f21SKevin Lo usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 535e1b74f21SKevin Lo usbd_transfer_submit(xfer); 536e1b74f21SKevin Lo uether_rxflush(ue); 537e1b74f21SKevin Lo return; 538e1b74f21SKevin Lo 539e1b74f21SKevin Lo default: /* Error */ 540e1b74f21SKevin Lo DPRINTF("bulk read error, %s\n", 541e1b74f21SKevin Lo usbd_errstr(error)); 542e1b74f21SKevin Lo 543e1b74f21SKevin Lo if (error != USB_ERR_CANCELLED) { 544e1b74f21SKevin Lo /* try to clear stall first */ 545e1b74f21SKevin Lo usbd_xfer_set_stall(xfer); 546e1b74f21SKevin Lo goto tr_setup; 547e1b74f21SKevin Lo } 548e1b74f21SKevin Lo return; 549e1b74f21SKevin Lo } 550e1b74f21SKevin Lo } 551e1b74f21SKevin Lo 552e1b74f21SKevin Lo static void 553e1b74f21SKevin Lo ure_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 554e1b74f21SKevin Lo { 555e1b74f21SKevin Lo struct ure_softc *sc = usbd_xfer_softc(xfer); 556e1b74f21SKevin Lo struct ifnet *ifp = uether_getifp(&sc->sc_ue); 557e1b74f21SKevin Lo struct usb_page_cache *pc; 558e1b74f21SKevin Lo struct mbuf *m; 559e1b74f21SKevin Lo struct ure_txpkt txpkt; 560e1b74f21SKevin Lo int len, pos; 561e1b74f21SKevin Lo 562e1b74f21SKevin Lo switch (USB_GET_STATE(xfer)) { 563e1b74f21SKevin Lo case USB_ST_TRANSFERRED: 564e1b74f21SKevin Lo DPRINTFN(11, "transfer complete\n"); 565e1b74f21SKevin Lo ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 566e1b74f21SKevin Lo /* FALLTHROUGH */ 567e1b74f21SKevin Lo case USB_ST_SETUP: 568e1b74f21SKevin Lo tr_setup: 569e1b74f21SKevin Lo if ((sc->sc_flags & URE_FLAG_LINK) == 0 || 570e1b74f21SKevin Lo (ifp->if_drv_flags & IFF_DRV_OACTIVE) != 0) { 571e1b74f21SKevin Lo /* 572e1b74f21SKevin Lo * don't send anything if there is no link ! 573e1b74f21SKevin Lo */ 574e1b74f21SKevin Lo return; 575e1b74f21SKevin Lo } 576e1b74f21SKevin Lo IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 577e1b74f21SKevin Lo if (m == NULL) 578e1b74f21SKevin Lo break; 579e1b74f21SKevin Lo pos = 0; 580e1b74f21SKevin Lo len = m->m_pkthdr.len; 581e1b74f21SKevin Lo pc = usbd_xfer_get_frame(xfer, 0); 582e1b74f21SKevin Lo memset(&txpkt, 0, sizeof(txpkt)); 583e1b74f21SKevin Lo txpkt.ure_pktlen = htole32((len & URE_TXPKT_LEN_MASK) | 584e1b74f21SKevin Lo URE_TKPKT_TX_FS | URE_TKPKT_TX_LS); 585e1b74f21SKevin Lo usbd_copy_in(pc, pos, &txpkt, sizeof(txpkt)); 586e1b74f21SKevin Lo pos += sizeof(txpkt); 587e1b74f21SKevin Lo usbd_m_copy_in(pc, pos, m, 0, m->m_pkthdr.len); 588e1b74f21SKevin Lo pos += m->m_pkthdr.len; 589e1b74f21SKevin Lo 590e1b74f21SKevin Lo if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 591e1b74f21SKevin Lo 592e1b74f21SKevin Lo /* 593e1b74f21SKevin Lo * If there's a BPF listener, bounce a copy 594e1b74f21SKevin Lo * of this frame to him. 595e1b74f21SKevin Lo */ 596e1b74f21SKevin Lo BPF_MTAP(ifp, m); 597e1b74f21SKevin Lo 598e1b74f21SKevin Lo m_freem(m); 599e1b74f21SKevin Lo 600e1b74f21SKevin Lo /* Set frame length. */ 601e1b74f21SKevin Lo usbd_xfer_set_frame_len(xfer, 0, pos); 602e1b74f21SKevin Lo 603e1b74f21SKevin Lo usbd_transfer_submit(xfer); 604e1b74f21SKevin Lo ifp->if_drv_flags |= IFF_DRV_OACTIVE; 605e1b74f21SKevin Lo return; 606e1b74f21SKevin Lo default: /* Error */ 607e1b74f21SKevin Lo DPRINTFN(11, "transfer error, %s\n", 608e1b74f21SKevin Lo usbd_errstr(error)); 609e1b74f21SKevin Lo 610e1b74f21SKevin Lo if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 611e1b74f21SKevin Lo ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 612e1b74f21SKevin Lo 613e1b74f21SKevin Lo if (error != USB_ERR_CANCELLED) { 614e1b74f21SKevin Lo /* try to clear stall first */ 615e1b74f21SKevin Lo usbd_xfer_set_stall(xfer); 616e1b74f21SKevin Lo goto tr_setup; 617e1b74f21SKevin Lo } 618e1b74f21SKevin Lo return; 619e1b74f21SKevin Lo } 620e1b74f21SKevin Lo } 621e1b74f21SKevin Lo 622e1b74f21SKevin Lo static void 623e1b74f21SKevin Lo ure_read_chipver(struct ure_softc *sc) 624e1b74f21SKevin Lo { 625e1b74f21SKevin Lo uint16_t ver; 626e1b74f21SKevin Lo 627e1b74f21SKevin Lo ver = ure_read_2(sc, URE_PLA_TCR1, URE_MCU_TYPE_PLA) & URE_VERSION_MASK; 628e1b74f21SKevin Lo switch (ver) { 629e1b74f21SKevin Lo case 0x4c00: 630e1b74f21SKevin Lo sc->sc_chip |= URE_CHIP_VER_4C00; 631e1b74f21SKevin Lo break; 632e1b74f21SKevin Lo case 0x4c10: 633e1b74f21SKevin Lo sc->sc_chip |= URE_CHIP_VER_4C10; 634e1b74f21SKevin Lo break; 635a24d62b5SKevin Lo case 0x5c00: 636a24d62b5SKevin Lo sc->sc_chip |= URE_CHIP_VER_5C00; 637a24d62b5SKevin Lo break; 638a24d62b5SKevin Lo case 0x5c10: 639a24d62b5SKevin Lo sc->sc_chip |= URE_CHIP_VER_5C10; 640a24d62b5SKevin Lo break; 641a24d62b5SKevin Lo case 0x5c20: 642a24d62b5SKevin Lo sc->sc_chip |= URE_CHIP_VER_5C20; 643a24d62b5SKevin Lo break; 644a24d62b5SKevin Lo case 0x5c30: 645a24d62b5SKevin Lo sc->sc_chip |= URE_CHIP_VER_5C30; 646a24d62b5SKevin Lo break; 647e1b74f21SKevin Lo default: 648e1b74f21SKevin Lo device_printf(sc->sc_ue.ue_dev, 649e1b74f21SKevin Lo "unknown version 0x%04x\n", ver); 650e1b74f21SKevin Lo break; 651e1b74f21SKevin Lo } 652e1b74f21SKevin Lo } 653e1b74f21SKevin Lo 654e1b74f21SKevin Lo static void 655e1b74f21SKevin Lo ure_attach_post(struct usb_ether *ue) 656e1b74f21SKevin Lo { 657e1b74f21SKevin Lo struct ure_softc *sc = uether_getsc(ue); 658e1b74f21SKevin Lo 659e1b74f21SKevin Lo sc->sc_phyno = 0; 660e1b74f21SKevin Lo 661e1b74f21SKevin Lo /* Determine the chip version. */ 662e1b74f21SKevin Lo ure_read_chipver(sc); 663e1b74f21SKevin Lo 664e1b74f21SKevin Lo /* Initialize controller and get station address. */ 665a24d62b5SKevin Lo if (sc->sc_flags & URE_FLAG_8152) 666e1b74f21SKevin Lo ure_rtl8152_init(sc); 667a24d62b5SKevin Lo else 668a24d62b5SKevin Lo ure_rtl8153_init(sc); 669e1b74f21SKevin Lo 670e1b74f21SKevin Lo if (sc->sc_chip & URE_CHIP_VER_4C00) 671e1b74f21SKevin Lo ure_read_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA, 672e1b74f21SKevin Lo ue->ue_eaddr, 8); 673e1b74f21SKevin Lo else 674e1b74f21SKevin Lo ure_read_mem(sc, URE_PLA_BACKUP, URE_MCU_TYPE_PLA, 675e1b74f21SKevin Lo ue->ue_eaddr, 8); 676e1b74f21SKevin Lo } 677e1b74f21SKevin Lo 678e1b74f21SKevin Lo static int 679e1b74f21SKevin Lo ure_attach_post_sub(struct usb_ether *ue) 680e1b74f21SKevin Lo { 681e1b74f21SKevin Lo struct ure_softc *sc; 682e1b74f21SKevin Lo struct ifnet *ifp; 683e1b74f21SKevin Lo int error; 684e1b74f21SKevin Lo 685e1b74f21SKevin Lo sc = uether_getsc(ue); 686e1b74f21SKevin Lo ifp = ue->ue_ifp; 687e1b74f21SKevin Lo ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 688e1b74f21SKevin Lo ifp->if_start = uether_start; 689e1b74f21SKevin Lo ifp->if_ioctl = ure_ioctl; 690e1b74f21SKevin Lo ifp->if_init = uether_init; 691e1b74f21SKevin Lo IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); 692e1b74f21SKevin Lo ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; 693e1b74f21SKevin Lo IFQ_SET_READY(&ifp->if_snd); 694e1b74f21SKevin Lo 695e1b74f21SKevin Lo mtx_lock(&Giant); 696e1b74f21SKevin Lo error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp, 697e1b74f21SKevin Lo uether_ifmedia_upd, ue->ue_methods->ue_mii_sts, 698e1b74f21SKevin Lo BMSR_DEFCAPMASK, sc->sc_phyno, MII_OFFSET_ANY, 0); 699e1b74f21SKevin Lo mtx_unlock(&Giant); 700e1b74f21SKevin Lo 701e1b74f21SKevin Lo return (error); 702e1b74f21SKevin Lo } 703e1b74f21SKevin Lo 704e1b74f21SKevin Lo static void 705e1b74f21SKevin Lo ure_init(struct usb_ether *ue) 706e1b74f21SKevin Lo { 707e1b74f21SKevin Lo struct ure_softc *sc = uether_getsc(ue); 708e1b74f21SKevin Lo struct ifnet *ifp = uether_getifp(ue); 709e1b74f21SKevin Lo 710e1b74f21SKevin Lo URE_LOCK_ASSERT(sc, MA_OWNED); 711e1b74f21SKevin Lo 712e1b74f21SKevin Lo if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 713e1b74f21SKevin Lo return; 714e1b74f21SKevin Lo 715e1b74f21SKevin Lo /* Cancel pending I/O. */ 716e1b74f21SKevin Lo ure_stop(ue); 717e1b74f21SKevin Lo 718e1b74f21SKevin Lo ure_reset(sc); 719e1b74f21SKevin Lo 720e1b74f21SKevin Lo /* Set MAC address. */ 721e1b74f21SKevin Lo ure_write_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA | URE_BYTE_EN_SIX_BYTES, 722e1b74f21SKevin Lo IF_LLADDR(ifp), 8); 723e1b74f21SKevin Lo 724e1b74f21SKevin Lo /* Reset the packet filter. */ 725e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA, 726e1b74f21SKevin Lo ure_read_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA) & 727e1b74f21SKevin Lo ~URE_FMC_FCR_MCU_EN); 728e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA, 729e1b74f21SKevin Lo ure_read_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA) | 730e1b74f21SKevin Lo URE_FMC_FCR_MCU_EN); 731e1b74f21SKevin Lo 732e1b74f21SKevin Lo /* Enable transmit and receive. */ 733e1b74f21SKevin Lo ure_write_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, 734e1b74f21SKevin Lo ure_read_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA) | URE_CR_RE | 735e1b74f21SKevin Lo URE_CR_TE); 736e1b74f21SKevin Lo 737e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA, 738e1b74f21SKevin Lo ure_read_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA) & 739e1b74f21SKevin Lo ~URE_RXDY_GATED_EN); 740e1b74f21SKevin Lo 741a24d62b5SKevin Lo /* Configure RX filters. */ 742a24d62b5SKevin Lo ure_rxfilter(ue); 743e1b74f21SKevin Lo 744e1b74f21SKevin Lo usbd_xfer_set_stall(sc->sc_xfer[URE_BULK_DT_WR]); 745e1b74f21SKevin Lo 746e1b74f21SKevin Lo /* Indicate we are up and running. */ 747e1b74f21SKevin Lo ifp->if_drv_flags |= IFF_DRV_RUNNING; 748e1b74f21SKevin Lo 749e1b74f21SKevin Lo /* Switch to selected media. */ 750e1b74f21SKevin Lo ure_ifmedia_upd(ifp); 751e1b74f21SKevin Lo } 752e1b74f21SKevin Lo 753e1b74f21SKevin Lo static void 754e1b74f21SKevin Lo ure_tick(struct usb_ether *ue) 755e1b74f21SKevin Lo { 756e1b74f21SKevin Lo struct ure_softc *sc = uether_getsc(ue); 757e1b74f21SKevin Lo struct mii_data *mii = GET_MII(sc); 758e1b74f21SKevin Lo 759e1b74f21SKevin Lo URE_LOCK_ASSERT(sc, MA_OWNED); 760e1b74f21SKevin Lo 761e1b74f21SKevin Lo mii_tick(mii); 762e1b74f21SKevin Lo if ((sc->sc_flags & URE_FLAG_LINK) == 0 763e1b74f21SKevin Lo && mii->mii_media_status & IFM_ACTIVE && 764e1b74f21SKevin Lo IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 765e1b74f21SKevin Lo sc->sc_flags |= URE_FLAG_LINK; 766e1b74f21SKevin Lo ure_start(ue); 767e1b74f21SKevin Lo } 768e1b74f21SKevin Lo } 769e1b74f21SKevin Lo 770e1b74f21SKevin Lo /* 771e1b74f21SKevin Lo * Program the 64-bit multicast hash filter. 772e1b74f21SKevin Lo */ 773e1b74f21SKevin Lo static void 774a24d62b5SKevin Lo ure_rxfilter(struct usb_ether *ue) 775e1b74f21SKevin Lo { 776e1b74f21SKevin Lo struct ure_softc *sc = uether_getsc(ue); 777e1b74f21SKevin Lo struct ifnet *ifp = uether_getifp(ue); 778e1b74f21SKevin Lo struct ifmultiaddr *ifma; 779e1b74f21SKevin Lo uint32_t h, rxmode; 780e1b74f21SKevin Lo uint32_t hashes[2] = { 0, 0 }; 781e1b74f21SKevin Lo 782e1b74f21SKevin Lo URE_LOCK_ASSERT(sc, MA_OWNED); 783e1b74f21SKevin Lo 784a24d62b5SKevin Lo rxmode = URE_RCR_APM; 785a24d62b5SKevin Lo if (ifp->if_flags & IFF_BROADCAST) 786a24d62b5SKevin Lo rxmode |= URE_RCR_AB; 787e1b74f21SKevin Lo if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) { 788e1b74f21SKevin Lo if (ifp->if_flags & IFF_PROMISC) 789e1b74f21SKevin Lo rxmode |= URE_RCR_AAP; 790e1b74f21SKevin Lo rxmode |= URE_RCR_AM; 791e1b74f21SKevin Lo hashes[0] = hashes[1] = 0xffffffff; 792e1b74f21SKevin Lo goto done; 793e1b74f21SKevin Lo } 794e1b74f21SKevin Lo 795a24d62b5SKevin Lo rxmode |= URE_RCR_AM; 796e1b74f21SKevin Lo if_maddr_rlock(ifp); 797e1b74f21SKevin Lo TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 798e1b74f21SKevin Lo if (ifma->ifma_addr->sa_family != AF_LINK) 799e1b74f21SKevin Lo continue; 800e1b74f21SKevin Lo h = ether_crc32_be(LLADDR((struct sockaddr_dl *) 801e1b74f21SKevin Lo ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; 802e1b74f21SKevin Lo if (h < 32) 803e1b74f21SKevin Lo hashes[0] |= (1 << h); 804e1b74f21SKevin Lo else 805e1b74f21SKevin Lo hashes[1] |= (1 << (h - 32)); 806e1b74f21SKevin Lo } 807e1b74f21SKevin Lo if_maddr_runlock(ifp); 808e1b74f21SKevin Lo 809e1b74f21SKevin Lo h = bswap32(hashes[0]); 810e1b74f21SKevin Lo hashes[0] = bswap32(hashes[1]); 811e1b74f21SKevin Lo hashes[1] = h; 812e1b74f21SKevin Lo rxmode |= URE_RCR_AM; 813e1b74f21SKevin Lo 814e1b74f21SKevin Lo done: 815e1b74f21SKevin Lo ure_write_4(sc, URE_PLA_MAR0, URE_MCU_TYPE_PLA, hashes[0]); 816e1b74f21SKevin Lo ure_write_4(sc, URE_PLA_MAR4, URE_MCU_TYPE_PLA, hashes[1]); 817e1b74f21SKevin Lo ure_write_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, rxmode); 818e1b74f21SKevin Lo } 819e1b74f21SKevin Lo 820e1b74f21SKevin Lo static void 821e1b74f21SKevin Lo ure_start(struct usb_ether *ue) 822e1b74f21SKevin Lo { 823e1b74f21SKevin Lo struct ure_softc *sc = uether_getsc(ue); 824e1b74f21SKevin Lo 825e1b74f21SKevin Lo /* 826e1b74f21SKevin Lo * start the USB transfers, if not already started: 827e1b74f21SKevin Lo */ 828e1b74f21SKevin Lo usbd_transfer_start(sc->sc_xfer[URE_BULK_DT_RD]); 829e1b74f21SKevin Lo usbd_transfer_start(sc->sc_xfer[URE_BULK_DT_WR]); 830e1b74f21SKevin Lo } 831e1b74f21SKevin Lo 832e1b74f21SKevin Lo static void 833e1b74f21SKevin Lo ure_reset(struct ure_softc *sc) 834e1b74f21SKevin Lo { 835e1b74f21SKevin Lo int i; 836e1b74f21SKevin Lo 837e1b74f21SKevin Lo ure_write_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, URE_CR_RST); 838e1b74f21SKevin Lo 839e1b74f21SKevin Lo for (i = 0; i < URE_TIMEOUT; i++) { 840e1b74f21SKevin Lo if (!(ure_read_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA) & 841e1b74f21SKevin Lo URE_CR_RST)) 842e1b74f21SKevin Lo break; 843e1b74f21SKevin Lo uether_pause(&sc->sc_ue, hz / 100); 844e1b74f21SKevin Lo } 845e1b74f21SKevin Lo if (i == URE_TIMEOUT) 846e1b74f21SKevin Lo device_printf(sc->sc_ue.ue_dev, "reset never completed\n"); 847e1b74f21SKevin Lo } 848e1b74f21SKevin Lo 849e1b74f21SKevin Lo /* 850e1b74f21SKevin Lo * Set media options. 851e1b74f21SKevin Lo */ 852e1b74f21SKevin Lo static int 853e1b74f21SKevin Lo ure_ifmedia_upd(struct ifnet *ifp) 854e1b74f21SKevin Lo { 855e1b74f21SKevin Lo struct ure_softc *sc = ifp->if_softc; 856e1b74f21SKevin Lo struct mii_data *mii = GET_MII(sc); 857e1b74f21SKevin Lo struct mii_softc *miisc; 858e1b74f21SKevin Lo int error; 859e1b74f21SKevin Lo 860e1b74f21SKevin Lo URE_LOCK_ASSERT(sc, MA_OWNED); 861e1b74f21SKevin Lo 862e1b74f21SKevin Lo LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 863e1b74f21SKevin Lo PHY_RESET(miisc); 864e1b74f21SKevin Lo error = mii_mediachg(mii); 865e1b74f21SKevin Lo return (error); 866e1b74f21SKevin Lo } 867e1b74f21SKevin Lo 868e1b74f21SKevin Lo /* 869e1b74f21SKevin Lo * Report current media status. 870e1b74f21SKevin Lo */ 871e1b74f21SKevin Lo static void 872e1b74f21SKevin Lo ure_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 873e1b74f21SKevin Lo { 874e1b74f21SKevin Lo struct ure_softc *sc; 875e1b74f21SKevin Lo struct mii_data *mii; 876e1b74f21SKevin Lo 877e1b74f21SKevin Lo sc = ifp->if_softc; 878e1b74f21SKevin Lo mii = GET_MII(sc); 879e1b74f21SKevin Lo 880e1b74f21SKevin Lo URE_LOCK(sc); 881e1b74f21SKevin Lo mii_pollstat(mii); 882e1b74f21SKevin Lo ifmr->ifm_active = mii->mii_media_active; 883e1b74f21SKevin Lo ifmr->ifm_status = mii->mii_media_status; 884e1b74f21SKevin Lo URE_UNLOCK(sc); 885e1b74f21SKevin Lo } 886e1b74f21SKevin Lo 887e1b74f21SKevin Lo static int 888e1b74f21SKevin Lo ure_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 889e1b74f21SKevin Lo { 890e1b74f21SKevin Lo struct usb_ether *ue = ifp->if_softc; 891e1b74f21SKevin Lo struct ure_softc *sc; 892e1b74f21SKevin Lo struct ifreq *ifr; 893e1b74f21SKevin Lo int error, mask, reinit; 894e1b74f21SKevin Lo 895e1b74f21SKevin Lo sc = uether_getsc(ue); 896e1b74f21SKevin Lo ifr = (struct ifreq *)data; 897e1b74f21SKevin Lo error = 0; 898e1b74f21SKevin Lo reinit = 0; 899e1b74f21SKevin Lo if (cmd == SIOCSIFCAP) { 900e1b74f21SKevin Lo URE_LOCK(sc); 901e1b74f21SKevin Lo mask = ifr->ifr_reqcap ^ ifp->if_capenable; 902e1b74f21SKevin Lo if (reinit > 0 && ifp->if_drv_flags & IFF_DRV_RUNNING) 903e1b74f21SKevin Lo ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 904e1b74f21SKevin Lo else 905e1b74f21SKevin Lo reinit = 0; 906e1b74f21SKevin Lo URE_UNLOCK(sc); 907e1b74f21SKevin Lo if (reinit > 0) 908e1b74f21SKevin Lo uether_init(ue); 909e1b74f21SKevin Lo } else 910e1b74f21SKevin Lo error = uether_ioctl(ifp, cmd, data); 911e1b74f21SKevin Lo 912e1b74f21SKevin Lo return (error); 913e1b74f21SKevin Lo } 914e1b74f21SKevin Lo 915e1b74f21SKevin Lo static void 916e1b74f21SKevin Lo ure_rtl8152_init(struct ure_softc *sc) 917e1b74f21SKevin Lo { 918e1b74f21SKevin Lo uint32_t pwrctrl; 919e1b74f21SKevin Lo 920e1b74f21SKevin Lo /* Disable ALDPS. */ 921e1b74f21SKevin Lo ure_ocp_reg_write(sc, URE_OCP_ALDPS_CONFIG, URE_ENPDNPS | URE_LINKENA | 922e1b74f21SKevin Lo URE_DIS_SDSAVE); 923e1b74f21SKevin Lo uether_pause(&sc->sc_ue, hz / 50); 924e1b74f21SKevin Lo 925e1b74f21SKevin Lo if (sc->sc_chip & URE_CHIP_VER_4C00) { 926e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA, 927e1b74f21SKevin Lo ure_read_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA) & 928e1b74f21SKevin Lo ~URE_LED_MODE_MASK); 929e1b74f21SKevin Lo } 930e1b74f21SKevin Lo 931e1b74f21SKevin Lo ure_write_2(sc, URE_USB_UPS_CTRL, URE_MCU_TYPE_USB, 932e1b74f21SKevin Lo ure_read_2(sc, URE_USB_UPS_CTRL, URE_MCU_TYPE_USB) & 933e1b74f21SKevin Lo ~URE_POWER_CUT); 934e1b74f21SKevin Lo ure_write_2(sc, URE_USB_PM_CTRL_STATUS, URE_MCU_TYPE_USB, 935e1b74f21SKevin Lo ure_read_2(sc, URE_USB_PM_CTRL_STATUS, URE_MCU_TYPE_USB) & 936e1b74f21SKevin Lo ~URE_RESUME_INDICATE); 937e1b74f21SKevin Lo 938e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_PHY_PWR, URE_MCU_TYPE_PLA, 939e1b74f21SKevin Lo ure_read_2(sc, URE_PLA_PHY_PWR, URE_MCU_TYPE_PLA) | 940e1b74f21SKevin Lo URE_TX_10M_IDLE_EN | URE_PFM_PWM_SWITCH); 941e1b74f21SKevin Lo pwrctrl = ure_read_4(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA); 942e1b74f21SKevin Lo pwrctrl &= ~URE_MCU_CLK_RATIO_MASK; 943e1b74f21SKevin Lo pwrctrl |= URE_MCU_CLK_RATIO | URE_D3_CLK_GATED_EN; 944e1b74f21SKevin Lo ure_write_4(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA, pwrctrl); 945e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_GPHY_INTR_IMR, URE_MCU_TYPE_PLA, 946e1b74f21SKevin Lo URE_GPHY_STS_MSK | URE_SPEED_DOWN_MSK | URE_SPDWN_RXDV_MSK | 947e1b74f21SKevin Lo URE_SPDWN_LINKCHG_MSK); 948e1b74f21SKevin Lo 949e1b74f21SKevin Lo /* Disable Rx aggregation. */ 950e1b74f21SKevin Lo ure_write_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB, 951e1b74f21SKevin Lo ure_read_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB) | 952e1b74f21SKevin Lo URE_RX_AGG_DISABLE); 953e1b74f21SKevin Lo 954e1b74f21SKevin Lo /* Disable ALDPS. */ 955e1b74f21SKevin Lo ure_ocp_reg_write(sc, URE_OCP_ALDPS_CONFIG, URE_ENPDNPS | URE_LINKENA | 956e1b74f21SKevin Lo URE_DIS_SDSAVE); 957e1b74f21SKevin Lo uether_pause(&sc->sc_ue, hz / 50); 958e1b74f21SKevin Lo 959e1b74f21SKevin Lo ure_init_fifo(sc); 960e1b74f21SKevin Lo 961e1b74f21SKevin Lo ure_write_1(sc, URE_USB_TX_AGG, URE_MCU_TYPE_USB, 962e1b74f21SKevin Lo URE_TX_AGG_MAX_THRESHOLD); 963e1b74f21SKevin Lo ure_write_4(sc, URE_USB_RX_BUF_TH, URE_MCU_TYPE_USB, URE_RX_THR_HIGH); 964e1b74f21SKevin Lo ure_write_4(sc, URE_USB_TX_DMA, URE_MCU_TYPE_USB, 965e1b74f21SKevin Lo URE_TEST_MODE_DISABLE | URE_TX_SIZE_ADJUST1); 966e1b74f21SKevin Lo } 967e1b74f21SKevin Lo 968e1b74f21SKevin Lo static void 969a24d62b5SKevin Lo ure_rtl8153_init(struct ure_softc *sc) 970a24d62b5SKevin Lo { 971a24d62b5SKevin Lo uint16_t val; 972a24d62b5SKevin Lo uint8_t u1u2[8]; 973a24d62b5SKevin Lo int i; 974a24d62b5SKevin Lo 975a24d62b5SKevin Lo /* Disable ALDPS. */ 976a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, 977a24d62b5SKevin Lo ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) & ~URE_EN_ALDPS); 978a24d62b5SKevin Lo uether_pause(&sc->sc_ue, hz / 50); 979a24d62b5SKevin Lo 980a24d62b5SKevin Lo memset(u1u2, 0x00, sizeof(u1u2)); 981a24d62b5SKevin Lo ure_write_mem(sc, URE_USB_TOLERANCE, 982a24d62b5SKevin Lo URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); 983a24d62b5SKevin Lo 984a24d62b5SKevin Lo for (i = 0; i < URE_TIMEOUT; i++) { 985a24d62b5SKevin Lo if (ure_read_2(sc, URE_PLA_BOOT_CTRL, URE_MCU_TYPE_PLA) & 986a24d62b5SKevin Lo URE_AUTOLOAD_DONE) 987a24d62b5SKevin Lo break; 988a24d62b5SKevin Lo uether_pause(&sc->sc_ue, hz / 100); 989a24d62b5SKevin Lo } 990a24d62b5SKevin Lo if (i == URE_TIMEOUT) 991a24d62b5SKevin Lo device_printf(sc->sc_ue.ue_dev, 992a24d62b5SKevin Lo "timeout waiting for chip autoload\n"); 993a24d62b5SKevin Lo 994a24d62b5SKevin Lo for (i = 0; i < URE_TIMEOUT; i++) { 995a24d62b5SKevin Lo val = ure_ocp_reg_read(sc, URE_OCP_PHY_STATUS) & 996a24d62b5SKevin Lo URE_PHY_STAT_MASK; 997a24d62b5SKevin Lo if (val == URE_PHY_STAT_LAN_ON || val == URE_PHY_STAT_PWRDN) 998a24d62b5SKevin Lo break; 999a24d62b5SKevin Lo uether_pause(&sc->sc_ue, hz / 100); 1000a24d62b5SKevin Lo } 1001a24d62b5SKevin Lo if (i == URE_TIMEOUT) 1002a24d62b5SKevin Lo device_printf(sc->sc_ue.ue_dev, 1003a24d62b5SKevin Lo "timeout waiting for phy to stabilize\n"); 1004a24d62b5SKevin Lo 1005a24d62b5SKevin Lo ure_write_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, 1006a24d62b5SKevin Lo ure_read_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB) & 1007a24d62b5SKevin Lo ~URE_U2P3_ENABLE); 1008a24d62b5SKevin Lo 1009a24d62b5SKevin Lo if (sc->sc_chip & URE_CHIP_VER_5C10) { 1010a24d62b5SKevin Lo val = ure_read_2(sc, URE_USB_SSPHYLINK2, URE_MCU_TYPE_USB); 1011a24d62b5SKevin Lo val &= ~URE_PWD_DN_SCALE_MASK; 1012a24d62b5SKevin Lo val |= URE_PWD_DN_SCALE(96); 1013a24d62b5SKevin Lo ure_write_2(sc, URE_USB_SSPHYLINK2, URE_MCU_TYPE_USB, val); 1014a24d62b5SKevin Lo 1015a24d62b5SKevin Lo ure_write_1(sc, URE_USB_USB2PHY, URE_MCU_TYPE_USB, 1016a24d62b5SKevin Lo ure_read_1(sc, URE_USB_USB2PHY, URE_MCU_TYPE_USB) | 1017a24d62b5SKevin Lo URE_USB2PHY_L1 | URE_USB2PHY_SUSPEND); 1018a24d62b5SKevin Lo } else if (sc->sc_chip & URE_CHIP_VER_5C20) { 1019a24d62b5SKevin Lo ure_write_1(sc, URE_PLA_DMY_REG0, URE_MCU_TYPE_PLA, 1020a24d62b5SKevin Lo ure_read_1(sc, URE_PLA_DMY_REG0, URE_MCU_TYPE_PLA) & 1021a24d62b5SKevin Lo ~URE_ECM_ALDPS); 1022a24d62b5SKevin Lo } 1023a24d62b5SKevin Lo if (sc->sc_chip & (URE_CHIP_VER_5C20 | URE_CHIP_VER_5C30)) { 1024a24d62b5SKevin Lo val = ure_read_1(sc, URE_USB_CSR_DUMMY1, URE_MCU_TYPE_USB); 1025a24d62b5SKevin Lo if (ure_read_2(sc, URE_USB_BURST_SIZE, URE_MCU_TYPE_USB) == 1026a24d62b5SKevin Lo 0) 1027a24d62b5SKevin Lo val &= ~URE_DYNAMIC_BURST; 1028a24d62b5SKevin Lo else 1029a24d62b5SKevin Lo val |= URE_DYNAMIC_BURST; 1030a24d62b5SKevin Lo ure_write_1(sc, URE_USB_CSR_DUMMY1, URE_MCU_TYPE_USB, val); 1031a24d62b5SKevin Lo } 1032a24d62b5SKevin Lo 1033a24d62b5SKevin Lo ure_write_1(sc, URE_USB_CSR_DUMMY2, URE_MCU_TYPE_USB, 1034a24d62b5SKevin Lo ure_read_1(sc, URE_USB_CSR_DUMMY2, URE_MCU_TYPE_USB) | 1035a24d62b5SKevin Lo URE_EP4_FULL_FC); 1036a24d62b5SKevin Lo 1037a24d62b5SKevin Lo ure_write_2(sc, URE_USB_WDT11_CTRL, URE_MCU_TYPE_USB, 1038a24d62b5SKevin Lo ure_read_2(sc, URE_USB_WDT11_CTRL, URE_MCU_TYPE_USB) & 1039a24d62b5SKevin Lo ~URE_TIMER11_EN); 1040a24d62b5SKevin Lo 1041a24d62b5SKevin Lo ure_write_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA, 1042a24d62b5SKevin Lo ure_read_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA) & 1043a24d62b5SKevin Lo ~URE_LED_MODE_MASK); 1044a24d62b5SKevin Lo 1045a24d62b5SKevin Lo if ((sc->sc_chip & URE_CHIP_VER_5C10) && 1046a24d62b5SKevin Lo usbd_get_speed(sc->sc_ue.ue_udev) != USB_SPEED_SUPER) 1047a24d62b5SKevin Lo val = URE_LPM_TIMER_500MS; 1048a24d62b5SKevin Lo else 1049a24d62b5SKevin Lo val = URE_LPM_TIMER_500US; 1050a24d62b5SKevin Lo ure_write_1(sc, URE_USB_LPM_CTRL, URE_MCU_TYPE_USB, 1051a24d62b5SKevin Lo val | URE_FIFO_EMPTY_1FB | URE_ROK_EXIT_LPM); 1052a24d62b5SKevin Lo 1053a24d62b5SKevin Lo val = ure_read_2(sc, URE_USB_AFE_CTRL2, URE_MCU_TYPE_USB); 1054a24d62b5SKevin Lo val &= ~URE_SEN_VAL_MASK; 1055a24d62b5SKevin Lo val |= URE_SEN_VAL_NORMAL | URE_SEL_RXIDLE; 1056a24d62b5SKevin Lo ure_write_2(sc, URE_USB_AFE_CTRL2, URE_MCU_TYPE_USB, val); 1057a24d62b5SKevin Lo 1058a24d62b5SKevin Lo ure_write_2(sc, URE_USB_CONNECT_TIMER, URE_MCU_TYPE_USB, 0x0001); 1059a24d62b5SKevin Lo 1060a24d62b5SKevin Lo ure_write_2(sc, URE_USB_POWER_CUT, URE_MCU_TYPE_USB, 1061a24d62b5SKevin Lo ure_read_2(sc, URE_USB_POWER_CUT, URE_MCU_TYPE_USB) & 1062a24d62b5SKevin Lo ~(URE_PWR_EN | URE_PHASE2_EN)); 1063a24d62b5SKevin Lo ure_write_2(sc, URE_USB_MISC_0, URE_MCU_TYPE_USB, 1064a24d62b5SKevin Lo ure_read_2(sc, URE_USB_MISC_0, URE_MCU_TYPE_USB) & 1065a24d62b5SKevin Lo ~URE_PCUT_STATUS); 1066a24d62b5SKevin Lo 1067a24d62b5SKevin Lo memset(u1u2, 0xff, sizeof(u1u2)); 1068a24d62b5SKevin Lo ure_write_mem(sc, URE_USB_TOLERANCE, 1069a24d62b5SKevin Lo URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); 1070a24d62b5SKevin Lo 1071a24d62b5SKevin Lo ure_write_2(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA, 1072a24d62b5SKevin Lo URE_ALDPS_SPDWN_RATIO); 1073a24d62b5SKevin Lo ure_write_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA, 1074a24d62b5SKevin Lo URE_EEE_SPDWN_RATIO); 1075a24d62b5SKevin Lo ure_write_2(sc, URE_PLA_MAC_PWR_CTRL3, URE_MCU_TYPE_PLA, 1076a24d62b5SKevin Lo URE_PKT_AVAIL_SPDWN_EN | URE_SUSPEND_SPDWN_EN | 1077a24d62b5SKevin Lo URE_U1U2_SPDWN_EN | URE_L1_SPDWN_EN); 1078a24d62b5SKevin Lo ure_write_2(sc, URE_PLA_MAC_PWR_CTRL4, URE_MCU_TYPE_PLA, 1079a24d62b5SKevin Lo URE_PWRSAVE_SPDWN_EN | URE_RXDV_SPDWN_EN | URE_TX10MIDLE_EN | 1080a24d62b5SKevin Lo URE_TP100_SPDWN_EN | URE_TP500_SPDWN_EN | URE_TP1000_SPDWN_EN | 1081a24d62b5SKevin Lo URE_EEE_SPDWN_EN); 1082a24d62b5SKevin Lo 1083a24d62b5SKevin Lo val = ure_read_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB); 1084a24d62b5SKevin Lo if (!(sc->sc_chip & (URE_CHIP_VER_5C00 | URE_CHIP_VER_5C10))) 1085a24d62b5SKevin Lo val |= URE_U2P3_ENABLE; 1086a24d62b5SKevin Lo else 1087a24d62b5SKevin Lo val &= ~URE_U2P3_ENABLE; 1088a24d62b5SKevin Lo ure_write_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, val); 1089a24d62b5SKevin Lo 1090a24d62b5SKevin Lo memset(u1u2, 0x00, sizeof(u1u2)); 1091a24d62b5SKevin Lo ure_write_mem(sc, URE_USB_TOLERANCE, 1092a24d62b5SKevin Lo URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); 1093a24d62b5SKevin Lo 1094a24d62b5SKevin Lo /* Disable ALDPS. */ 1095a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, 1096a24d62b5SKevin Lo ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) & ~URE_EN_ALDPS); 1097a24d62b5SKevin Lo uether_pause(&sc->sc_ue, hz / 50); 1098a24d62b5SKevin Lo 1099a24d62b5SKevin Lo ure_init_fifo(sc); 1100a24d62b5SKevin Lo 1101a24d62b5SKevin Lo /* Disable Rx aggregation. */ 1102a24d62b5SKevin Lo ure_write_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB, 1103a24d62b5SKevin Lo ure_read_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB) | 1104a24d62b5SKevin Lo URE_RX_AGG_DISABLE); 1105a24d62b5SKevin Lo 1106a24d62b5SKevin Lo val = ure_read_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB); 1107a24d62b5SKevin Lo if (!(sc->sc_chip & (URE_CHIP_VER_5C00 | URE_CHIP_VER_5C10))) 1108a24d62b5SKevin Lo val |= URE_U2P3_ENABLE; 1109a24d62b5SKevin Lo else 1110a24d62b5SKevin Lo val &= ~URE_U2P3_ENABLE; 1111a24d62b5SKevin Lo ure_write_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, val); 1112a24d62b5SKevin Lo 1113a24d62b5SKevin Lo memset(u1u2, 0xff, sizeof(u1u2)); 1114a24d62b5SKevin Lo ure_write_mem(sc, URE_USB_TOLERANCE, 1115a24d62b5SKevin Lo URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); 1116a24d62b5SKevin Lo } 1117a24d62b5SKevin Lo 1118a24d62b5SKevin Lo static void 1119e1b74f21SKevin Lo ure_stop(struct usb_ether *ue) 1120e1b74f21SKevin Lo { 1121e1b74f21SKevin Lo struct ure_softc *sc = uether_getsc(ue); 1122e1b74f21SKevin Lo struct ifnet *ifp = uether_getifp(ue); 1123e1b74f21SKevin Lo 1124e1b74f21SKevin Lo URE_LOCK_ASSERT(sc, MA_OWNED); 1125e1b74f21SKevin Lo 1126e1b74f21SKevin Lo ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1127e1b74f21SKevin Lo sc->sc_flags &= ~URE_FLAG_LINK; 1128e1b74f21SKevin Lo 1129e1b74f21SKevin Lo /* 1130e1b74f21SKevin Lo * stop all the transfers, if not already stopped: 1131e1b74f21SKevin Lo */ 1132e1b74f21SKevin Lo usbd_transfer_stop(sc->sc_xfer[URE_BULK_DT_WR]); 1133e1b74f21SKevin Lo usbd_transfer_stop(sc->sc_xfer[URE_BULK_DT_RD]); 1134e1b74f21SKevin Lo } 1135e1b74f21SKevin Lo 1136e1b74f21SKevin Lo static void 1137e1b74f21SKevin Lo ure_disable_teredo(struct ure_softc *sc) 1138e1b74f21SKevin Lo { 1139e1b74f21SKevin Lo 1140e1b74f21SKevin Lo ure_write_4(sc, URE_PLA_TEREDO_CFG, URE_MCU_TYPE_PLA, 1141e1b74f21SKevin Lo ure_read_4(sc, URE_PLA_TEREDO_CFG, URE_MCU_TYPE_PLA) & 1142e1b74f21SKevin Lo ~(URE_TEREDO_SEL | URE_TEREDO_RS_EVENT_MASK | URE_OOB_TEREDO_EN)); 1143e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_WDT6_CTRL, URE_MCU_TYPE_PLA, 1144e1b74f21SKevin Lo URE_WDT6_SET_MODE); 1145e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_REALWOW_TIMER, URE_MCU_TYPE_PLA, 0); 1146e1b74f21SKevin Lo ure_write_4(sc, URE_PLA_TEREDO_TIMER, URE_MCU_TYPE_PLA, 0); 1147e1b74f21SKevin Lo } 1148e1b74f21SKevin Lo 1149e1b74f21SKevin Lo static void 1150e1b74f21SKevin Lo ure_init_fifo(struct ure_softc *sc) 1151e1b74f21SKevin Lo { 1152e1b74f21SKevin Lo uint32_t rx_fifo1, rx_fifo2; 1153e1b74f21SKevin Lo int i; 1154e1b74f21SKevin Lo 1155e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA, 1156e1b74f21SKevin Lo ure_read_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA) | 1157e1b74f21SKevin Lo URE_RXDY_GATED_EN); 1158e1b74f21SKevin Lo 1159e1b74f21SKevin Lo ure_disable_teredo(sc); 1160e1b74f21SKevin Lo 1161e1b74f21SKevin Lo ure_write_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, 1162e1b74f21SKevin Lo ure_read_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA) & 1163e1b74f21SKevin Lo ~URE_RCR_ACPT_ALL); 1164e1b74f21SKevin Lo 1165a24d62b5SKevin Lo if (!(sc->sc_flags & URE_FLAG_8152)) { 1166a24d62b5SKevin Lo if (sc->sc_chip & (URE_CHIP_VER_5C00 | URE_CHIP_VER_5C10 | 1167a24d62b5SKevin Lo URE_CHIP_VER_5C20)) { 1168a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_ADC_CFG, 1169a24d62b5SKevin Lo URE_CKADSEL_L | URE_ADC_EN | URE_EN_EMI_L); 1170a24d62b5SKevin Lo } 1171a24d62b5SKevin Lo if (sc->sc_chip & URE_CHIP_VER_5C00) { 1172a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_EEE_CFG, 1173a24d62b5SKevin Lo ure_ocp_reg_read(sc, URE_OCP_EEE_CFG) & 1174a24d62b5SKevin Lo ~URE_CTAP_SHORT_EN); 1175a24d62b5SKevin Lo } 1176a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, 1177a24d62b5SKevin Lo ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) | 1178a24d62b5SKevin Lo URE_EEE_CLKDIV_EN); 1179a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_DOWN_SPEED, 1180a24d62b5SKevin Lo ure_ocp_reg_read(sc, URE_OCP_DOWN_SPEED) | 1181a24d62b5SKevin Lo URE_EN_10M_BGOFF); 1182a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, 1183a24d62b5SKevin Lo ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) | 1184a24d62b5SKevin Lo URE_EN_10M_PLLOFF); 1185a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_IMPEDANCE); 1186a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0x0b13); 1187a24d62b5SKevin Lo ure_write_2(sc, URE_PLA_PHY_PWR, URE_MCU_TYPE_PLA, 1188a24d62b5SKevin Lo ure_read_2(sc, URE_PLA_PHY_PWR, URE_MCU_TYPE_PLA) | 1189a24d62b5SKevin Lo URE_PFM_PWM_SWITCH); 1190a24d62b5SKevin Lo 1191a24d62b5SKevin Lo /* Enable LPF corner auto tune. */ 1192a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_LPF_CFG); 1193a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0xf70f); 1194a24d62b5SKevin Lo 1195a24d62b5SKevin Lo /* Adjust 10M amplitude. */ 1196a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_10M_AMP1); 1197a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0x00af); 1198a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_10M_AMP2); 1199a24d62b5SKevin Lo ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0x0208); 1200a24d62b5SKevin Lo } 1201a24d62b5SKevin Lo 1202e1b74f21SKevin Lo ure_reset(sc); 1203e1b74f21SKevin Lo 1204e1b74f21SKevin Lo ure_write_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, 0); 1205e1b74f21SKevin Lo 1206e1b74f21SKevin Lo ure_write_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA, 1207e1b74f21SKevin Lo ure_read_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) & 1208e1b74f21SKevin Lo ~URE_NOW_IS_OOB); 1209e1b74f21SKevin Lo 1210e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA, 1211e1b74f21SKevin Lo ure_read_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA) & 1212e1b74f21SKevin Lo ~URE_MCU_BORW_EN); 1213e1b74f21SKevin Lo for (i = 0; i < URE_TIMEOUT; i++) { 1214e1b74f21SKevin Lo if (ure_read_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) & 1215e1b74f21SKevin Lo URE_LINK_LIST_READY) 1216e1b74f21SKevin Lo break; 1217e1b74f21SKevin Lo uether_pause(&sc->sc_ue, hz / 100); 1218e1b74f21SKevin Lo } 1219e1b74f21SKevin Lo if (i == URE_TIMEOUT) 1220e1b74f21SKevin Lo device_printf(sc->sc_ue.ue_dev, 1221e1b74f21SKevin Lo "timeout waiting for OOB control\n"); 1222e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA, 1223e1b74f21SKevin Lo ure_read_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA) | 1224e1b74f21SKevin Lo URE_RE_INIT_LL); 1225e1b74f21SKevin Lo for (i = 0; i < URE_TIMEOUT; i++) { 1226e1b74f21SKevin Lo if (ure_read_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) & 1227e1b74f21SKevin Lo URE_LINK_LIST_READY) 1228e1b74f21SKevin Lo break; 1229e1b74f21SKevin Lo uether_pause(&sc->sc_ue, hz / 100); 1230e1b74f21SKevin Lo } 1231e1b74f21SKevin Lo if (i == URE_TIMEOUT) 1232e1b74f21SKevin Lo device_printf(sc->sc_ue.ue_dev, 1233e1b74f21SKevin Lo "timeout waiting for OOB control\n"); 1234e1b74f21SKevin Lo 1235e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_CPCR, URE_MCU_TYPE_PLA, 1236e1b74f21SKevin Lo ure_read_2(sc, URE_PLA_CPCR, URE_MCU_TYPE_PLA) & 1237e1b74f21SKevin Lo ~URE_CPCR_RX_VLAN); 1238e1b74f21SKevin Lo ure_write_2(sc, URE_PLA_TCR0, URE_MCU_TYPE_PLA, 1239e1b74f21SKevin Lo ure_read_2(sc, URE_PLA_TCR0, URE_MCU_TYPE_PLA) | 1240e1b74f21SKevin Lo URE_TCR0_AUTO_FIFO); 1241e1b74f21SKevin Lo 1242e1b74f21SKevin Lo /* Configure Rx FIFO threshold. */ 1243e1b74f21SKevin Lo ure_write_4(sc, URE_PLA_RXFIFO_CTRL0, URE_MCU_TYPE_PLA, 1244e1b74f21SKevin Lo URE_RXFIFO_THR1_NORMAL); 1245e1b74f21SKevin Lo if (usbd_get_speed(sc->sc_ue.ue_udev) == USB_SPEED_FULL) { 1246e1b74f21SKevin Lo rx_fifo1 = URE_RXFIFO_THR2_FULL; 1247e1b74f21SKevin Lo rx_fifo2 = URE_RXFIFO_THR3_FULL; 1248e1b74f21SKevin Lo } else { 1249e1b74f21SKevin Lo rx_fifo1 = URE_RXFIFO_THR2_HIGH; 1250e1b74f21SKevin Lo rx_fifo2 = URE_RXFIFO_THR3_HIGH; 1251e1b74f21SKevin Lo } 1252e1b74f21SKevin Lo ure_write_4(sc, URE_PLA_RXFIFO_CTRL1, URE_MCU_TYPE_PLA, rx_fifo1); 1253e1b74f21SKevin Lo ure_write_4(sc, URE_PLA_RXFIFO_CTRL2, URE_MCU_TYPE_PLA, rx_fifo2); 1254e1b74f21SKevin Lo 1255e1b74f21SKevin Lo /* Configure Tx FIFO threshold. */ 1256e1b74f21SKevin Lo ure_write_4(sc, URE_PLA_TXFIFO_CTRL, URE_MCU_TYPE_PLA, 1257e1b74f21SKevin Lo URE_TXFIFO_THR_NORMAL); 1258e1b74f21SKevin Lo } 1259