Hi, This diff adds preliminary support for RTL8156 to ure(4). Tested with the Planex USB-LAN2500R.
Index: share/man/man4/ure.4 =================================================================== RCS file: /cvs/src/share/man/man4/ure.4,v retrieving revision 1.6 diff -u -p -u -p -r1.6 ure.4 --- share/man/man4/ure.4 29 Aug 2019 08:55:05 -0000 1.6 +++ share/man/man4/ure.4 3 Dec 2019 08:29:40 -0000 @@ -31,7 +31,7 @@ .Os .Sh NAME .Nm ure -.Nd RealTek RTL8152/RTL8153/RTL8153B 10/100/Gigabit USB Ethernet device +.Nd RealTek RTL8152/RTL8153/RTL8153B/RTL8156 10/100/Gigabit/2.5Gb USB Ethernet device .Sh SYNOPSIS .Cd "ure* at uhub?" .Cd "rgephy* at mii?" @@ -40,12 +40,13 @@ The .Nm driver provides support for USB Ethernet adapters based on the RealTek -RTL8152, RTL8153 and RTL8153B chipsets. +RTL8152, RTL8153, RTL8153B and RTL8156 chipsets. .Pp The RTL8152 contains an integrated Fast Ethernet MAC, which supports both 10 and 100Mbps speeds in either full or half duplex. The RTL8153 and RTL8153B have Gigabit Ethernet MACs and additionally support 1000Mbps speeds. +NICs based on the RTL8156 are capable of 10, 100, 1000 and 2500Mbps operation. .Pp For more information on configuring this device, see .Xr ifconfig 8 . Index: share/man/man4/usb.4 =================================================================== RCS file: /cvs/src/share/man/man4/usb.4,v retrieving revision 1.197 diff -u -p -u -p -r1.197 usb.4 --- share/man/man4/usb.4 29 Aug 2019 08:55:05 -0000 1.197 +++ share/man/man4/usb.4 3 Dec 2019 08:29:40 -0000 @@ -128,7 +128,7 @@ SMSC LAN95xx 10/100 USB Ethernet device .It Xr udav 4 Davicom DM9601 10/100 USB Ethernet device .It Xr ure 4 -RealTek RTL8152/RTL8153/RTL8153B 10/100/Gigabit USB Ethernet device +RealTek RTL8152/RTL8153/RTL8153B/RTL8156 10/100/Gigabit/2.5Gb USB Ethernet device .It Xr url 4 Realtek RTL8150L 10/100 USB Ethernet device .It Xr urndis 4 Index: sys/dev/usb/if_ure.c =================================================================== RCS file: /cvs/src/sys/dev/usb/if_ure.c,v retrieving revision 1.12 diff -u -p -u -p -r1.12 if_ure.c --- sys/dev/usb/if_ure.c 29 Aug 2019 14:04:48 -0000 1.12 +++ sys/dev/usb/if_ure.c 3 Dec 2019 08:29:41 -0000 @@ -50,6 +50,7 @@ #include <netinet/in.h> #include <netinet/if_ether.h> +#include <dev/mii/mii.h> #include <dev/mii/miivar.h> #include <dev/usb/usb.h> @@ -73,7 +74,8 @@ int uredebug = 0; const struct usb_devno ure_devs[] = { { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_DOCK_ETHERNET }, { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8152 }, - { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8153 } + { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8153 }, + { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8156 } }; int ure_match(struct device *, void *, void *); @@ -107,6 +109,7 @@ void ure_init(void *); void ure_stop(struct ure_softc *); void ure_start(struct ifnet *); void ure_reset(struct ure_softc *); +void ure_watchdog(struct ifnet *); void ure_miibus_statchg(struct device *); int ure_miibus_readreg(struct device *, int, int); @@ -125,6 +128,9 @@ void ure_tick(void *); int ure_ifmedia_upd(struct ifnet *); void ure_ifmedia_sts(struct ifnet *, struct ifmediareq *); +void ure_add_media_types(struct ure_softc *); +void ure_link_state(struct ure_softc *); +int ure_get_link_status(struct ure_softc *); void ure_iff(struct ure_softc *); void ure_rxvlan(struct ure_softc *); int ure_ioctl(struct ifnet *, u_long, caddr_t); @@ -379,7 +385,57 @@ ure_ifmedia_upd(struct ifnet *ifp) { struct ure_softc *sc = ifp->if_softc; struct mii_data *mii = &sc->ure_mii; - int err; + struct ifmedia *ifm = &sc->ure_ifmedia; + int anar, gig, err, reg; + + if (sc->ure_flags & URE_FLAG_8156) { + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + + reg = ure_ocp_reg_read(sc, 0xa5d4); + reg &= ~URE_ADV_2500TFDX; + + anar = gig = 0; + switch (IFM_SUBTYPE(ifm->ifm_media)) { + case IFM_AUTO: + anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10; + gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX; + reg |= URE_ADV_2500TFDX; + break; + case IFM_2500_T: + anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10; + gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX; + reg |= URE_ADV_2500TFDX; + ifp->if_baudrate = IF_Mbps(2500); + break; + case IFM_1000_T: + anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10; + gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX; + ifp->if_baudrate = IF_Gbps(1); + break; + case IFM_100_TX: + anar |= ANAR_TX | ANAR_TX_FD; + ifp->if_baudrate = IF_Mbps(100); + break; + case IFM_10_T: + anar |= ANAR_10 | ANAR_10_FD; + ifp->if_baudrate = IF_Mbps(10); + break; + default: + printf("%s: unsupported media type\n", + sc->ure_dev.dv_xname); + return (EINVAL); + } + + ure_ocp_reg_write(sc, URE_OCP_BASE_MII + MII_ANAR * 2, + anar | ANAR_PAUSE_ASYM | ANAR_FC); + ure_ocp_reg_write(sc, URE_OCP_BASE_MII + MII_100T2CR * 2, gig); + ure_ocp_reg_write(sc, 0xa5d4, reg); + ure_ocp_reg_write(sc, URE_OCP_BASE_MII + MII_BMCR, + BMCR_AUTOEN | BMCR_STARTNEG); + + return (0); + } if (mii->mii_instance) { struct mii_softc *miisc; @@ -399,6 +455,30 @@ ure_ifmedia_sts(struct ifnet *ifp, struc { struct ure_softc *sc = ifp->if_softc; struct mii_data *mii = &sc->ure_mii; + uint16_t status = 0; + + if (sc->ure_flags & URE_FLAG_8156) { + ifmr->ifm_status = IFM_AVALID; + if (ure_get_link_status(sc)) { + ifmr->ifm_status |= IFM_ACTIVE; + status = ure_read_2(sc, URE_PLA_PHYSTATUS, + URE_MCU_TYPE_PLA); + if ((status & URE_PHYSTATUS_FDX) || + (status & URE_PHYSTATUS_2500MBPS)) + ifmr->ifm_active |= IFM_FDX; + else + ifmr->ifm_active |= IFM_HDX; + if (status & URE_PHYSTATUS_10MBPS) + ifmr->ifm_active |= IFM_10_T; + else if (status & URE_PHYSTATUS_100MBPS) + ifmr->ifm_active |= IFM_100_TX; + else if (status & URE_PHYSTATUS_1000MBPS) + ifmr->ifm_active |= IFM_1000_T; + else if (status & URE_PHYSTATUS_2500MBPS) + ifmr->ifm_active |= IFM_2500_T; + } + return; + } mii_pollstat(mii); ifmr->ifm_active = mii->mii_media_active; @@ -406,6 +486,50 @@ ure_ifmedia_sts(struct ifnet *ifp, struc } void +ure_add_media_types(struct ure_softc *sc) +{ + ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL); + ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL); + ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_100_TX, 0, NULL); + ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_100_TX | IFM_FDX, 0, + NULL); + ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_1000_T, 0, NULL); + ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_1000_T | IFM_FDX, 0, + NULL); + ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_2500_T, 0, NULL); + ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_2500_T | IFM_FDX, 0, + NULL); +} + +void +ure_link_state(struct ure_softc *sc) +{ + struct ifnet *ifp = &sc->ure_ac.ac_if; + int link = LINK_STATE_DOWN; + + if (ure_get_link_status(sc)) + link = LINK_STATE_UP; + + if (ifp->if_link_state != link) { + ifp->if_link_state = link; + if_link_state_change(ifp); + } +} + +int +ure_get_link_status(struct ure_softc *sc) +{ + if (ure_read_2(sc, URE_PLA_PHYSTATUS, URE_MCU_TYPE_PLA) & + URE_PHYSTATUS_LINK) { + sc->ure_flags |= URE_FLAG_LINK; + return (1); + } else { + sc->ure_flags &= ~URE_FLAG_LINK; + return (0); + } +} + +void ure_iff(struct ure_softc *sc) { struct ifnet *ifp = &sc->ure_ac.ac_if; @@ -465,11 +589,19 @@ ure_rxvlan(struct ure_softc *sc) struct ifnet *ifp = &sc->ure_ac.ac_if; uint16_t reg; - reg = ure_read_2(sc, URE_PLA_CPCR, URE_MCU_TYPE_PLA); - reg &= ~URE_CPCR_RX_VLAN; - if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) - reg |= URE_CPCR_RX_VLAN; - ure_write_2(sc, URE_PLA_CPCR, URE_MCU_TYPE_PLA, reg); + if (sc->ure_flags & URE_FLAG_8156) { + reg = ure_read_2(sc, 0xc012, URE_MCU_TYPE_PLA); + reg &= ~0x00c0; + if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) + reg |= 0x00c0; + ure_write_2(sc, 0xc012, URE_MCU_TYPE_PLA, reg); + } else { + reg = ure_read_2(sc, URE_PLA_CPCR, URE_MCU_TYPE_PLA); + reg &= ~URE_CPCR_RX_VLAN; + if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) + reg |= URE_CPCR_RX_VLAN; + ure_write_2(sc, URE_PLA_CPCR, URE_MCU_TYPE_PLA, reg); + } } void @@ -490,6 +622,27 @@ ure_reset(struct ure_softc *sc) } void +ure_watchdog(struct ifnet *ifp) +{ + struct ure_softc *sc = ifp->if_softc; + struct ure_chain *c; + usbd_status stat; + int s; + + ifp->if_oerrors++; + printf("%s: watchdog timeout\n", sc->ure_dev.dv_xname); + + s = splusb(); + c = &sc->ure_cdata.tx_chain[0]; + usbd_get_xfer_status(c->uc_xfer, NULL, NULL, NULL, &stat); + ure_txeof(c->uc_xfer, c, stat); + + if (!IFQ_IS_EMPTY(&ifp->if_snd)) + ure_start(ifp); + splx(s); +} + +void ure_init(void *xsc) { struct ure_softc *sc = xsc; @@ -528,16 +681,16 @@ ure_init(void *xsc) ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_NORAML); if (!(sc->ure_flags & URE_FLAG_8152)) { - reg = URE_BUFSZ - URE_FRAMELEN(ifp->if_mtu) - - sizeof(struct ure_rxpkt) - URE_RX_BUF_ALIGN; - if (sc->ure_flags & URE_FLAG_8153B) { + reg = sc->ure_rxbufsz - URE_FRAMELEN(ifp->if_mtu) + + sizeof(struct ure_rxpkt) + URE_RX_BUF_ALIGN; + if (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156)) { ure_write_2(sc, URE_USB_RX_EARLY_SIZE, URE_MCU_TYPE_USB, reg / 8); ure_write_2(sc, URE_USB_RX_EARLY_AGG, URE_MCU_TYPE_USB, - 16); + (sc->ure_flags & URE_FLAG_8153B) ? 16 : 80); ure_write_2(sc, URE_USB_PM_CTRL_STATUS, - URE_MCU_TYPE_USB, 15000); + URE_MCU_TYPE_USB, 1875); } else { ure_write_2(sc, URE_USB_RX_EARLY_SIZE, URE_MCU_TYPE_USB, reg / 4); @@ -564,7 +717,7 @@ ure_init(void *xsc) /* Enable transmit and receive. */ URE_SETBIT_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, URE_CR_RE | URE_CR_TE); - if (sc->ure_flags & URE_FLAG_8153B) { + if (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156)) { ure_write_1(sc, URE_USB_UPT_RXDMA_OWN, URE_MCU_TYPE_USB, URE_OWN_UPDATE | URE_OWN_CLEAR); } @@ -597,12 +750,14 @@ ure_init(void *xsc) for (i = 0; i < URE_RX_LIST_CNT; i++) { c = &sc->ure_cdata.rx_chain[i]; usbd_setup_xfer(c->uc_xfer, sc->ure_ep[URE_ENDPT_RX], - c, c->uc_buf, sc->ure_bufsz, + c, c->uc_buf, sc->ure_rxbufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, ure_rxeof); usbd_transfer(c->uc_xfer); } + ure_ifmedia_upd(ifp); + /* Indicate we are up and running. */ sc->ure_flags &= ~URE_FLAG_LINK; ifp->if_flags |= IFF_RUNNING; @@ -617,30 +772,41 @@ void ure_start(struct ifnet *ifp) { struct ure_softc *sc = ifp->if_softc; + struct ure_cdata *cd = &sc->ure_cdata; struct mbuf *m_head = NULL; + int idx; if ((sc->ure_flags & URE_FLAG_LINK) == 0 || ifq_is_oactive(&ifp->if_snd)) { return; } - m_head = ifq_deq_begin(&ifp->if_snd); - if (m_head == NULL) { - return; - } + idx = cd->tx_prod; - if (ure_encap(sc, m_head, 0)) { - ifq_deq_rollback(&ifp->if_snd, m_head); - ifq_set_oactive(&ifp->if_snd); - return; - } - ifq_deq_commit(&ifp->if_snd, m_head); + while (cd->tx_cnt < URE_TX_LIST_CNT) { + m_head = ifq_deq_begin(&ifp->if_snd); + if (m_head == NULL) + break; + + if (ure_encap(sc, m_head, idx)) { + ifq_deq_rollback(&ifp->if_snd, m_head); + ifq_set_oactive(&ifp->if_snd); + break; + } + ifq_deq_commit(&ifp->if_snd, m_head); #if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); #endif - ifq_set_oactive(&ifp->if_snd); + idx = (idx + 1) % URE_TX_LIST_CNT; + cd->tx_cnt++; + } + + cd->tx_prod = idx; + + if (cd->tx_cnt >= URE_TX_LIST_CNT) + ifq_set_oactive(&ifp->if_snd); } void @@ -672,6 +838,7 @@ ure_stop(struct ure_softc *sc) ifq_clr_oactive(&ifp->if_snd); timeout_del(&sc->ure_stat_ch); + sc->ure_flags &= ~URE_FLAG_LINK; if (sc->ure_ep[URE_ENDPT_RX] != NULL) { usbd_abort_pipe(sc->ure_ep[URE_ENDPT_RX]); @@ -714,8 +881,6 @@ ure_stop(struct ure_softc *sc) sc->ure_cdata.tx_chain[i].uc_xfer = NULL; } } - - sc->ure_flags &= ~URE_FLAG_LINK; } void @@ -852,7 +1017,14 @@ ure_rtl8153_init(struct ure_softc *sc) void ure_rtl8153b_init(struct ure_softc *sc) { - int i; + uint16_t reg; + int i; + + if (sc->ure_flags & URE_FLAG_8156) { + URE_CLRBIT_1(sc, 0xd26b, URE_MCU_TYPE_USB, 0x01); + ure_write_2(sc, 0xd32a, URE_MCU_TYPE_USB, 0); + URE_SETBIT_2(sc, 0xcfee, URE_MCU_TYPE_USB, 0x0020); + } URE_CLRBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB, LPM_U1U2_EN); @@ -883,8 +1055,12 @@ ure_rtl8153b_init(struct ure_softc *sc) URE_CLRBIT_1(sc, URE_USB_POWER_CUT, URE_MCU_TYPE_USB, URE_UPS_EN | URE_USP_PREWAKE); URE_CLRBIT_1(sc, 0xcfff, URE_MCU_TYPE_USB, 0x01); - URE_CLRBIT_2(sc, URE_USB_MISC_0, URE_MCU_TYPE_USB, URE_PCUT_STATUS); - ure_rtl8153_phy_status(sc, 0); + + if (!(sc->ure_flags & URE_FLAG_8156)) { + URE_CLRBIT_2(sc, URE_USB_MISC_0, URE_MCU_TYPE_USB, + URE_PCUT_STATUS); + ure_rtl8153_phy_status(sc, 0); + } URE_CLRBIT_1(sc, URE_PLA_INDICATE_FALG, URE_MCU_TYPE_PLA, URE_UPCOMING_RUNTIME_D3); @@ -901,13 +1077,34 @@ ure_rtl8153b_init(struct ure_softc *sc) URE_SETBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB, LPM_U1U2_EN); /* MAC clock speed down. */ - URE_SETBIT_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA, - URE_MAC_CLK_SPDWN_EN); + if (sc->ure_flags & URE_FLAG_8156) { + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA, 0x0403); + reg = ure_read_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA) & + ~0xff; + reg |= URE_MAC_CLK_SPDWN_EN | 0x0003; + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA, reg); + + URE_CLRBIT_2(sc, URE_PLA_MAC_PWR_CTRL3, URE_MCU_TYPE_PLA, + 0x4000); + + reg = ure_read_2(sc, URE_PLA_EXTRA_STATUS, URE_MCU_TYPE_PLA); + if (ure_get_link_status(sc)) + reg |= 0x8000; + else + reg &= ~0x8000; + reg |= 0x0001; + ure_write_2(sc, URE_PLA_EXTRA_STATUS, URE_MCU_TYPE_PLA, reg); + } else + URE_SETBIT_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA, + URE_MAC_CLK_SPDWN_EN); /* Enable Rx aggregation. */ URE_CLRBIT_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB, URE_RX_AGG_DISABLE | URE_RX_ZERO_EN); + if (sc->ure_flags & URE_FLAG_8156) + URE_SETBIT_1(sc, 0xcfd9, URE_MCU_TYPE_USB, 0x04); + URE_SETBIT_2(sc, URE_PLA_RSTTALLY, URE_MCU_TYPE_PLA, URE_TALLY_RESET); } @@ -994,7 +1191,7 @@ ure_rtl8153_nic_reset(struct ure_softc * uint8_t u1u2[8] = { 0 }; int i; - if (sc->ure_flags & URE_FLAG_8153B) { + if (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156)) { URE_CLRBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB, LPM_U1U2_EN); } else { @@ -1017,61 +1214,86 @@ ure_rtl8153_nic_reset(struct ure_softc * URE_UPS_FLAGS_EN_ALDPS); } - ure_write_2(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA, 0); - ure_write_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA, 0); - ure_write_2(sc, URE_PLA_MAC_PWR_CTRL3, URE_MCU_TYPE_PLA, 0); - ure_write_2(sc, URE_PLA_MAC_PWR_CTRL4, URE_MCU_TYPE_PLA, 0); + if (!(sc->ure_flags & URE_FLAG_8156)) { + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA, 0); + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA, 0); + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL3, URE_MCU_TYPE_PLA, 0); + ure_write_2(sc, URE_PLA_MAC_PWR_CTRL4, URE_MCU_TYPE_PLA, 0); + } URE_SETBIT_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA, URE_RXDY_GATED_EN); ure_disable_teredo(sc); URE_CLRBIT_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, URE_RCR_ACPT_ALL); - ure_reset(sc); + if (sc->ure_flags & URE_FLAG_8156) + ure_write_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, 0); + else + ure_reset(sc); + ure_reset_bmu(sc); URE_CLRBIT_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA, URE_NOW_IS_OOB); URE_CLRBIT_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; - usbd_delay_ms(sc->ure_udev, 1); - } - if (i == URE_TIMEOUT) - printf("%s: timeout waiting for OOB control\n", - sc->ure_dev.dv_xname); - URE_SETBIT_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; - usbd_delay_ms(sc->ure_udev, 1); - } - if (i == URE_TIMEOUT) - printf("%s: timeout waiting for OOB control\n", - sc->ure_dev.dv_xname); + if (!(sc->ure_flags & URE_FLAG_8156)) { + 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; + usbd_delay_ms(sc->ure_udev, 1); + } + if (i == URE_TIMEOUT) + printf("%s: timeout waiting for OOB control\n", + sc->ure_dev.dv_xname); + URE_SETBIT_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; + usbd_delay_ms(sc->ure_udev, 1); + } + if (i == URE_TIMEOUT) + printf("%s: timeout waiting for OOB control\n", + sc->ure_dev.dv_xname); + } ure_rxvlan(sc); ure_write_2(sc, URE_PLA_RMS, URE_MCU_TYPE_PLA, URE_FRAMELEN(ifp->if_mtu)); ure_write_1(sc, URE_PLA_MTPS, URE_MCU_TYPE_PLA, MTPS_JUMBO); - URE_SETBIT_2(sc, URE_PLA_TCR0, URE_MCU_TYPE_PLA, URE_TCR0_AUTO_FIFO); - ure_reset(sc); + if (!(sc->ure_flags & URE_FLAG_8156)) { + URE_SETBIT_2(sc, URE_PLA_TCR0, URE_MCU_TYPE_PLA, + URE_TCR0_AUTO_FIFO); + ure_reset(sc); + } /* Configure Rx FIFO threshold. */ - ure_write_4(sc, URE_PLA_RXFIFO_CTRL0, URE_MCU_TYPE_PLA, - URE_RXFIFO_THR1_NORMAL); - ure_write_2(sc, URE_PLA_RXFIFO_CTRL1, URE_MCU_TYPE_PLA, - URE_RXFIFO_THR2_NORMAL); - ure_write_2(sc, URE_PLA_RXFIFO_CTRL2, URE_MCU_TYPE_PLA, - URE_RXFIFO_THR3_NORMAL); + if (sc->ure_flags & URE_FLAG_8156) { + ure_write_2(sc, URE_PLA_RXFIFO_CTRL0 + 2, URE_MCU_TYPE_PLA, + 0x0008); + ure_write_2(sc, URE_PLA_RXFIFO_CTRL1 + 2, URE_MCU_TYPE_PLA, + 0x0100); + ure_write_2(sc, URE_PLA_RXFIFO_CTRL2, URE_MCU_TYPE_PLA, 0); + } else { + ure_write_4(sc, URE_PLA_RXFIFO_CTRL0, URE_MCU_TYPE_PLA, + URE_RXFIFO_THR1_NORMAL); + ure_write_2(sc, URE_PLA_RXFIFO_CTRL1, URE_MCU_TYPE_PLA, + URE_RXFIFO_THR2_NORMAL); + ure_write_2(sc, URE_PLA_RXFIFO_CTRL2, URE_MCU_TYPE_PLA, + URE_RXFIFO_THR3_NORMAL); + } /* Configure Tx FIFO threshold. */ ure_write_4(sc, URE_PLA_TXFIFO_CTRL, URE_MCU_TYPE_PLA, URE_TXFIFO_THR_NORMAL2); - if (sc->ure_flags & URE_FLAG_8153B) { + if (sc->ure_flags & URE_FLAG_8156) { + URE_CLRBIT_2(sc, URE_PLA_MAC_PWR_CTRL3, URE_MCU_TYPE_PLA, + 0x4000); + ure_write_4(sc, URE_USB_RX_BUF_TH, URE_MCU_TYPE_USB, + 0x00600400); + } else if (sc->ure_flags & URE_FLAG_8153B) { ure_write_4(sc, URE_USB_RX_BUF_TH, URE_MCU_TYPE_USB, URE_RX_THR_B); } @@ -1087,11 +1309,11 @@ ure_rtl8153_nic_reset(struct ure_softc * } if ((sc->ure_chip & (URE_CHIP_VER_5C20 | URE_CHIP_VER_5C30)) || - (sc->ure_flags & URE_FLAG_8153B)) + (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156))) URE_SETBIT_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, URE_U2P3_ENABLE); - if (sc->ure_flags & URE_FLAG_8153B) { + if (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156)) { URE_SETBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB, LPM_U1U2_EN); } else { @@ -1125,7 +1347,7 @@ ure_rtl8153_phy_status(struct ure_softc printf("%s: timeout waiting for phy to stabilize\n", sc->ure_dev.dv_xname); } - + void ure_reset_bmu(struct ure_softc *sc) { @@ -1138,7 +1360,7 @@ ure_reset_bmu(struct ure_softc *sc) void ure_disable_teredo(struct ure_softc *sc) { - if (sc->ure_flags & URE_FLAG_8153B) + if (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156)) ure_write_1(sc, URE_PLA_TEREDO_CFG, URE_MCU_TYPE_PLA, 0xff); else { URE_CLRBIT_2(sc, URE_PLA_TEREDO_CFG, URE_MCU_TYPE_PLA, @@ -1180,7 +1402,11 @@ ure_ioctl(struct ifnet *ifp, u_long cmd, case SIOCGIFMEDIA: case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->ure_mii.mii_media, cmd); + if (sc->ure_flags & URE_FLAG_8156) + error = ifmedia_ioctl(ifp, ifr, &sc->ure_ifmedia, cmd); + else + error = ifmedia_ioctl(ifp, ifr, &sc->ure_mii.mii_media, + cmd); break; default: @@ -1217,28 +1443,30 @@ ure_attach(struct device *parent, struct struct usb_attach_arg *uaa = aux; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; - struct mii_data *mii; u_char eaddr[8]; /* 4byte padded */ struct ifnet *ifp; - int i, mii_flags, s; + int i, mii_flags = 0, s; uint16_t ver; sc->ure_udev = uaa->device; sc->ure_iface = uaa->iface; - if (uaa->product == USB_PRODUCT_REALTEK_RTL8152) + if (uaa->product == USB_PRODUCT_REALTEK_RTL8152) { sc->ure_flags |= URE_FLAG_8152; + sc->ure_rxbufsz = URE_8152_RXBUFSZ; + } else if (uaa->product == USB_PRODUCT_REALTEK_RTL8156) { + sc->ure_flags |= URE_FLAG_8156; + sc->ure_rxbufsz = URE_8153_RXBUFSZ; + } else + sc->ure_rxbufsz = URE_8153_RXBUFSZ; usb_init_task(&sc->ure_tick_task, ure_tick_task, sc, USB_TASK_TYPE_GENERIC); - rw_init(&sc->ure_mii_lock, "uremii"); usb_init_task(&sc->ure_stop_task, (void (*)(void *))ure_stop, sc, USB_TASK_TYPE_GENERIC); id = usbd_get_interface_descriptor(sc->ure_iface); - sc->ure_bufsz = URE_BUFSZ; - for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->ure_iface, i); if (!ed) { @@ -1264,35 +1492,41 @@ ure_attach(struct device *parent, struct switch (ver) { case 0x4c00: sc->ure_chip |= URE_CHIP_VER_4C00; - printf("ver 4c00"); + printf("RTL8152 (0x4c00)"); break; case 0x4c10: sc->ure_chip |= URE_CHIP_VER_4C10; - printf("ver 4c10"); + printf("RTL8152 (0x4c10)"); break; case 0x5c00: sc->ure_chip |= URE_CHIP_VER_5C00; - printf("ver 5c00"); + printf("RTL8153 (0x5c00)"); break; case 0x5c10: sc->ure_chip |= URE_CHIP_VER_5C10; - printf("ver 5c10"); + printf("RTL8153 (0x5c10)"); break; case 0x5c20: sc->ure_chip |= URE_CHIP_VER_5C20; - printf("ver 5c20"); + printf("RTL8153 (0x5c20)"); break; case 0x5c30: sc->ure_chip |= URE_CHIP_VER_5C30; - printf("ver 5c30"); + printf("RTL8153 (0x5c30)"); break; case 0x6000: sc->ure_flags = URE_FLAG_8153B; - printf("ver 6000"); + printf("RTL8153B (0x6000)"); break; case 0x6010: sc->ure_flags = URE_FLAG_8153B; - printf("ver 6010"); + printf("RTL8153B (0x6010)"); + break; + case 0x7020: + printf("RTL8156 (0x7020)"); + break; + case 0x7030: + printf("RTL8156 (0x7030)"); break; default: printf(", unknown ver %02x", ver); @@ -1301,7 +1535,7 @@ ure_attach(struct device *parent, struct if (sc->ure_flags & URE_FLAG_8152) ure_rtl8152_init(sc); - else if (sc->ure_flags & URE_FLAG_8153B) + else if (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156)) ure_rtl8153b_init(sc); else ure_rtl8153_init(sc); @@ -1323,27 +1557,40 @@ ure_attach(struct device *parent, struct ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = ure_ioctl; ifp->if_start = ure_start; + ifp->if_watchdog = ure_watchdog; ifp->if_capabilities = 0; - mii = &sc->ure_mii; - mii->mii_ifp = ifp; - mii->mii_readreg = ure_miibus_readreg; - mii->mii_writereg = ure_miibus_writereg; - mii->mii_statchg = ure_miibus_statchg; - mii->mii_flags = MIIF_AUTOTSLEEP; - - ifmedia_init(&mii->mii_media, 0, ure_ifmedia_upd, ure_ifmedia_sts); - mii_flags = 0; - if (!(sc->ure_flags & URE_FLAG_8152)) - mii_flags |= MIIF_DOPAUSE; - mii_attach(self, mii, 0xffffffff, sc->ure_phyno, MII_OFFSET_ANY, - mii_flags); - - if (LIST_FIRST(&mii->mii_phys) == NULL) { - ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); - ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); - } else - ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); + if (sc->ure_flags & URE_FLAG_8156) { + ifmedia_init(&sc->ure_ifmedia, IFM_IMASK, ure_ifmedia_upd, + ure_ifmedia_sts); + ure_add_media_types(sc); + ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL); + ifmedia_set(&sc->ure_ifmedia, IFM_ETHER | IFM_AUTO); + sc->ure_ifmedia.ifm_media = sc->ure_ifmedia.ifm_cur->ifm_media; + } else { + rw_init(&sc->ure_mii_lock, "uremii"); + + sc->ure_mii.mii_ifp = ifp; + sc->ure_mii.mii_readreg = ure_miibus_readreg; + sc->ure_mii.mii_writereg = ure_miibus_writereg; + sc->ure_mii.mii_statchg = ure_miibus_statchg; + sc->ure_mii.mii_flags = MIIF_AUTOTSLEEP; + + ifmedia_init(&sc->ure_mii.mii_media, 0, ure_ifmedia_upd, + ure_ifmedia_sts); + if (!(sc->ure_flags & URE_FLAG_8152)) + mii_flags |= MIIF_DOPAUSE; + mii_attach(self, &sc->ure_mii, 0xffffffff, sc->ure_phyno, + MII_OFFSET_ANY, mii_flags); + if (LIST_FIRST(&sc->ure_mii.mii_phys) == NULL) { + ifmedia_add(&sc->ure_mii.mii_media, + IFM_ETHER | IFM_NONE, 0, NULL); + ifmedia_set(&sc->ure_mii.mii_media, + IFM_ETHER | IFM_NONE); + } else + ifmedia_set(&sc->ure_mii.mii_media, + IFM_ETHER | IFM_AUTO); + } if_attach(ifp); ether_ifattach(ifp); @@ -1407,9 +1654,13 @@ ure_tick_task(void *xsc) mii = &sc->ure_mii; s = splnet(); - mii_tick(mii); - if ((sc->ure_flags & URE_FLAG_LINK) == 0) - ure_miibus_statchg(&sc->ure_dev); + if (sc->ure_flags & URE_FLAG_8156) + ure_link_state(sc); + else { + mii_tick(mii); + if ((sc->ure_flags & URE_FLAG_LINK) == 0) + ure_miibus_statchg(&sc->ure_dev); + } timeout_add_sec(&sc->ure_stat_ch, 1); splx(s); } @@ -1457,7 +1708,8 @@ ure_rxeof(struct usbd_xfer *xfer, void * sc->ure_dev.dv_xname, usbd_errstr(status)); } if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->ure_ep[URE_ENDPT_RX]); + usbd_clear_endpoint_stall_async( + sc->ure_ep[URE_ENDPT_RX]); goto done; } @@ -1501,10 +1753,10 @@ done: s = splnet(); if_input(ifp, &ml); splx(s); - memset(c->uc_buf, 0, sc->ure_bufsz); + memset(c->uc_buf, 0, sc->ure_rxbufsz); usbd_setup_xfer(xfer, sc->ure_ep[URE_ENDPT_RX], c, c->uc_buf, - sc->ure_bufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY, + sc->ure_rxbufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, ure_rxeof); usbd_transfer(xfer); } @@ -1515,12 +1767,14 @@ ure_txeof(struct usbd_xfer *xfer, void * { struct ure_softc *sc; struct ure_chain *c; + struct ure_cdata *cd; struct ifnet *ifp; int s; c = priv; sc = c->uc_sc; ifp = &sc->ure_ac.ac_if; + cd = &sc->ure_cdata; if (usbd_is_dying(sc->ure_udev)) return; @@ -1529,6 +1783,7 @@ ure_txeof(struct usbd_xfer *xfer, void * s = splnet(); + cd->tx_cnt--; if (status != USBD_NORMAL_COMPLETION) { if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { splx(s); @@ -1538,7 +1793,8 @@ ure_txeof(struct usbd_xfer *xfer, void * printf("%s: usb error on tx: %s\n", sc->ure_dev.dv_xname, usbd_errstr(status)); if (status == USBD_STALLED) - usbd_clear_endpoint_stall_async(sc->ure_ep[URE_ENDPT_TX]); + usbd_clear_endpoint_stall_async( + sc->ure_ep[URE_ENDPT_TX]); splx(s); return; } @@ -1553,7 +1809,6 @@ ure_txeof(struct usbd_xfer *xfer, void * ure_start(ifp); splx(s); - } int @@ -1573,8 +1828,7 @@ ure_tx_list_init(struct ure_softc *sc) c->uc_xfer = usbd_alloc_xfer(sc->ure_udev); if (c->uc_xfer == NULL) return ENOBUFS; - c->uc_buf = usbd_alloc_buffer(c->uc_xfer, - sc->ure_bufsz); + c->uc_buf = usbd_alloc_buffer(c->uc_xfer, URE_TXBUFSZ); if (c->uc_buf == NULL) { usbd_free_xfer(c->uc_xfer); return ENOBUFS; @@ -1582,7 +1836,9 @@ ure_tx_list_init(struct ure_softc *sc) } } - return 0; + cd->tx_prod = cd->tx_cnt = 0; + + return (0); } int @@ -1603,7 +1859,7 @@ ure_rx_list_init(struct ure_softc *sc) if (c->uc_xfer == NULL) return ENOBUFS; c->uc_buf = usbd_alloc_buffer(c->uc_xfer, - sc->ure_bufsz); + sc->ure_rxbufsz); if (c->uc_buf == NULL) { usbd_free_xfer(c->uc_xfer); return ENOBUFS; @@ -1611,7 +1867,7 @@ ure_rx_list_init(struct ure_softc *sc) } } - return 0; + return (0); } int @@ -1621,21 +1877,18 @@ ure_encap(struct ure_softc *sc, struct m usbd_status err; struct ure_txpkt txhdr; uint32_t frm_len = 0; - u_char *buf; c = &sc->ure_cdata.tx_chain[idx]; - buf = c->uc_buf; /* header */ htolem32(&txhdr.ure_pktlen, m->m_pkthdr.len | URE_TXPKT_TX_FS | URE_TXPKT_TX_LS); txhdr.ure_rsvd0 = 0; - memcpy(buf, &txhdr, sizeof(txhdr)); - buf += sizeof(txhdr); + memcpy(c->uc_buf, &txhdr, sizeof(txhdr)); frm_len = sizeof(txhdr); /* packet */ - m_copydata(m, 0, m->m_pkthdr.len, buf); + m_copydata(m, 0, m->m_pkthdr.len, c->uc_buf + frm_len); frm_len += m->m_pkthdr.len; c->uc_mbuf = m; @@ -1647,9 +1900,8 @@ ure_encap(struct ure_softc *sc, struct m err = usbd_transfer(c->uc_xfer); if (err != USBD_IN_PROGRESS) { ure_stop(sc); - return EIO; + return (EIO); } - sc->ure_cdata.tx_cnt++; - return 0; + return (0); } Index: sys/dev/usb/if_urereg.h =================================================================== RCS file: /cvs/src/sys/dev/usb/if_urereg.h,v retrieving revision 1.7 diff -u -p -u -p -r1.7 if_urereg.h --- sys/dev/usb/if_urereg.h 29 Aug 2019 08:55:06 -0000 1.7 +++ sys/dev/usb/if_urereg.h 3 Dec 2019 08:29:41 -0000 @@ -41,10 +41,10 @@ #define URE_BYTE_EN_BYTE 0x11 #define URE_BYTE_EN_SIX_BYTES 0x3f -#define URE_FRAMELEN(mtu) \ +#define URE_FRAMELEN(mtu) \ (mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN) -#define URE_JUMBO_FRAMELEN (9 * 1024) -#define URE_JUMBO_MTU \ +#define URE_JUMBO_FRAMELEN (9 * 1024) +#define URE_JUMBO_MTU \ (URE_JUMBO_FRAMELEN - ETHER_HDR_LEN - ETHER_CRC_LEN - \ ETHER_VLAN_ENCAP_LEN) @@ -310,6 +310,14 @@ /* URE_PLA_EXTRA_STATUS */ #define URE_LINK_CHANGE_FLAG 0x0100 +/* URE_PLA_PHYSTATUS */ +#define URE_PHYSTATUS_FDX 0x0001 +#define URE_PHYSTATUS_LINK 0x0002 +#define URE_PHYSTATUS_10MBPS 0x0004 +#define URE_PHYSTATUS_100MBPS 0x0008 +#define URE_PHYSTATUS_1000MBPS 0x0010 +#define URE_PHYSTATUS_2500MBPS 0x0400 + /* URE_USB_USB2PHY */ #define URE_USB2PHY_SUSPEND 0x0001 #define URE_USB2PHY_L1 0x0002 @@ -432,6 +440,8 @@ #define URE_ADC_EN 0x0080 #define URE_CKADSEL_L 0x0100 +#define URE_ADV_2500TFDX 0x0080 + #define URE_MCU_TYPE_PLA 0x0100 #define URE_MCU_TYPE_USB 0x0000 @@ -470,11 +480,13 @@ struct ure_txpkt { #define URE_ENDPT_TX 1 #define URE_ENDPT_MAX 2 -#define URE_TX_LIST_CNT 1 +#define URE_TX_LIST_CNT 4 #define URE_RX_LIST_CNT 1 #define URE_RX_BUF_ALIGN sizeof(uint64_t) -#define URE_BUFSZ 16384 +#define URE_TXBUFSZ 16384 +#define URE_8152_RXBUFSZ 16384 +#define URE_8153_RXBUFSZ 32768 struct ure_chain { struct ure_softc *uc_sc; @@ -489,9 +501,7 @@ struct ure_cdata { struct ure_chain tx_chain[URE_TX_LIST_CNT]; struct ure_chain rx_chain[URE_RX_LIST_CNT]; int tx_prod; - int tx_const; int tx_cnt; - int rx_prod; }; struct ure_softc { @@ -508,6 +518,7 @@ struct ure_softc { /* ethernet */ struct arpcom ure_ac; struct mii_data ure_mii; + struct ifmedia ure_ifmedia; struct rwlock ure_mii_lock; int ure_refcnt; @@ -515,7 +526,7 @@ struct ure_softc { struct timeout ure_stat_ch; struct timeval ure_rx_notice; - int ure_bufsz; + int ure_rxbufsz; int ure_phyno; @@ -523,6 +534,7 @@ struct ure_softc { #define URE_FLAG_LINK 0x0001 #define URE_FLAG_8152 0x1000 /* RTL8152 */ #define URE_FLAG_8153B 0x2000 /* RTL8153B */ +#define URE_FLAG_8156 0x4000 /* RTL8156 */ u_int ure_chip; #define URE_CHIP_VER_4C00 0x01 Index: sys/dev/usb/usbdevs =================================================================== RCS file: /cvs/src/sys/dev/usb/usbdevs,v retrieving revision 1.701 diff -u -p -u -p -r1.701 usbdevs --- sys/dev/usb/usbdevs 27 Aug 2019 17:59:58 -0000 1.701 +++ sys/dev/usb/usbdevs 3 Dec 2019 08:29:41 -0000 @@ -3597,6 +3597,7 @@ product REALTEK RTL8150 0x8150 RTL8150 product REALTEK RTL8151 0x8151 RTL8151 PNA product REALTEK RTL8152 0x8152 RTL8152 product REALTEK RTL8153 0x8153 RTL8153 +product REALTEK RTL8156 0x8156 RTL8156 product REALTEK RTL8188CE_0 0x8170 RTL8188CE product REALTEK RTL8171 0x8171 RTL8171 product REALTEK RTL8172 0x8172 RTL8172