From f314c4b5f4eb9579952f6445b7dac19e7cfe70cd Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Thu, 22 Oct 2026 05:36:56 +0200 Subject: [PATCH] WIP ure(4) from FreeBSD. --- etc/devd/usb.conf | 50 +- share/man/man4/Makefile | 2 + share/man/man4/miibus.4 | 3 + share/man/man4/ure.4 | 127 ++++ share/man/man4/usb.4 | 3 + sys/bus/u4b/net/Makefile | 2 +- sys/bus/u4b/net/if_ure.c | 1274 ++++++++++++++++++++++++++++++++++ sys/bus/u4b/net/if_urereg.h | 440 ++++++++++++ sys/bus/u4b/net/ure/Makefile | 10 + sys/bus/u4b/usbdevs | 3 + sys/conf/files | 1 + sys/config/LINT64 | 3 + 12 files changed, 1916 insertions(+), 2 deletions(-) create mode 100644 share/man/man4/ure.4 create mode 100644 sys/bus/u4b/net/if_ure.c create mode 100644 sys/bus/u4b/net/if_urereg.h create mode 100644 sys/bus/u4b/net/ure/Makefile diff --git a/etc/devd/usb.conf b/etc/devd/usb.conf index 15a0efc6d12..f7591fc078a 100644 --- a/etc/devd/usb.conf +++ b/etc/devd/usb.conf @@ -1563,6 +1563,14 @@ nomatch 32 { action "kldload -n if_aue"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0955"; + match "product" "0x09ff"; + action "kldload -n if_ure"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -1751,7 +1759,23 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x0bda"; - match "product" "(0x0179|0x018a|0x317f|0x8170|0x8176|0x8177|0x8178|0x8179|0x817a|0x817b|0x817c|0x817d|0x817e|0x817f|0x818a|0x8191|0x8754)"; + match "product" "(0x0179|0x018a|0x317f)"; + action "kldload -n if_urtwn"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bda"; + match "product" "(0x8152|0x8153)"; + action "kldload -n if_ure"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0bda"; + match "product" "(0x8170|0x8176|0x8177|0x8178|0x8179|0x817a|0x817b|0x817c|0x817d|0x817e|0x817f|0x818a|0x8191|0x8754)"; action "kldload -n if_urtwn"; }; @@ -2851,6 +2875,14 @@ nomatch 32 { action "kldload -n if_run"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x17ef"; + match "product" "(0x3062|0x3069)"; + action "kldload -n if_ure"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -2859,6 +2891,14 @@ nomatch 32 { action "kldload -n if_axe"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x17ef"; + match "product" "0x7205"; + action "kldload -n if_ure"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -3219,6 +3259,14 @@ nomatch 32 { action "kldload -n if_cdce"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2357"; + match "product" "0x0601"; + action "kldload -n if_ure"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 9ad000431e5..a82c464912a 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -365,6 +365,7 @@ MAN= aac.4 \ unix.4 \ uplcom.4 \ upmap.4 \ + ure.4 \ urio.4 \ urndis.4 \ urtwn.4 \ @@ -549,6 +550,7 @@ MLINKS+=tx.4 if_tx.4 MLINKS+=txp.4 if_txp.4 MLINKS+=udav.4 if_udav.4 MLINKS+=upmap.4 kpmap.4 +MLINKS+=ure.4 if_ure.4 MLINKS+=urndis.4 if_urndis.4 MLINKS+=urtwn.4 if_urtwn.4 MLINKS+=vga_switcheroo.4 apple_gmux.4 diff --git a/share/man/man4/miibus.4 b/share/man/man4/miibus.4 index 5ca2f87b5cd..cc51f546a62 100644 --- a/share/man/man4/miibus.4 +++ b/share/man/man4/miibus.4 @@ -107,6 +107,8 @@ Texas Instruments ThunderLAN SMC EtherPower II (83c170) .It Xr udav 4 Davicom DM9601 USB Ethernet +.It Xr ure 4 +RealTek RTL8152/RTL8153 USB to Ethernet driver .It Xr vge 4 VIA Networking Technologies VT6122 PCI Gigabit Ethernet .It Xr vr 4 @@ -158,6 +160,7 @@ but as a result are not well behaved newbus device drivers. .Xr tl 4 , .Xr tx 4 , .Xr udav 4 , +.Xr ure 4 , .Xr vge 4 , .Xr vr 4 , .Xr wb 4 , diff --git a/share/man/man4/ure.4 b/share/man/man4/ure.4 new file mode 100644 index 00000000000..b902cc2de6f --- /dev/null +++ b/share/man/man4/ure.4 @@ -0,0 +1,127 @@ +.\" +.\" Copyright (c) 2015-2016 Kevin Lo +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: head/share/man/man4/ure.4 308121 2016-10-31 05:58:11Z kevlo $ +.\" +.Dd October 31, 2016 +.Dt URE 4 +.Os +.Sh NAME +.Nm ure +.Nd "RealTek RTL8152/RTL8153 USB to Ethernet controller driver" +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device uhci" +.Cd "device ohci" +.Cd "device usb" +.Cd "device miibus" +.Cd "device uether" +.Cd "device ure" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +if_ure_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides support for USB Ethernet adapters based on the RealTek +RTL8152 and RTL8153 USB Ethernet controllers. +.Pp +NICs based on the RTL8152 are capable of 10 and 100Mbps speeds. +NICs based on the RTL8153 are capable of 10, 100 and 1000Mbps operation. +.Pp +The +.Nm +driver supports the following media types: +.Bl -tag -width ".Cm 10baseT/UTP" +.It Cm autoselect +Enable auto selection of the media type and options. +The user can manually override +the auto selected mode by adding media options to the +.Pa /etc/rc.conf +file. +.It Cm 10baseT/UTP +Set 10Mbps operation. +The +.Cm mediaopt +option can also be used to select either +.Cm full-duplex +or +.Cm half-duplex +modes. +.It Cm 100baseTX +Set 100Mbps (Fast Ethernet) operation. +The +.Cm mediaopt +option can also be used to select either +.Cm full-duplex +or +.Cm half-duplex +modes. +.It Cm 1000baseTX +Set 1000baseTX operation over twisted pair. +The RealTek gigE chips support 1000Mbps in +.Cm full-duplex +mode only. +.El +.Pp +The +.Nm +driver supports the following media options: +.Bl -tag -width ".Cm full-duplex" +.It Cm full-duplex +Force full duplex operation. +.It Cm half-duplex +Force half duplex operation. +.El +.Pp +For more information on configuring this device, see +.Xr ifconfig 8 . +.Sh DIAGNOSTICS +.Bl -diag +.It "ure%d: watchdog timeout" +A packet was queued for transmission and a transmit command was +issued, however the device failed to acknowledge the transmission +before a timeout expired. +.El +.Sh SEE ALSO +.Xr arp 4 , +.Xr ifmedia 4 , +.Xr miibus 4 , +.Xr netintro 4 , +.Xr ng_ether 4 , +.Xr ifconfig 8 +.Sh AUTHORS +The +.Nm +driver was written by +.An Kevin Lo Aq Mt kevlo@FreeBSD.org . diff --git a/share/man/man4/usb.4 b/share/man/man4/usb.4 index fc5f5e9b6a9..9d0158de50a 100644 --- a/share/man/man4/usb.4 +++ b/share/man/man4/usb.4 @@ -114,6 +114,8 @@ Kawasaki LSI KL5KUSB101B Ethernet driver Moschip MCS7730/MCS7830/MCS7832 USB Ethernet driver .It Xr udav 4 Davicom DM9601 USB Ethernet driver +.It Xr ure 4 +RealTek RTL8152/RTL8153 USB to Ethernet driver .El .Ss Wireless network interfaces .Bl -tag -width ".Xr umoscom 4" -offset indent -compact @@ -302,6 +304,7 @@ specifications can be found at: .Xr umoscom 4 , .Xr ums 4 , .Xr uplcom 4 , +.Xr ure 4 , .Xr urio 4 , .Xr urndis 4 , .Xr urtwn 4 , diff --git a/sys/bus/u4b/net/Makefile b/sys/bus/u4b/net/Makefile index 8c1d2635bc2..c23d08b0d38 100644 --- a/sys/bus/u4b/net/Makefile +++ b/sys/bus/u4b/net/Makefile @@ -1,6 +1,6 @@ # # XXX MISSING: smsc -SUBDIR= aue axe axge cdce cue ipheth kue mos udav uether urndis +SUBDIR= aue axe axge cdce cue ipheth kue mos udav uether ure urndis .include diff --git a/sys/bus/u4b/net/if_ure.c b/sys/bus/u4b/net/if_ure.c new file mode 100644 index 00000000000..a916a29b21d --- /dev/null +++ b/sys/bus/u4b/net/if_ure.c @@ -0,0 +1,1274 @@ +/*- + * Copyright (c) 2015-2016 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/dev/usb/net/if_ure.c 346052 2019-04-09 13:54:08Z ganbold $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include "usbdevs.h" + +#define USB_DEBUG_VAR ure_debug +#include +#include + +#include +#include + +#ifdef USB_DEBUG +static int ure_debug = 0; + +static SYSCTL_NODE(_hw_usb, OID_AUTO, ure, CTLFLAG_RW, 0, "USB ure"); +SYSCTL_INT(_hw_usb_ure, OID_AUTO, debug, CTLFLAG_RW, &ure_debug, 0, + "Debug level"); +#endif + +#define ETHER_IS_ZERO(addr) \ + (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5])) + +/* + * Various supported device vendors/products. + */ +static const STRUCT_USB_HOST_ID ure_devs[] = { +#define URE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) } + URE_DEV(LENOVO, RTL8153, 0), + URE_DEV(LENOVO, TBT3LAN, 0), + URE_DEV(LENOVO, ONELINK, 0), + URE_DEV(LENOVO, USBCLAN, 0), + URE_DEV(NVIDIA, RTL8153, 0), + URE_DEV(REALTEK, RTL8152, URE_FLAG_8152), + URE_DEV(REALTEK, RTL8153, 0), + URE_DEV(TPLINK, RTL8153, 0), +#undef URE_DEV +}; + +static device_probe_t ure_probe; +static device_attach_t ure_attach; +static device_detach_t ure_detach; + +static usb_callback_t ure_bulk_read_callback; +static usb_callback_t ure_bulk_write_callback; + +static miibus_readreg_t ure_miibus_readreg; +static miibus_writereg_t ure_miibus_writereg; +static miibus_statchg_t ure_miibus_statchg; + +static uether_fn_t ure_attach_post; +static uether_fn_t ure_init; +static uether_fn_t ure_stop; +static uether_fn_t ure_start; +static uether_fn_t ure_tick; +static uether_fn_t ure_rxfilter; + +static int ure_ctl(struct ure_softc *, uint8_t, uint16_t, uint16_t, + void *, int); +static int ure_read_mem(struct ure_softc *, uint16_t, uint16_t, void *, + int); +static int ure_write_mem(struct ure_softc *, uint16_t, uint16_t, void *, + int); +static uint8_t ure_read_1(struct ure_softc *, uint16_t, uint16_t); +static uint16_t ure_read_2(struct ure_softc *, uint16_t, uint16_t); +static uint32_t ure_read_4(struct ure_softc *, uint16_t, uint16_t); +static int ure_write_1(struct ure_softc *, uint16_t, uint16_t, uint32_t); +static int ure_write_2(struct ure_softc *, uint16_t, uint16_t, uint32_t); +static int ure_write_4(struct ure_softc *, uint16_t, uint16_t, uint32_t); +static uint16_t ure_ocp_reg_read(struct ure_softc *, uint16_t); +static void ure_ocp_reg_write(struct ure_softc *, uint16_t, uint16_t); + +static void ure_read_chipver(struct ure_softc *); +static int ure_attach_post_sub(struct usb_ether *); +static void ure_reset(struct ure_softc *); +static int ure_ifmedia_upd(struct ifnet *); +static void ure_ifmedia_sts(struct ifnet *, struct ifmediareq *); +static int ure_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); +static void ure_rtl8152_init(struct ure_softc *); +static void ure_rtl8153_init(struct ure_softc *); +static void ure_disable_teredo(struct ure_softc *); +static void ure_init_fifo(struct ure_softc *); + +static const struct usb_config ure_config[URE_N_TRANSFER] = { + [URE_BULK_DT_WR] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .bufsize = MCLBYTES, + .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, + .callback = ure_bulk_write_callback, + .timeout = 10000, /* 10 seconds */ + }, + [URE_BULK_DT_RD] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_IN, + .bufsize = 16384, + .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, + .callback = ure_bulk_read_callback, + .timeout = 0, /* no timeout */ + }, +}; + +static device_method_t ure_methods[] = { + /* Device interface. */ + DEVMETHOD(device_probe, ure_probe), + DEVMETHOD(device_attach, ure_attach), + DEVMETHOD(device_detach, ure_detach), + + /* MII interface. */ + DEVMETHOD(miibus_readreg, ure_miibus_readreg), + DEVMETHOD(miibus_writereg, ure_miibus_writereg), + DEVMETHOD(miibus_statchg, ure_miibus_statchg), + + DEVMETHOD_END +}; + +static driver_t ure_driver = { + .name = "ure", + .methods = ure_methods, + .size = sizeof(struct ure_softc), +}; + +static devclass_t ure_devclass; + +DRIVER_MODULE(ure, uhub, ure_driver, ure_devclass, NULL, NULL); +DRIVER_MODULE(miibus, ure, miibus_driver, miibus_devclass, NULL, NULL); +MODULE_DEPEND(ure, uether, 1, 1, 1); +MODULE_DEPEND(ure, usb, 1, 1, 1); +MODULE_DEPEND(ure, ether, 1, 1, 1); +MODULE_DEPEND(ure, miibus, 1, 1, 1); +MODULE_VERSION(ure, 1); +//USB_PNP_HOST_INFO(ure_devs); + +static const struct usb_ether_methods ure_ue_methods = { + .ue_attach_post = ure_attach_post, + .ue_attach_post_sub = ure_attach_post_sub, + .ue_start = ure_start, + .ue_init = ure_init, + .ue_stop = ure_stop, + .ue_tick = ure_tick, + .ue_setmulti = ure_rxfilter, + .ue_setpromisc = ure_rxfilter, + .ue_mii_upd = ure_ifmedia_upd, + .ue_mii_sts = ure_ifmedia_sts, +}; + +static int +ure_ctl(struct ure_softc *sc, uint8_t rw, uint16_t val, uint16_t index, + void *buf, int len) +{ + struct usb_device_request req; + + URE_LOCK_ASSERT(sc, MA_OWNED); + + if (rw == URE_CTL_WRITE) + req.bmRequestType = UT_WRITE_VENDOR_DEVICE; + else + req.bmRequestType = UT_READ_VENDOR_DEVICE; + req.bRequest = UR_SET_ADDRESS; + USETW(req.wValue, val); + USETW(req.wIndex, index); + USETW(req.wLength, len); + + return (uether_do_request(&sc->sc_ue, &req, buf, 1000)); +} + +static int +ure_read_mem(struct ure_softc *sc, uint16_t addr, uint16_t index, + void *buf, int len) +{ + + return (ure_ctl(sc, URE_CTL_READ, addr, index, buf, len)); +} + +static int +ure_write_mem(struct ure_softc *sc, uint16_t addr, uint16_t index, + void *buf, int len) +{ + + return (ure_ctl(sc, URE_CTL_WRITE, addr, index, buf, len)); +} + +static uint8_t +ure_read_1(struct ure_softc *sc, uint16_t reg, uint16_t index) +{ + uint32_t val; + uint8_t temp[4]; + uint8_t shift; + + shift = (reg & 3) << 3; + reg &= ~3; + + ure_read_mem(sc, reg, index, &temp, 4); + val = UGETDW(temp); + val >>= shift; + + return (val & 0xff); +} + +static uint16_t +ure_read_2(struct ure_softc *sc, uint16_t reg, uint16_t index) +{ + uint32_t val; + uint8_t temp[4]; + uint8_t shift; + + shift = (reg & 2) << 3; + reg &= ~3; + + ure_read_mem(sc, reg, index, &temp, 4); + val = UGETDW(temp); + val >>= shift; + + return (val & 0xffff); +} + +static uint32_t +ure_read_4(struct ure_softc *sc, uint16_t reg, uint16_t index) +{ + uint8_t temp[4]; + + ure_read_mem(sc, reg, index, &temp, 4); + return (UGETDW(temp)); +} + +static int +ure_write_1(struct ure_softc *sc, uint16_t reg, uint16_t index, uint32_t val) +{ + uint16_t byen; + uint8_t temp[4]; + uint8_t shift; + + byen = URE_BYTE_EN_BYTE; + shift = reg & 3; + val &= 0xff; + + if (reg & 3) { + byen <<= shift; + val <<= (shift << 3); + reg &= ~3; + } + + USETDW(temp, val); + return (ure_write_mem(sc, reg, index | byen, &temp, 4)); +} + +static int +ure_write_2(struct ure_softc *sc, uint16_t reg, uint16_t index, uint32_t val) +{ + uint16_t byen; + uint8_t temp[4]; + uint8_t shift; + + byen = URE_BYTE_EN_WORD; + shift = reg & 2; + val &= 0xffff; + + if (reg & 2) { + byen <<= shift; + val <<= (shift << 3); + reg &= ~3; + } + + USETDW(temp, val); + return (ure_write_mem(sc, reg, index | byen, &temp, 4)); +} + +static int +ure_write_4(struct ure_softc *sc, uint16_t reg, uint16_t index, uint32_t val) +{ + uint8_t temp[4]; + + USETDW(temp, val); + return (ure_write_mem(sc, reg, index | URE_BYTE_EN_DWORD, &temp, 4)); +} + +static uint16_t +ure_ocp_reg_read(struct ure_softc *sc, uint16_t addr) +{ + uint16_t reg; + + ure_write_2(sc, URE_PLA_OCP_GPHY_BASE, URE_MCU_TYPE_PLA, addr & 0xf000); + reg = (addr & 0x0fff) | 0xb000; + + return (ure_read_2(sc, reg, URE_MCU_TYPE_PLA)); +} + +static void +ure_ocp_reg_write(struct ure_softc *sc, uint16_t addr, uint16_t data) +{ + uint16_t reg; + + ure_write_2(sc, URE_PLA_OCP_GPHY_BASE, URE_MCU_TYPE_PLA, addr & 0xf000); + reg = (addr & 0x0fff) | 0xb000; + + ure_write_2(sc, reg, URE_MCU_TYPE_PLA, data); +} + +static int +ure_miibus_readreg(device_t dev, int phy, int reg) +{ + struct ure_softc *sc; + uint16_t val; + int locked; + + sc = device_get_softc(dev); + locked = lockowned(&sc->sc_lock); + if (!locked) + URE_LOCK(sc); + + /* Let the rgephy driver read the URE_GMEDIASTAT register. */ + if (reg == URE_GMEDIASTAT) { + if (!locked) + URE_UNLOCK(sc); + return (ure_read_1(sc, URE_GMEDIASTAT, URE_MCU_TYPE_PLA)); + } + + val = ure_ocp_reg_read(sc, URE_OCP_BASE_MII + reg * 2); + + if (!locked) + URE_UNLOCK(sc); + return (val); +} + +static int +ure_miibus_writereg(device_t dev, int phy, int reg, int val) +{ + struct ure_softc *sc; + int locked; + + sc = device_get_softc(dev); + if (sc->sc_phyno != phy) + return (0); + + locked = lockowned(&sc->sc_lock); + if (!locked) + URE_LOCK(sc); + + ure_ocp_reg_write(sc, URE_OCP_BASE_MII + reg * 2, val); + + if (!locked) + URE_UNLOCK(sc); + return (0); +} + +static void +ure_miibus_statchg(device_t dev) +{ + struct ure_softc *sc; + struct mii_data *mii; + struct ifnet *ifp; + int locked; + + sc = device_get_softc(dev); + mii = GET_MII(sc); + locked = lockowned(&sc->sc_lock); + if (!locked) + URE_LOCK(sc); + + ifp = uether_getifp(&sc->sc_ue); + if (mii == NULL || ifp == NULL || + (ifp->if_flags & IFF_RUNNING) == 0) + goto done; + + sc->sc_flags &= ~URE_FLAG_LINK; + if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == + (IFM_ACTIVE | IFM_AVALID)) { + switch (IFM_SUBTYPE(mii->mii_media_active)) { + case IFM_10_T: + case IFM_100_TX: + sc->sc_flags |= URE_FLAG_LINK; + break; + case IFM_1000_T: + if ((sc->sc_flags & URE_FLAG_8152) != 0) + break; + sc->sc_flags |= URE_FLAG_LINK; + break; + default: + break; + } + } + + /* Lost link, do nothing. */ + if ((sc->sc_flags & URE_FLAG_LINK) == 0) + goto done; +done: + if (!locked) + URE_UNLOCK(sc); +} + +/* + * Probe for a RTL8152/RTL8153 chip. + */ +static int +ure_probe(device_t dev) +{ + struct usb_attach_arg *uaa; + + uaa = device_get_ivars(dev); + if (uaa->usb_mode != USB_MODE_HOST) + return (ENXIO); + if (uaa->info.bConfigIndex != URE_CONFIG_IDX) + return (ENXIO); + if (uaa->info.bIfaceIndex != URE_IFACE_IDX) + return (ENXIO); + + return (usbd_lookup_id_by_uaa(ure_devs, sizeof(ure_devs), uaa)); +} + +/* + * Attach the interface. Allocate softc structures, do ifmedia + * setup and ethernet/BPF attach. + */ +static int +ure_attach(device_t dev) +{ + struct usb_attach_arg *uaa = device_get_ivars(dev); + struct ure_softc *sc = device_get_softc(dev); + struct usb_ether *ue = &sc->sc_ue; + uint8_t iface_index; + int error; + + sc->sc_flags = USB_GET_DRIVER_INFO(uaa); + device_set_usb_desc(dev); + lockinit(&sc->sc_lock, device_get_nameunit(dev), 0, LK_CANRECURSE); + + iface_index = URE_IFACE_IDX; + error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, + ure_config, URE_N_TRANSFER, sc, &sc->sc_lock); + if (error != 0) { + device_printf(dev, "allocating USB transfers failed\n"); + goto detach; + } + + ue->ue_sc = sc; + ue->ue_dev = dev; + ue->ue_udev = uaa->device; + ue->ue_lock = &sc->sc_lock; + ue->ue_methods = &ure_ue_methods; + + error = uether_ifattach(ue); + if (error != 0) { + device_printf(dev, "could not attach interface\n"); + goto detach; + } + return (0); /* success */ + +detach: + ure_detach(dev); + return (ENXIO); /* failure */ +} + +static int +ure_detach(device_t dev) +{ + struct ure_softc *sc = device_get_softc(dev); + struct usb_ether *ue = &sc->sc_ue; + + usbd_transfer_unsetup(sc->sc_xfer, URE_N_TRANSFER); + uether_ifdetach(ue); + lockuninit(&sc->sc_lock); + + return (0); +} + +static void +ure_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct ure_softc *sc = usbd_xfer_softc(xfer); + struct usb_ether *ue = &sc->sc_ue; + struct ifnet *ifp = uether_getifp(ue); + struct usb_page_cache *pc; + struct ure_rxpkt pkt; + int actlen, len; + + usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + if (actlen < (int)(sizeof(pkt))) { + ifp->if_ierrors++; + goto tr_setup; + } + pc = usbd_xfer_get_frame(xfer, 0); + usbd_copy_out(pc, 0, &pkt, sizeof(pkt)); + len = le32toh(pkt.ure_pktlen) & URE_RXPKT_LEN_MASK; + len -= ETHER_CRC_LEN; + if (actlen < (int)(len + sizeof(pkt))) { + ifp->if_ierrors++; + goto tr_setup; + } + + uether_rxbuf(ue, pc, sizeof(pkt), len); + /* FALLTHROUGH */ + case USB_ST_SETUP: +tr_setup: + usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); + usbd_transfer_submit(xfer); + uether_rxflush(ue); + return; + + default: /* Error */ + DPRINTF("bulk read error, %s\n", + usbd_errstr(error)); + + if (error != USB_ERR_CANCELLED) { + /* try to clear stall first */ + usbd_xfer_set_stall(xfer); + goto tr_setup; + } + return; + } +} + +static void +ure_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct ure_softc *sc = usbd_xfer_softc(xfer); + struct ifnet *ifp = uether_getifp(&sc->sc_ue); + struct usb_page_cache *pc; + struct mbuf *m; + struct ure_txpkt txpkt; + int len, pos; + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + DPRINTFN(11, "transfer complete\n"); + ifq_clr_oactive(&ifp->if_snd); + /* FALLTHROUGH */ + case USB_ST_SETUP: +tr_setup: + if ((sc->sc_flags & URE_FLAG_LINK) == 0 || + ifq_is_oactive(&ifp->if_snd)) { + /* + * don't send anything if there is no link ! + */ + return; + } + m = ifq_dequeue(&ifp->if_snd); + if (m == NULL) + break; + pos = 0; + len = m->m_pkthdr.len; + pc = usbd_xfer_get_frame(xfer, 0); + memset(&txpkt, 0, sizeof(txpkt)); + txpkt.ure_pktlen = htole32((len & URE_TXPKT_LEN_MASK) | + URE_TKPKT_TX_FS | URE_TKPKT_TX_LS); + usbd_copy_in(pc, pos, &txpkt, sizeof(txpkt)); + pos += sizeof(txpkt); + usbd_m_copy_in(pc, pos, m, 0, m->m_pkthdr.len); + pos += m->m_pkthdr.len; + + IFNET_STAT_INC(ifp, opackets, 1); + + /* + * If there's a BPF listener, bounce a copy + * of this frame to him. + */ + BPF_MTAP(ifp, m); + + m_freem(m); + + /* Set frame length. */ + usbd_xfer_set_frame_len(xfer, 0, pos); + + usbd_transfer_submit(xfer); + ifq_set_oactive(&ifp->if_snd); + return; + default: /* Error */ + DPRINTFN(11, "transfer error, %s\n", + usbd_errstr(error)); + + IFNET_STAT_INC(ifp, oerrors, 1); + ifq_clr_oactive(&ifp->if_snd); + + if (error != USB_ERR_CANCELLED) { + /* try to clear stall first */ + usbd_xfer_set_stall(xfer); + goto tr_setup; + } + return; + } +} + +static void +ure_read_chipver(struct ure_softc *sc) +{ + uint16_t ver; + + ver = ure_read_2(sc, URE_PLA_TCR1, URE_MCU_TYPE_PLA) & URE_VERSION_MASK; + switch (ver) { + case 0x4c00: + sc->sc_chip |= URE_CHIP_VER_4C00; + break; + case 0x4c10: + sc->sc_chip |= URE_CHIP_VER_4C10; + break; + case 0x5c00: + sc->sc_chip |= URE_CHIP_VER_5C00; + break; + case 0x5c10: + sc->sc_chip |= URE_CHIP_VER_5C10; + break; + case 0x5c20: + sc->sc_chip |= URE_CHIP_VER_5C20; + break; + case 0x5c30: + sc->sc_chip |= URE_CHIP_VER_5C30; + break; + default: + device_printf(sc->sc_ue.ue_dev, + "unknown version 0x%04x\n", ver); + break; + } +} + +static void +ure_attach_post(struct usb_ether *ue) +{ + struct ure_softc *sc = uether_getsc(ue); + + sc->sc_phyno = 0; + + /* Determine the chip version. */ + ure_read_chipver(sc); + + /* Initialize controller and get station address. */ + if (sc->sc_flags & URE_FLAG_8152) + ure_rtl8152_init(sc); + else + ure_rtl8153_init(sc); + + if ((sc->sc_chip & URE_CHIP_VER_4C00) || + (sc->sc_chip & URE_CHIP_VER_4C10)) + ure_read_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA, + ue->ue_eaddr, 8); + else + ure_read_mem(sc, URE_PLA_BACKUP, URE_MCU_TYPE_PLA, + ue->ue_eaddr, 8); + + if (ETHER_IS_ZERO(sc->sc_ue.ue_eaddr)) { + device_printf(sc->sc_ue.ue_dev, "MAC assigned randomly\n"); + karc4rand(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN); + sc->sc_ue.ue_eaddr[0] &= ~0x01; /* unicast */ + sc->sc_ue.ue_eaddr[0] |= 0x02; /* locally administered */ + } +} + +static int +ure_attach_post_sub(struct usb_ether *ue) +{ + struct ure_softc *sc; + struct ifnet *ifp; + int error; + + sc = uether_getsc(ue); + ifp = uether_getifp(ue); + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_start = uether_start; + ifp->if_ioctl = ure_ioctl; + ifp->if_init = uether_init; + ifq_set_maxlen(&ifp->if_snd, ifqmaxlen); + ifq_set_ready(&ifp->if_snd); + + get_mplock(); + error = mii_phy_probe(ue->ue_dev, &ue->ue_miibus, + uether_ifmedia_upd, ue->ue_methods->ue_mii_sts); + rel_mplock(); + + return (error); +} + +static void +ure_init(struct usb_ether *ue) +{ + struct ure_softc *sc = uether_getsc(ue); + struct ifnet *ifp = uether_getifp(ue); + + URE_LOCK_ASSERT(sc, MA_OWNED); + + if ((ifp->if_flags & IFF_RUNNING) != 0) + return; + + /* Cancel pending I/O. */ + ure_stop(ue); + + ure_reset(sc); + + /* Set MAC address. */ + ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_CONFIG); + ure_write_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA | URE_BYTE_EN_SIX_BYTES, + IF_LLADDR(ifp), 8); + ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_NORAML); + + /* Reset the packet filter. */ + ure_write_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA) & + ~URE_FMC_FCR_MCU_EN); + ure_write_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA) | + URE_FMC_FCR_MCU_EN); + + /* Enable transmit and receive. */ + ure_write_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, + ure_read_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA) | URE_CR_RE | + URE_CR_TE); + + ure_write_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA) & + ~URE_RXDY_GATED_EN); + + /* Configure RX filters. */ + ure_rxfilter(ue); + + usbd_xfer_set_stall(sc->sc_xfer[URE_BULK_DT_WR]); + + /* Indicate we are up and running. */ + ifp->if_flags |= IFF_RUNNING; + + /* Switch to selected media. */ + ure_ifmedia_upd(ifp); +} + +static void +ure_tick(struct usb_ether *ue) +{ + struct ure_softc *sc = uether_getsc(ue); + struct mii_data *mii = GET_MII(sc); + + URE_LOCK_ASSERT(sc, MA_OWNED); + + mii_tick(mii); + if ((sc->sc_flags & URE_FLAG_LINK) == 0 + && mii->mii_media_status & IFM_ACTIVE && + IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { + sc->sc_flags |= URE_FLAG_LINK; + ure_start(ue); + } +} + +/* + * Program the 64-bit multicast hash filter. + */ +static void +ure_rxfilter(struct usb_ether *ue) +{ + struct ure_softc *sc = uether_getsc(ue); + struct ifnet *ifp = uether_getifp(ue); + struct ifmultiaddr *ifma; + uint32_t h, rxmode; + uint32_t hashes[2] = { 0, 0 }; + + URE_LOCK_ASSERT(sc, MA_OWNED); + + rxmode = URE_RCR_APM; + if (ifp->if_flags & IFF_BROADCAST) + rxmode |= URE_RCR_AB; + if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) { + if (ifp->if_flags & IFF_PROMISC) + rxmode |= URE_RCR_AAP; + rxmode |= URE_RCR_AM; + hashes[0] = hashes[1] = 0xffffffff; + goto done; + } + + rxmode |= URE_RCR_AM; + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + h = ether_crc32_be(LLADDR((struct sockaddr_dl *) + ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; + if (h < 32) + hashes[0] |= (1 << h); + else + hashes[1] |= (1 << (h - 32)); + } + + h = bswap32(hashes[0]); + hashes[0] = bswap32(hashes[1]); + hashes[1] = h; + rxmode |= URE_RCR_AM; + +done: + ure_write_4(sc, URE_PLA_MAR0, URE_MCU_TYPE_PLA, hashes[0]); + ure_write_4(sc, URE_PLA_MAR4, URE_MCU_TYPE_PLA, hashes[1]); + ure_write_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, rxmode); +} + +static void +ure_start(struct usb_ether *ue) +{ + struct ure_softc *sc = uether_getsc(ue); + + /* + * start the USB transfers, if not already started: + */ + usbd_transfer_start(sc->sc_xfer[URE_BULK_DT_RD]); + usbd_transfer_start(sc->sc_xfer[URE_BULK_DT_WR]); +} + +static void +ure_reset(struct ure_softc *sc) +{ + int i; + + ure_write_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, URE_CR_RST); + + for (i = 0; i < URE_TIMEOUT; i++) { + if (!(ure_read_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA) & + URE_CR_RST)) + break; + uether_pause(&sc->sc_ue, hz / 100); + } + if (i == URE_TIMEOUT) + device_printf(sc->sc_ue.ue_dev, "reset never completed\n"); +} + +/* + * Set media options. + */ +static int +ure_ifmedia_upd(struct ifnet *ifp) +{ + struct ure_softc *sc = ifp->if_softc; + struct mii_data *mii = GET_MII(sc); + struct mii_softc *miisc; + int error; + + URE_LOCK_ASSERT(sc, MA_OWNED); + + LIST_FOREACH(miisc, &mii->mii_phys, mii_list) + mii_phy_reset(miisc); + error = mii_mediachg(mii); + return (error); +} + +/* + * Report current media status. + */ +static void +ure_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) +{ + struct ure_softc *sc; + struct mii_data *mii; + + sc = ifp->if_softc; + mii = GET_MII(sc); + + URE_LOCK(sc); + mii_pollstat(mii); + ifmr->ifm_active = mii->mii_media_active; + ifmr->ifm_status = mii->mii_media_status; + URE_UNLOCK(sc); +} + +static int +ure_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *uc) +{ + struct usb_ether *ue = ifp->if_softc; + struct ure_softc *sc; + struct ifreq *ifr; + int error, mask, reinit; + + sc = uether_getsc(ue); + ifr = (struct ifreq *)data; + error = 0; + reinit = 0; + if (cmd == SIOCSIFCAP) { + URE_LOCK(sc); + mask = ifr->ifr_reqcap ^ ifp->if_capenable; + if (reinit > 0 && ifp->if_flags & IFF_RUNNING) + ifp->if_flags &= ~IFF_RUNNING; + else + reinit = 0; + URE_UNLOCK(sc); + if (reinit > 0) + uether_init(ue); + } else + error = uether_ioctl(ifp, cmd, data, uc); + + return (error); +} + +static void +ure_rtl8152_init(struct ure_softc *sc) +{ + uint32_t pwrctrl; + + /* Disable ALDPS. */ + ure_ocp_reg_write(sc, URE_OCP_ALDPS_CONFIG, URE_ENPDNPS | URE_LINKENA | + URE_DIS_SDSAVE); + uether_pause(&sc->sc_ue, hz / 50); + + if (sc->sc_chip & URE_CHIP_VER_4C00) { + ure_write_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA) & + ~URE_LED_MODE_MASK); + } + + ure_write_2(sc, URE_USB_UPS_CTRL, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_UPS_CTRL, URE_MCU_TYPE_USB) & + ~URE_POWER_CUT); + ure_write_2(sc, URE_USB_PM_CTRL_STATUS, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_PM_CTRL_STATUS, URE_MCU_TYPE_USB) & + ~URE_RESUME_INDICATE); + + ure_write_2(sc, URE_PLA_PHY_PWR, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_PHY_PWR, URE_MCU_TYPE_PLA) | + URE_TX_10M_IDLE_EN | URE_PFM_PWM_SWITCH); + pwrctrl = ure_read_4(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA); + pwrctrl &= ~URE_MCU_CLK_RATIO_MASK; + pwrctrl |= URE_MCU_CLK_RATIO | URE_D3_CLK_GATED_EN; + ure_write_4(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA, pwrctrl); + ure_write_2(sc, URE_PLA_GPHY_INTR_IMR, URE_MCU_TYPE_PLA, + URE_GPHY_STS_MSK | URE_SPEED_DOWN_MSK | URE_SPDWN_RXDV_MSK | + URE_SPDWN_LINKCHG_MSK); + + /* Disable Rx aggregation. */ + ure_write_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB) | + URE_RX_AGG_DISABLE); + + /* Disable ALDPS. */ + ure_ocp_reg_write(sc, URE_OCP_ALDPS_CONFIG, URE_ENPDNPS | URE_LINKENA | + URE_DIS_SDSAVE); + uether_pause(&sc->sc_ue, hz / 50); + + ure_init_fifo(sc); + + ure_write_1(sc, URE_USB_TX_AGG, URE_MCU_TYPE_USB, + URE_TX_AGG_MAX_THRESHOLD); + ure_write_4(sc, URE_USB_RX_BUF_TH, URE_MCU_TYPE_USB, URE_RX_THR_HIGH); + ure_write_4(sc, URE_USB_TX_DMA, URE_MCU_TYPE_USB, + URE_TEST_MODE_DISABLE | URE_TX_SIZE_ADJUST1); +} + +static void +ure_rtl8153_init(struct ure_softc *sc) +{ + uint16_t val; + uint8_t u1u2[8]; + int i; + + /* Disable ALDPS. */ + ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, + ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) & ~URE_EN_ALDPS); + uether_pause(&sc->sc_ue, hz / 50); + + memset(u1u2, 0x00, sizeof(u1u2)); + ure_write_mem(sc, URE_USB_TOLERANCE, + URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); + + for (i = 0; i < URE_TIMEOUT; i++) { + if (ure_read_2(sc, URE_PLA_BOOT_CTRL, URE_MCU_TYPE_PLA) & + URE_AUTOLOAD_DONE) + break; + uether_pause(&sc->sc_ue, hz / 100); + } + if (i == URE_TIMEOUT) + device_printf(sc->sc_ue.ue_dev, + "timeout waiting for chip autoload\n"); + + for (i = 0; i < URE_TIMEOUT; i++) { + val = ure_ocp_reg_read(sc, URE_OCP_PHY_STATUS) & + URE_PHY_STAT_MASK; + if (val == URE_PHY_STAT_LAN_ON || val == URE_PHY_STAT_PWRDN) + break; + uether_pause(&sc->sc_ue, hz / 100); + } + if (i == URE_TIMEOUT) + device_printf(sc->sc_ue.ue_dev, + "timeout waiting for phy to stabilize\n"); + + ure_write_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB) & + ~URE_U2P3_ENABLE); + + if (sc->sc_chip & URE_CHIP_VER_5C10) { + val = ure_read_2(sc, URE_USB_SSPHYLINK2, URE_MCU_TYPE_USB); + val &= ~URE_PWD_DN_SCALE_MASK; + val |= URE_PWD_DN_SCALE(96); + ure_write_2(sc, URE_USB_SSPHYLINK2, URE_MCU_TYPE_USB, val); + + ure_write_1(sc, URE_USB_USB2PHY, URE_MCU_TYPE_USB, + ure_read_1(sc, URE_USB_USB2PHY, URE_MCU_TYPE_USB) | + URE_USB2PHY_L1 | URE_USB2PHY_SUSPEND); + } else if (sc->sc_chip & URE_CHIP_VER_5C20) { + ure_write_1(sc, URE_PLA_DMY_REG0, URE_MCU_TYPE_PLA, + ure_read_1(sc, URE_PLA_DMY_REG0, URE_MCU_TYPE_PLA) & + ~URE_ECM_ALDPS); + } + if (sc->sc_chip & (URE_CHIP_VER_5C20 | URE_CHIP_VER_5C30)) { + val = ure_read_1(sc, URE_USB_CSR_DUMMY1, URE_MCU_TYPE_USB); + if (ure_read_2(sc, URE_USB_BURST_SIZE, URE_MCU_TYPE_USB) == + 0) + val &= ~URE_DYNAMIC_BURST; + else + val |= URE_DYNAMIC_BURST; + ure_write_1(sc, URE_USB_CSR_DUMMY1, URE_MCU_TYPE_USB, val); + } + + ure_write_1(sc, URE_USB_CSR_DUMMY2, URE_MCU_TYPE_USB, + ure_read_1(sc, URE_USB_CSR_DUMMY2, URE_MCU_TYPE_USB) | + URE_EP4_FULL_FC); + + ure_write_2(sc, URE_USB_WDT11_CTRL, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_WDT11_CTRL, URE_MCU_TYPE_USB) & + ~URE_TIMER11_EN); + + ure_write_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA) & + ~URE_LED_MODE_MASK); + + if ((sc->sc_chip & URE_CHIP_VER_5C10) && + usbd_get_speed(sc->sc_ue.ue_udev) != USB_SPEED_SUPER) + val = URE_LPM_TIMER_500MS; + else + val = URE_LPM_TIMER_500US; + ure_write_1(sc, URE_USB_LPM_CTRL, URE_MCU_TYPE_USB, + val | URE_FIFO_EMPTY_1FB | URE_ROK_EXIT_LPM); + + val = ure_read_2(sc, URE_USB_AFE_CTRL2, URE_MCU_TYPE_USB); + val &= ~URE_SEN_VAL_MASK; + val |= URE_SEN_VAL_NORMAL | URE_SEL_RXIDLE; + ure_write_2(sc, URE_USB_AFE_CTRL2, URE_MCU_TYPE_USB, val); + + ure_write_2(sc, URE_USB_CONNECT_TIMER, URE_MCU_TYPE_USB, 0x0001); + + ure_write_2(sc, URE_USB_POWER_CUT, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_POWER_CUT, URE_MCU_TYPE_USB) & + ~(URE_PWR_EN | URE_PHASE2_EN)); + ure_write_2(sc, URE_USB_MISC_0, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_MISC_0, URE_MCU_TYPE_USB) & + ~URE_PCUT_STATUS); + + memset(u1u2, 0xff, sizeof(u1u2)); + ure_write_mem(sc, URE_USB_TOLERANCE, + URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); + + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA, + URE_ALDPS_SPDWN_RATIO); + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA, + URE_EEE_SPDWN_RATIO); + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL3, URE_MCU_TYPE_PLA, + URE_PKT_AVAIL_SPDWN_EN | URE_SUSPEND_SPDWN_EN | + URE_U1U2_SPDWN_EN | URE_L1_SPDWN_EN); + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL4, URE_MCU_TYPE_PLA, + URE_PWRSAVE_SPDWN_EN | URE_RXDV_SPDWN_EN | URE_TX10MIDLE_EN | + URE_TP100_SPDWN_EN | URE_TP500_SPDWN_EN | URE_TP1000_SPDWN_EN | + URE_EEE_SPDWN_EN); + + val = ure_read_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB); + if (!(sc->sc_chip & (URE_CHIP_VER_5C00 | URE_CHIP_VER_5C10))) + val |= URE_U2P3_ENABLE; + else + val &= ~URE_U2P3_ENABLE; + ure_write_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, val); + + memset(u1u2, 0x00, sizeof(u1u2)); + ure_write_mem(sc, URE_USB_TOLERANCE, + URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); + + /* Disable ALDPS. */ + ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, + ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) & ~URE_EN_ALDPS); + uether_pause(&sc->sc_ue, hz / 50); + + ure_init_fifo(sc); + + /* Disable Rx aggregation. */ + ure_write_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB, + ure_read_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB) | + URE_RX_AGG_DISABLE); + + val = ure_read_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB); + if (!(sc->sc_chip & (URE_CHIP_VER_5C00 | URE_CHIP_VER_5C10))) + val |= URE_U2P3_ENABLE; + else + val &= ~URE_U2P3_ENABLE; + ure_write_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, val); + + memset(u1u2, 0xff, sizeof(u1u2)); + ure_write_mem(sc, URE_USB_TOLERANCE, + URE_MCU_TYPE_USB | URE_BYTE_EN_SIX_BYTES, u1u2, sizeof(u1u2)); +} + +static void +ure_stop(struct usb_ether *ue) +{ + struct ure_softc *sc = uether_getsc(ue); + struct ifnet *ifp = uether_getifp(ue); + + URE_LOCK_ASSERT(sc, MA_OWNED); + + ifp->if_flags &= ~IFF_RUNNING; + ifq_clr_oactive(&ifp->if_snd); + sc->sc_flags &= ~URE_FLAG_LINK; + + /* + * stop all the transfers, if not already stopped: + */ + usbd_transfer_stop(sc->sc_xfer[URE_BULK_DT_WR]); + usbd_transfer_stop(sc->sc_xfer[URE_BULK_DT_RD]); +} + +static void +ure_disable_teredo(struct ure_softc *sc) +{ + + ure_write_4(sc, URE_PLA_TEREDO_CFG, URE_MCU_TYPE_PLA, + ure_read_4(sc, URE_PLA_TEREDO_CFG, URE_MCU_TYPE_PLA) & + ~(URE_TEREDO_SEL | URE_TEREDO_RS_EVENT_MASK | URE_OOB_TEREDO_EN)); + ure_write_2(sc, URE_PLA_WDT6_CTRL, URE_MCU_TYPE_PLA, + URE_WDT6_SET_MODE); + ure_write_2(sc, URE_PLA_REALWOW_TIMER, URE_MCU_TYPE_PLA, 0); + ure_write_4(sc, URE_PLA_TEREDO_TIMER, URE_MCU_TYPE_PLA, 0); +} + +static void +ure_init_fifo(struct ure_softc *sc) +{ + uint32_t rx_fifo1, rx_fifo2; + int i; + + ure_write_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA) | + URE_RXDY_GATED_EN); + + ure_disable_teredo(sc); + + ure_write_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, + ure_read_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA) & + ~URE_RCR_ACPT_ALL); + + if (!(sc->sc_flags & URE_FLAG_8152)) { + if (sc->sc_chip & (URE_CHIP_VER_5C00 | URE_CHIP_VER_5C10 | + URE_CHIP_VER_5C20)) { + ure_ocp_reg_write(sc, URE_OCP_ADC_CFG, + URE_CKADSEL_L | URE_ADC_EN | URE_EN_EMI_L); + } + if (sc->sc_chip & URE_CHIP_VER_5C00) { + ure_ocp_reg_write(sc, URE_OCP_EEE_CFG, + ure_ocp_reg_read(sc, URE_OCP_EEE_CFG) & + ~URE_CTAP_SHORT_EN); + } + ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, + ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) | + URE_EEE_CLKDIV_EN); + ure_ocp_reg_write(sc, URE_OCP_DOWN_SPEED, + ure_ocp_reg_read(sc, URE_OCP_DOWN_SPEED) | + URE_EN_10M_BGOFF); + ure_ocp_reg_write(sc, URE_OCP_POWER_CFG, + ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) | + URE_EN_10M_PLLOFF); + ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_IMPEDANCE); + ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0x0b13); + ure_write_2(sc, URE_PLA_PHY_PWR, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_PHY_PWR, URE_MCU_TYPE_PLA) | + URE_PFM_PWM_SWITCH); + + /* Enable LPF corner auto tune. */ + ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_LPF_CFG); + ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0xf70f); + + /* Adjust 10M amplitude. */ + ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_10M_AMP1); + ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0x00af); + ure_ocp_reg_write(sc, URE_OCP_SRAM_ADDR, URE_SRAM_10M_AMP2); + ure_ocp_reg_write(sc, URE_OCP_SRAM_DATA, 0x0208); + } + + ure_reset(sc); + + ure_write_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, 0); + + ure_write_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA, + ure_read_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) & + ~URE_NOW_IS_OOB); + + ure_write_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA) & + ~URE_MCU_BORW_EN); + for (i = 0; i < URE_TIMEOUT; i++) { + if (ure_read_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) & + URE_LINK_LIST_READY) + break; + uether_pause(&sc->sc_ue, hz / 100); + } + if (i == URE_TIMEOUT) + device_printf(sc->sc_ue.ue_dev, + "timeout waiting for OOB control\n"); + ure_write_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA) | + URE_RE_INIT_LL); + for (i = 0; i < URE_TIMEOUT; i++) { + if (ure_read_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) & + URE_LINK_LIST_READY) + break; + uether_pause(&sc->sc_ue, hz / 100); + } + if (i == URE_TIMEOUT) + device_printf(sc->sc_ue.ue_dev, + "timeout waiting for OOB control\n"); + + ure_write_2(sc, URE_PLA_CPCR, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_CPCR, URE_MCU_TYPE_PLA) & + ~URE_CPCR_RX_VLAN); + ure_write_2(sc, URE_PLA_TCR0, URE_MCU_TYPE_PLA, + ure_read_2(sc, URE_PLA_TCR0, URE_MCU_TYPE_PLA) | + URE_TCR0_AUTO_FIFO); + + /* Configure Rx FIFO threshold. */ + ure_write_4(sc, URE_PLA_RXFIFO_CTRL0, URE_MCU_TYPE_PLA, + URE_RXFIFO_THR1_NORMAL); + if (usbd_get_speed(sc->sc_ue.ue_udev) == USB_SPEED_FULL) { + rx_fifo1 = URE_RXFIFO_THR2_FULL; + rx_fifo2 = URE_RXFIFO_THR3_FULL; + } else { + rx_fifo1 = URE_RXFIFO_THR2_HIGH; + rx_fifo2 = URE_RXFIFO_THR3_HIGH; + } + ure_write_4(sc, URE_PLA_RXFIFO_CTRL1, URE_MCU_TYPE_PLA, rx_fifo1); + ure_write_4(sc, URE_PLA_RXFIFO_CTRL2, URE_MCU_TYPE_PLA, rx_fifo2); + + /* Configure Tx FIFO threshold. */ + ure_write_4(sc, URE_PLA_TXFIFO_CTRL, URE_MCU_TYPE_PLA, + URE_TXFIFO_THR_NORMAL); +} diff --git a/sys/bus/u4b/net/if_urereg.h b/sys/bus/u4b/net/if_urereg.h new file mode 100644 index 00000000000..83fccb516f7 --- /dev/null +++ b/sys/bus/u4b/net/if_urereg.h @@ -0,0 +1,440 @@ +/*- + * Copyright (c) 2015-2016 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/dev/usb/net/if_urereg.h 346028 2019-04-08 13:40:46Z ganbold $ + */ + +#define URE_CONFIG_IDX 0 /* config number 1 */ +#define URE_IFACE_IDX 0 + +#define URE_CTL_READ 0x01 +#define URE_CTL_WRITE 0x02 + +#define URE_TIMEOUT 1000 +#define URE_PHY_TIMEOUT 2000 + +#define URE_BYTE_EN_DWORD 0xff +#define URE_BYTE_EN_WORD 0x33 +#define URE_BYTE_EN_BYTE 0x11 +#define URE_BYTE_EN_SIX_BYTES 0x3f + +#define URE_MAX_FRAMELEN (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) + +#define URE_PLA_IDR 0xc000 +#define URE_PLA_RCR 0xc010 +#define URE_PLA_RMS 0xc016 +#define URE_PLA_RXFIFO_CTRL0 0xc0a0 +#define URE_PLA_RXFIFO_CTRL1 0xc0a4 +#define URE_PLA_RXFIFO_CTRL2 0xc0a8 +#define URE_PLA_DMY_REG0 0xc0b0 +#define URE_PLA_FMC 0xc0b4 +#define URE_PLA_CFG_WOL 0xc0b6 +#define URE_PLA_TEREDO_CFG 0xc0bc +#define URE_PLA_MAR0 0xcd00 +#define URE_PLA_MAR4 0xcd04 +#define URE_PLA_BACKUP 0xd000 +#define URE_PAL_BDC_CR 0xd1a0 +#define URE_PLA_TEREDO_TIMER 0xd2cc +#define URE_PLA_REALWOW_TIMER 0xd2e8 +#define URE_PLA_LEDSEL 0xdd90 +#define URE_PLA_LED_FEATURE 0xdd92 +#define URE_PLA_PHYAR 0xde00 +#define URE_PLA_BOOT_CTRL 0xe004 +#define URE_PLA_GPHY_INTR_IMR 0xe022 +#define URE_PLA_EEE_CR 0xe040 +#define URE_PLA_EEEP_CR 0xe080 +#define URE_PLA_MAC_PWR_CTRL 0xe0c0 +#define URE_PLA_MAC_PWR_CTRL2 0xe0ca +#define URE_PLA_MAC_PWR_CTRL3 0xe0cc +#define URE_PLA_MAC_PWR_CTRL4 0xe0ce +#define URE_PLA_WDT6_CTRL 0xe428 +#define URE_PLA_TCR0 0xe610 +#define URE_PLA_TCR1 0xe612 +#define URE_PLA_MTPS 0xe615 +#define URE_PLA_TXFIFO_CTRL 0xe618 +#define URE_PLA_RSTTELLY 0xe800 +#define URE_PLA_CR 0xe813 +#define URE_PLA_CRWECR 0xe81c +#define URE_PLA_CONFIG5 0xe822 +#define URE_PLA_PHY_PWR 0xe84c +#define URE_PLA_OOB_CTRL 0xe84f +#define URE_PLA_CPCR 0xe854 +#define URE_PLA_MISC_0 0xe858 +#define URE_PLA_MISC_1 0xe85a +#define URE_PLA_OCP_GPHY_BASE 0xe86c +#define URE_PLA_TELLYCNT 0xe890 +#define URE_PLA_SFF_STS_7 0xe8de +#define URE_GMEDIASTAT 0xe908 + +#define URE_USB_USB2PHY 0xb41e +#define URE_USB_SSPHYLINK2 0xb428 +#define URE_USB_U2P3_CTRL 0xb460 +#define URE_USB_CSR_DUMMY1 0xb464 +#define URE_USB_CSR_DUMMY2 0xb466 +#define URE_USB_DEV_STAT 0xb808 +#define URE_USB_CONNECT_TIMER 0xcbf8 +#define URE_USB_BURST_SIZE 0xcfc0 +#define URE_USB_USB_CTRL 0xd406 +#define URE_USB_PHY_CTRL 0xd408 +#define URE_USB_TX_AGG 0xd40a +#define URE_USB_RX_BUF_TH 0xd40c +#define URE_USB_USB_TIMER 0xd428 +#define URE_USB_RX_EARLY_AGG 0xd42c +#define URE_USB_PM_CTRL_STATUS 0xd432 +#define URE_USB_TX_DMA 0xd434 +#define URE_USB_TOLERANCE 0xd490 +#define URE_USB_LPM_CTRL 0xd41a +#define URE_USB_UPS_CTRL 0xd800 +#define URE_USB_MISC_0 0xd81a +#define URE_USB_POWER_CUT 0xd80a +#define URE_USB_AFE_CTRL2 0xd824 +#define URE_USB_WDT11_CTRL 0xe43c + +/* OCP Registers. */ +#define URE_OCP_ALDPS_CONFIG 0x2010 +#define URE_OCP_EEE_CONFIG1 0x2080 +#define URE_OCP_EEE_CONFIG2 0x2092 +#define URE_OCP_EEE_CONFIG3 0x2094 +#define URE_OCP_BASE_MII 0xa400 +#define URE_OCP_EEE_AR 0xa41a +#define URE_OCP_EEE_DATA 0xa41c +#define URE_OCP_PHY_STATUS 0xa420 +#define URE_OCP_POWER_CFG 0xa430 +#define URE_OCP_EEE_CFG 0xa432 +#define URE_OCP_SRAM_ADDR 0xa436 +#define URE_OCP_SRAM_DATA 0xa438 +#define URE_OCP_DOWN_SPEED 0xa442 +#define URE_OCP_EEE_ABLE 0xa5c4 +#define URE_OCP_EEE_ADV 0xa5d0 +#define URE_OCP_EEE_LPABLE 0xa5d2 +#define URE_OCP_PHY_STATE 0xa708 +#define URE_OCP_ADC_CFG 0xbc06 + +/* SRAM Register. */ +#define URE_SRAM_LPF_CFG 0x8012 +#define URE_SRAM_10M_AMP1 0x8080 +#define URE_SRAM_10M_AMP2 0x8082 +#define URE_SRAM_IMPEDANCE 0x8084 + +/* PLA_RCR */ +#define URE_RCR_AAP 0x00000001 +#define URE_RCR_APM 0x00000002 +#define URE_RCR_AM 0x00000004 +#define URE_RCR_AB 0x00000008 +#define URE_RCR_ACPT_ALL \ + (URE_RCR_AAP | URE_RCR_APM | URE_RCR_AM | URE_RCR_AB) + +/* PLA_RXFIFO_CTRL0 */ +#define URE_RXFIFO_THR1_NORMAL 0x00080002 +#define URE_RXFIFO_THR1_OOB 0x01800003 + +/* PLA_RXFIFO_CTRL1 */ +#define URE_RXFIFO_THR2_FULL 0x00000060 +#define URE_RXFIFO_THR2_HIGH 0x00000038 +#define URE_RXFIFO_THR2_OOB 0x0000004a +#define URE_RXFIFO_THR2_NORMAL 0x00a0 + +/* PLA_RXFIFO_CTRL2 */ +#define URE_RXFIFO_THR3_FULL 0x00000078 +#define URE_RXFIFO_THR3_HIGH 0x00000048 +#define URE_RXFIFO_THR3_OOB 0x0000005a +#define URE_RXFIFO_THR3_NORMAL 0x0110 + +/* PLA_TXFIFO_CTRL */ +#define URE_TXFIFO_THR_NORMAL 0x00400008 +#define URE_TXFIFO_THR_NORMAL2 0x01000008 + +/* PLA_DMY_REG0 */ +#define URE_ECM_ALDPS 0x0002 + +/* PLA_FMC */ +#define URE_FMC_FCR_MCU_EN 0x0001 + +/* PLA_EEEP_CR */ +#define URE_EEEP_CR_EEEP_TX 0x0002 + +/* PLA_WDT6_CTRL */ +#define URE_WDT6_SET_MODE 0x0010 + +/* PLA_TCR0 */ +#define URE_TCR0_TX_EMPTY 0x0800 +#define URE_TCR0_AUTO_FIFO 0x0080 + +/* PLA_TCR1 */ +#define URE_VERSION_MASK 0x7cf0 + +/* PLA_CR */ +#define URE_CR_RST 0x10 +#define URE_CR_RE 0x08 +#define URE_CR_TE 0x04 + +/* PLA_CRWECR */ +#define URE_CRWECR_NORAML 0x00 +#define URE_CRWECR_CONFIG 0xc0 + +/* PLA_OOB_CTRL */ +#define URE_NOW_IS_OOB 0x80 +#define URE_TXFIFO_EMPTY 0x20 +#define URE_RXFIFO_EMPTY 0x10 +#define URE_LINK_LIST_READY 0x02 +#define URE_DIS_MCU_CLROOB 0x01 +#define URE_FIFO_EMPTY (URE_TXFIFO_EMPTY | URE_RXFIFO_EMPTY) + +/* PLA_MISC_1 */ +#define URE_RXDY_GATED_EN 0x0008 + +/* PLA_SFF_STS_7 */ +#define URE_RE_INIT_LL 0x8000 +#define URE_MCU_BORW_EN 0x4000 + +/* PLA_CPCR */ +#define URE_CPCR_RX_VLAN 0x0040 + +/* PLA_TEREDO_CFG */ +#define URE_TEREDO_SEL 0x8000 +#define URE_TEREDO_WAKE_MASK 0x7f00 +#define URE_TEREDO_RS_EVENT_MASK 0x00fe +#define URE_OOB_TEREDO_EN 0x0001 + +/* PAL_BDC_CR */ +#define URE_ALDPS_PROXY_MODE 0x0001 + +/* PLA_CONFIG5 */ +#define URE_LAN_WAKE_EN 0x0002 + +/* PLA_LED_FEATURE */ +#define URE_LED_MODE_MASK 0x0700 + +/* PLA_PHY_PWR */ +#define URE_TX_10M_IDLE_EN 0x0080 +#define URE_PFM_PWM_SWITCH 0x0040 + +/* PLA_MAC_PWR_CTRL */ +#define URE_D3_CLK_GATED_EN 0x00004000 +#define URE_MCU_CLK_RATIO 0x07010f07 +#define URE_MCU_CLK_RATIO_MASK 0x0f0f0f0f +#define URE_ALDPS_SPDWN_RATIO 0x0f87 + +/* PLA_MAC_PWR_CTRL2 */ +#define URE_EEE_SPDWN_RATIO 0x8007 + +/* PLA_MAC_PWR_CTRL3 */ +#define URE_PKT_AVAIL_SPDWN_EN 0x0100 +#define URE_SUSPEND_SPDWN_EN 0x0004 +#define URE_U1U2_SPDWN_EN 0x0002 +#define URE_L1_SPDWN_EN 0x0001 + +/* PLA_MAC_PWR_CTRL4 */ +#define URE_PWRSAVE_SPDWN_EN 0x1000 +#define URE_RXDV_SPDWN_EN 0x0800 +#define URE_TX10MIDLE_EN 0x0100 +#define URE_TP100_SPDWN_EN 0x0020 +#define URE_TP500_SPDWN_EN 0x0010 +#define URE_TP1000_SPDWN_EN 0x0008 +#define URE_EEE_SPDWN_EN 0x0001 + +/* PLA_GPHY_INTR_IMR */ +#define URE_GPHY_STS_MSK 0x0001 +#define URE_SPEED_DOWN_MSK 0x0002 +#define URE_SPDWN_RXDV_MSK 0x0004 +#define URE_SPDWN_LINKCHG_MSK 0x0008 + +/* PLA_PHYAR */ +#define URE_PHYAR_PHYDATA 0x0000ffff +#define URE_PHYAR_BUSY 0x80000000 + +/* PLA_EEE_CR */ +#define URE_EEE_RX_EN 0x0001 +#define URE_EEE_TX_EN 0x0002 + +/* PLA_BOOT_CTRL */ +#define URE_AUTOLOAD_DONE 0x0002 + +/* USB_USB2PHY */ +#define URE_USB2PHY_SUSPEND 0x0001 +#define URE_USB2PHY_L1 0x0002 + +/* USB_SSPHYLINK2 */ +#define URE_PWD_DN_SCALE_MASK 0x3ffe +#define URE_PWD_DN_SCALE(x) ((x) << 1) + +/* USB_CSR_DUMMY1 */ +#define URE_DYNAMIC_BURST 0x0001 + +/* USB_CSR_DUMMY2 */ +#define URE_EP4_FULL_FC 0x0001 + +/* USB_DEV_STAT */ +#define URE_STAT_SPEED_MASK 0x0006 +#define URE_STAT_SPEED_HIGH 0x0000 +#define URE_STAT_SPEED_FULL 0x0001 + +/* USB_TX_AGG */ +#define URE_TX_AGG_MAX_THRESHOLD 0x03 + +/* USB_RX_BUF_TH */ +#define URE_RX_THR_SUPER 0x0c350180 +#define URE_RX_THR_HIGH 0x7a120180 +#define URE_RX_THR_SLOW 0xffff0180 + +/* USB_TX_DMA */ +#define URE_TEST_MODE_DISABLE 0x00000001 +#define URE_TX_SIZE_ADJUST1 0x00000100 + +/* USB_UPS_CTRL */ +#define URE_POWER_CUT 0x0100 + +/* USB_PM_CTRL_STATUS */ +#define URE_RESUME_INDICATE 0x0001 + +/* USB_USB_CTRL */ +#define URE_RX_AGG_DISABLE 0x0010 +#define URE_RX_ZERO_EN 0x0080 + +/* USB_U2P3_CTRL */ +#define URE_U2P3_ENABLE 0x0001 + +/* USB_POWER_CUT */ +#define URE_PWR_EN 0x0001 +#define URE_PHASE2_EN 0x0008 + +/* USB_MISC_0 */ +#define URE_PCUT_STATUS 0x0001 + +/* USB_RX_EARLY_TIMEOUT */ +#define URE_COALESCE_SUPER 85000U +#define URE_COALESCE_HIGH 250000U +#define URE_COALESCE_SLOW 524280U + +/* USB_WDT11_CTRL */ +#define URE_TIMER11_EN 0x0001 + +/* USB_LPM_CTRL */ +#define URE_FIFO_EMPTY_1FB 0x30 +#define URE_LPM_TIMER_MASK 0x0c +#define URE_LPM_TIMER_500MS 0x04 +#define URE_LPM_TIMER_500US 0x0c +#define URE_ROK_EXIT_LPM 0x02 + +/* USB_AFE_CTRL2 */ +#define URE_SEN_VAL_MASK 0xf800 +#define URE_SEN_VAL_NORMAL 0xa000 +#define URE_SEL_RXIDLE 0x0100 + +/* OCP_ALDPS_CONFIG */ +#define URE_ENPWRSAVE 0x8000 +#define URE_ENPDNPS 0x0200 +#define URE_LINKENA 0x0100 +#define URE_DIS_SDSAVE 0x0010 + +/* OCP_PHY_STATUS */ +#define URE_PHY_STAT_MASK 0x0007 +#define URE_PHY_STAT_LAN_ON 3 +#define URE_PHY_STAT_PWRDN 5 + +/* OCP_POWER_CFG */ +#define URE_EEE_CLKDIV_EN 0x8000 +#define URE_EN_ALDPS 0x0004 +#define URE_EN_10M_PLLOFF 0x0001 + +/* OCP_EEE_CFG */ +#define URE_CTAP_SHORT_EN 0x0040 +#define URE_EEE10_EN 0x0010 + +/* OCP_DOWN_SPEED */ +#define URE_EN_10M_BGOFF 0x0080 + +/* OCP_PHY_STATE */ +#define URE_TXDIS_STATE 0x01 +#define URE_ABD_STATE 0x02 + +/* OCP_ADC_CFG */ +#define URE_CKADSEL_L 0x0100 +#define URE_ADC_EN 0x0080 +#define URE_EN_EMI_L 0x0040 + +#define URE_MCU_TYPE_PLA 0x0100 +#define URE_MCU_TYPE_USB 0x0000 + +#define GET_MII(sc) uether_getmii(&(sc)->sc_ue) + +struct ure_intrpkt { + uint8_t ure_tsr; + uint8_t ure_rsr; + uint8_t ure_gep_msr; + uint8_t ure_waksr; + uint8_t ure_txok_cnt; + uint8_t ure_rxlost_cnt; + uint8_t ure_crcerr_cnt; + uint8_t ure_col_cnt; +} __packed; + +struct ure_rxpkt { + uint32_t ure_pktlen; +#define URE_RXPKT_LEN_MASK 0x7fff + uint32_t ure_rsvd0; + uint32_t ure_rsvd1; + uint32_t ure_rsvd2; + uint32_t ure_rsvd3; + uint32_t ure_rsvd4; +} __packed; + +struct ure_txpkt { + uint32_t ure_pktlen; +#define URE_TKPKT_TX_FS (1 << 31) +#define URE_TKPKT_TX_LS (1 << 30) +#define URE_TXPKT_LEN_MASK 0xffff + uint32_t ure_rsvd0; +} __packed; + +enum { + URE_BULK_DT_WR, + URE_BULK_DT_RD, + URE_N_TRANSFER, +}; + +struct ure_softc { + struct usb_ether sc_ue; + struct lock sc_lock; + struct usb_xfer *sc_xfer[URE_N_TRANSFER]; + + int sc_phyno; + + u_int sc_flags; +#define URE_FLAG_LINK 0x0001 +#define URE_FLAG_8152 0x1000 /* RTL8152 */ + + u_int sc_chip; +#define URE_CHIP_VER_4C00 0x01 +#define URE_CHIP_VER_4C10 0x02 +#define URE_CHIP_VER_5C00 0x04 +#define URE_CHIP_VER_5C10 0x08 +#define URE_CHIP_VER_5C20 0x10 +#define URE_CHIP_VER_5C30 0x20 +}; + +#define URE_LOCK(_sc) lockmgr(&(_sc)->sc_lock, LK_EXCLUSIVE) +#define URE_UNLOCK(_sc) lockmgr(&(_sc)->sc_lock, LK_RELEASE) +#define URE_LOCK_ASSERT(_sc, t) KKASSERT(lockowned(&(_sc)->sc_lock)) diff --git a/sys/bus/u4b/net/ure/Makefile b/sys/bus/u4b/net/ure/Makefile new file mode 100644 index 00000000000..610497c269a --- /dev/null +++ b/sys/bus/u4b/net/ure/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD: head/sys/modules/usb/ure/Makefile 314651 2017-03-04 10:10:17Z ngie $ + +.PATH: ${.CURDIR}/.. + +KMOD= if_ure +SRCS+= if_ure.c usbdevs.h +SRCS+= bus_if.h device_if.h miibus_if.h usb_if.h \ + opt_bus.h opt_inet.h opt_usb.h + +.include diff --git a/sys/bus/u4b/usbdevs b/sys/bus/u4b/usbdevs index 84790a871b9..4b7794c9cc6 100644 --- a/sys/bus/u4b/usbdevs +++ b/sys/bus/u4b/usbdevs @@ -3310,6 +3310,9 @@ product MELCO WIU2433DHP 0x029b WI-U2-433DHP /* Mercusys, Inc. */ product MERCUSYS MW150US 0x0102 Mercusys MW150US +/* NVIDIA products */ +product NVIDIA RTL8153 0x09ff USB 3.0 Ethernet + /* Merlin products */ product MERLIN V620 0x1110 Merlin V620 diff --git a/sys/conf/files b/sys/conf/files index aa9602eb61f..46dd100e8c1 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2910,6 +2910,7 @@ bus/u4b/net/if_ipheth.c optional ipheth uether bus/u4b/net/if_kue.c optional kue uether bus/u4b/net/if_mos.c optional mos uether bus/u4b/net/if_udav.c optional udav uether +bus/u4b/net/if_ure.c optional ure uether bus/u4b/net/if_urndis.c optional urndis uether # # USB WLAN drivers diff --git a/sys/config/LINT64 b/sys/config/LINT64 index 2ef7a15f2c1..c5293551be2 100644 --- a/sys/config/LINT64 +++ b/sys/config/LINT64 @@ -1969,6 +1969,9 @@ device rum device run device runfw # +# RealTek RTL8152/RTL8153 USB to Ethernet driver +device ure +# # RNDIS USB ethernet driver device urndis # -- 2.49.0