aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/Makefile2
-rw-r--r--share/man/man4/miibus.45
-rw-r--r--share/man/man4/ure.4121
-rw-r--r--sys/conf/NOTES3
-rw-r--r--sys/conf/files3
-rw-r--r--sys/dev/usb/net/if_ure.c1070
-rw-r--r--sys/dev/usb/net/if_urereg.h435
-rw-r--r--sys/dev/usb/usbdevs1
-rw-r--r--sys/modules/usb/Makefile2
-rw-r--r--sys/modules/usb/ure/Makefile10
10 files changed, 1649 insertions, 3 deletions
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index 3b750184d321..1807876217b3 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -521,6 +521,7 @@ MAN= aac.4 \
tws.4 \
tx.4 \
txp.4 \
+ ure.4 \
vale.4 \
vga.4 \
vge.4 \
@@ -710,6 +711,7 @@ MLINKS+=tl.4 if_tl.4
MLINKS+=tun.4 if_tun.4
MLINKS+=tx.4 if_tx.4
MLINKS+=txp.4 if_txp.4
+MLINKS+=ure.4 if_ure.4
MLINKS+=vge.4 if_vge.4
MLINKS+=vlan.4 if_vlan.4
MLINKS+=vxlan.4 if_vxlan.4
diff --git a/share/man/man4/miibus.4 b/share/man/man4/miibus.4
index b0f5204b5b51..667addfb6317 100644
--- a/share/man/man4/miibus.4
+++ b/share/man/man4/miibus.4
@@ -8,7 +8,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 5, 2015
+.Dd December 1, 2015
.Dt MIIBUS 4
.Os
.Sh NAME
@@ -117,6 +117,8 @@ Texas Instruments ThunderLAN
SMC EtherPower II (83c170)
.It Xr udav 4
Davicom DM9601 USB Ethernet
+.It Xr ure 4
+RealTek RTL8152 USB To Fast Ethernet
.It Xr vge 4
VIA VT612x PCI Gigabit Ethernet
.It Xr vr 4
@@ -177,6 +179,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 vte 4 ,
diff --git a/share/man/man4/ure.4 b/share/man/man4/ure.4
new file mode 100644
index 000000000000..1b2ebb885d79
--- /dev/null
+++ b/share/man/man4/ure.4
@@ -0,0 +1,121 @@
+.\"
+.\" Copyright (c) 2015 Kevin Lo <kevlo@FreeBSD.org>
+.\" 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$
+.\"
+.Dd December 1, 2015
+.Dt URE 4
+.Os
+.Sh NAME
+.Nm ure
+.Nd "RealTek RTL8152 USB to Fast 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 USB to Fast Ethernet controller chip.
+.Pp
+The RTL8152 contains an integrated Fast Ethernet MAC, which supports
+both 10 and 100Mbps speeds in either full or half duplex.
+.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.
+.El
+.Pp
+The
+.Nm
+driver supports the following media options:
+.Bl -tag -width ".Cm 10baseT/UTP"
+.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 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/sys/conf/NOTES b/sys/conf/NOTES
index 89a9a0a3f82f..3c64d5b502c2 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2740,6 +2740,9 @@ device rue
# Davicom DM9601E USB to fast ethernet. Supports the Corega FEther USB-TXC.
device udav
#
+# RealTek RTL8152 USB to fast ethernet.
+device ure
+#
# Moschip MCS7730/MCS7840 USB to fast ethernet. Supports the Sitecom LN030.
device mos
#
diff --git a/sys/conf/files b/sys/conf/files
index ea03624fd155..3d511db76e1c 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -2612,12 +2612,13 @@ dev/usb/net/if_mos.c optional mos
dev/usb/net/if_rue.c optional rue
dev/usb/net/if_smsc.c optional smsc
dev/usb/net/if_udav.c optional udav
+dev/usb/net/if_ure.c optional ure
dev/usb/net/if_usie.c optional usie
dev/usb/net/if_urndis.c optional urndis
dev/usb/net/ruephy.c optional rue
dev/usb/net/usb_ethernet.c optional uether | aue | axe | axge | cdce | \
cue | ipheth | kue | mos | rue | \
- smsc | udav | urndis
+ smsc | udav | ure | urndis
dev/usb/net/uhso.c optional uhso
#
# USB WLAN drivers
diff --git a/sys/dev/usb/net/if_ure.c b/sys/dev/usb/net/if_ure.c
new file mode 100644
index 000000000000..4d215f8ef8de
--- /dev/null
+++ b/sys/dev/usb/net/if_ure.c
@@ -0,0 +1,1070 @@
+/*-
+ * Copyright (c) 2015 Kevin Lo <kevlo@FreeBSD.org>
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/unistd.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include "usbdevs.h"
+
+#define USB_DEBUG_VAR ure_debug
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+
+#include <dev/usb/net/usb_ethernet.h>
+#include <dev/usb/net/if_urereg.h>
+
+#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_RWTUN, &ure_debug, 0,
+ "Debug level");
+#endif
+
+/*
+ * Various supported device vendors/products.
+ */
+static const STRUCT_USB_HOST_ID ure_devs[] = {
+#define URE_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
+ URE_DEV(REALTEK, RTL8152),
+#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_setmulti;
+static uether_fn_t ure_setpromisc;
+
+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);
+static void ure_rtl8152_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 = MCLBYTES,
+ .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);
+
+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_setmulti,
+ .ue_setpromisc = ure_setpromisc,
+ .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 = mtx_owned(&sc->sc_mtx);
+ if (!locked)
+ URE_LOCK(sc);
+
+ 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 = mtx_owned(&sc->sc_mtx);
+ 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 = mtx_owned(&sc->sc_mtx);
+ if (!locked)
+ URE_LOCK(sc);
+
+ ifp = uether_getifp(&sc->sc_ue);
+ if (mii == NULL || ifp == NULL ||
+ (ifp->if_drv_flags & IFF_DRV_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;
+ 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 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;
+
+ device_set_usb_desc(dev);
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ iface_index = URE_IFACE_IDX;
+ error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
+ ure_config, URE_N_TRANSFER, sc, &sc->sc_mtx);
+ 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_mtx = &sc->sc_mtx;
+ 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);
+ mtx_destroy(&sc->sc_mtx);
+
+ 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))) {
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ 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))) {
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ 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");
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+tr_setup:
+ if ((sc->sc_flags & URE_FLAG_LINK) == 0 ||
+ (ifp->if_drv_flags & IFF_DRV_OACTIVE) != 0) {
+ /*
+ * don't send anything if there is no link !
+ */
+ return;
+ }
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ 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;
+
+ if_inc_counter(ifp, IFCOUNTER_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);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ return;
+ default: /* Error */
+ DPRINTFN(11, "transfer error, %s\n",
+ usbd_errstr(error));
+
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ 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;
+ 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. */
+ ure_rtl8152_init(sc);
+
+ if (sc->sc_chip & URE_CHIP_VER_4C00)
+ 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);
+}
+
+static int
+ure_attach_post_sub(struct usb_ether *ue)
+{
+ struct ure_softc *sc;
+ struct ifnet *ifp;
+ int error;
+
+ sc = uether_getsc(ue);
+ ifp = ue->ue_ifp;
+ 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);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ mtx_lock(&Giant);
+ error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp,
+ uether_ifmedia_upd, ue->ue_methods->ue_mii_sts,
+ BMSR_DEFCAPMASK, sc->sc_phyno, MII_OFFSET_ANY, 0);
+ mtx_unlock(&Giant);
+
+ return (error);
+}
+
+static void
+ure_init(struct usb_ether *ue)
+{
+ struct ure_softc *sc = uether_getsc(ue);
+ struct ifnet *ifp = uether_getifp(ue);
+ uint32_t rxmode;
+
+ URE_LOCK_ASSERT(sc, MA_OWNED);
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
+
+ /* Cancel pending I/O. */
+ ure_stop(ue);
+
+ ure_reset(sc);
+
+ /* Set MAC address. */
+ ure_write_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA | URE_BYTE_EN_SIX_BYTES,
+ IF_LLADDR(ifp), 8);
+
+ /* 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);
+
+ /* Set Rx mode. */
+ rxmode = URE_RCR_APM;
+
+ /* If we want promiscuous mode, set the allframes bit. */
+ if (ifp->if_flags & IFF_PROMISC)
+ rxmode |= URE_RCR_AAP;
+
+ if (ifp->if_flags & IFF_BROADCAST)
+ rxmode |= URE_RCR_AB;
+
+ ure_write_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, rxmode);
+
+ /* Load the multicast filter. */
+ ure_setmulti(ue);
+
+ usbd_xfer_set_stall(sc->sc_xfer[URE_BULK_DT_WR]);
+
+ /* Indicate we are up and running. */
+ ifp->if_drv_flags |= IFF_DRV_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);
+ }
+}
+
+static void
+ure_setpromisc(struct usb_ether *ue)
+{
+ struct ure_softc *sc = uether_getsc(ue);
+ struct ifnet *ifp = uether_getifp(ue);
+ uint32_t rxmode;
+
+ rxmode = ure_read_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA);
+
+ if (ifp->if_flags & IFF_PROMISC)
+ rxmode |= URE_RCR_AAP;
+ else
+ rxmode &= ~URE_RCR_AAP;
+
+ ure_write_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, rxmode);
+
+ ure_setmulti(ue);
+}
+
+/*
+ * Program the 64-bit multicast hash filter.
+ */
+static void
+ure_setmulti(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_read_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA);
+ 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;
+ }
+
+ if_maddr_rlock(ifp);
+ 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));
+ }
+ if_maddr_runlock(ifp);
+
+ 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)
+ 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 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_drv_flags & IFF_DRV_RUNNING)
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ else
+ reinit = 0;
+ URE_UNLOCK(sc);
+ if (reinit > 0)
+ uether_init(ue);
+ } else
+ error = uether_ioctl(ifp, cmd, data);
+
+ 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_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_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ 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);
+
+ 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/dev/usb/net/if_urereg.h b/sys/dev/usb/net/if_urereg.h
new file mode 100644
index 000000000000..89c34f5a64ca
--- /dev/null
+++ b/sys/dev/usb/net/if_urereg.h
@@ -0,0 +1,435 @@
+/*-
+ * Copyright (c) 2015 Kevin Lo <kevlo@FreeBSD.org>
+ * 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$
+ */
+
+#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_PLA_PHYSTATUS 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 0x001
+
+/* 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 mtx sc_mtx;
+ struct usb_xfer *sc_xfer[URE_N_TRANSFER];
+
+ int sc_phyno;
+
+ u_int sc_flags;
+#define URE_FLAG_LINK 0x0001
+
+ u_int sc_chip;
+#define URE_CHIP_VER_4C00 0x01
+#define URE_CHIP_VER_4C10 0x02
+};
+
+#define URE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define URE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define URE_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->sc_mtx, t)
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 83d41e63d8cd..42ba9c1ffcd0 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -3784,6 +3784,7 @@ product REALTEK USB20CRW 0x0158 USB20CRW Card Reader
product REALTEK RTL8188ETV 0x0179 RTL8188ETV
product REALTEK RTL8188CTV 0x018a RTL8188CTV
product REALTEK USBKR100 0x8150 USBKR100 USB Ethernet
+product REALTEK RTL8152 0x8152 RTL8152 USB Ethernet
product REALTEK RTL8153 0x8153 RTL8153 USB Ethernet
product REALTEK RTL8188CE_0 0x8170 RTL8188CE
product REALTEK RTL8171 0x8171 RTL8171
diff --git a/sys/modules/usb/Makefile b/sys/modules/usb/Makefile
index ed8edcf510fb..8bb355ba2beb 100644
--- a/sys/modules/usb/Makefile
+++ b/sys/modules/usb/Makefile
@@ -53,7 +53,7 @@ SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \
umct umcs umodem umoscom uplcom uslcom uvisor uvscom
SUBDIR += udl
SUBDIR += uether aue axe axge cdce cue ${_kue} mos rue smsc udav uhso ipheth
-SUBDIR += urndis
+SUBDIR += ure urndis
SUBDIR += usfs umass urio
SUBDIR += quirk template
SUBDIR += ${_g_audio} ${_g_keyboard} ${_g_modem} ${_g_mouse}
diff --git a/sys/modules/usb/ure/Makefile b/sys/modules/usb/ure/Makefile
new file mode 100644
index 000000000000..61dfc378b37a
--- /dev/null
+++ b/sys/modules/usb/ure/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/usb/net
+
+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 <bsd.kmod.mk>