1*81508fe3Sjsg /* $OpenBSD: if_ure.c,v 1.35 2024/05/23 03:21:09 jsg Exp $ */
242c54c93Sjmatthew /*-
355929a15Skevlo * Copyright (c) 2015, 2016, 2019 Kevin Lo <kevlo@openbsd.org>
4fd07ab7eSkevlo * Copyright (c) 2020 Jonathon Fletcher <jonathon.fletcher@gmail.com>
542c54c93Sjmatthew * All rights reserved.
642c54c93Sjmatthew *
742c54c93Sjmatthew * Redistribution and use in source and binary forms, with or without
842c54c93Sjmatthew * modification, are permitted provided that the following conditions
942c54c93Sjmatthew * are met:
1042c54c93Sjmatthew * 1. Redistributions of source code must retain the above copyright
1142c54c93Sjmatthew * notice, this list of conditions and the following disclaimer.
1242c54c93Sjmatthew * 2. Redistributions in binary form must reproduce the above copyright
1342c54c93Sjmatthew * notice, this list of conditions and the following disclaimer in the
1442c54c93Sjmatthew * documentation and/or other materials provided with the distribution.
1542c54c93Sjmatthew *
1642c54c93Sjmatthew * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1742c54c93Sjmatthew * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1842c54c93Sjmatthew * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1942c54c93Sjmatthew * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2042c54c93Sjmatthew * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2142c54c93Sjmatthew * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2242c54c93Sjmatthew * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2342c54c93Sjmatthew * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2442c54c93Sjmatthew * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2542c54c93Sjmatthew * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2642c54c93Sjmatthew * SUCH DAMAGE.
2742c54c93Sjmatthew */
2842c54c93Sjmatthew
2942c54c93Sjmatthew #include "bpfilter.h"
30c096a1a3Skevlo #include "vlan.h"
3142c54c93Sjmatthew
3242c54c93Sjmatthew #include <sys/param.h>
3342c54c93Sjmatthew #include <sys/systm.h>
3442c54c93Sjmatthew #include <sys/sockio.h>
3542c54c93Sjmatthew #include <sys/rwlock.h>
3642c54c93Sjmatthew #include <sys/mbuf.h>
3742c54c93Sjmatthew #include <sys/device.h>
3842c54c93Sjmatthew
3942c54c93Sjmatthew #include <machine/bus.h>
4042c54c93Sjmatthew
4142c54c93Sjmatthew #include <net/if.h>
4242c54c93Sjmatthew #include <net/if_media.h>
4342c54c93Sjmatthew
4442c54c93Sjmatthew #if NBPFILTER > 0
4542c54c93Sjmatthew #include <net/bpf.h>
4642c54c93Sjmatthew #endif
4742c54c93Sjmatthew
4842c54c93Sjmatthew #include <netinet/in.h>
4942c54c93Sjmatthew #include <netinet/if_ether.h>
5042c54c93Sjmatthew
51c096a1a3Skevlo #include <dev/mii/mii.h>
5242c54c93Sjmatthew #include <dev/mii/miivar.h>
5342c54c93Sjmatthew
5442c54c93Sjmatthew #include <dev/usb/usb.h>
5542c54c93Sjmatthew #include <dev/usb/usbdi.h>
5642c54c93Sjmatthew #include <dev/usb/usbdi_util.h>
5742c54c93Sjmatthew #include <dev/usb/usbdivar.h>
5842c54c93Sjmatthew #include <dev/usb/usbdevs.h>
5942c54c93Sjmatthew
60794a317fSkettenis #include <dev/ic/rtl81x9reg.h>
61794a317fSkettenis #include <dev/usb/if_urereg.h>
6242c54c93Sjmatthew
6342c54c93Sjmatthew #ifdef URE_DEBUG
6442c54c93Sjmatthew #define DPRINTF(x) do { if (uredebug) printf x; } while (0)
6542c54c93Sjmatthew #define DPRINTFN(n,x) do { if (uredebug >= (n)) printf x; } while (0)
6642c54c93Sjmatthew int uredebug = 0;
6742c54c93Sjmatthew #else
6842c54c93Sjmatthew #define DPRINTF(x)
6942c54c93Sjmatthew #define DPRINTFN(n,x)
7042c54c93Sjmatthew #endif
7142c54c93Sjmatthew
7242c54c93Sjmatthew const struct usb_devno ure_devs[] = {
7311bacf69Sjsg { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RTL8156 },
7411bacf69Sjsg { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_RTL8152B },
7511bacf69Sjsg { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_RTL8153 },
7611bacf69Sjsg { USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_USB3GIGV1 },
7711bacf69Sjsg { USB_VENDOR_CLEVO, USB_PRODUCT_CLEVO_RTL8153B },
7811bacf69Sjsg { USB_VENDOR_CLUB3D, USB_PRODUCT_CLUB3D_RTL8153 },
7911bacf69Sjsg { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_RTL8153_1 },
8011bacf69Sjsg { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_RTL8153_2 },
8111bacf69Sjsg { USB_VENDOR_DYNABOOK, USB_PRODUCT_DYNABOOK_RTL8153B_1 },
8211bacf69Sjsg { USB_VENDOR_DYNABOOK, USB_PRODUCT_DYNABOOK_RTL8153B_2 },
8311bacf69Sjsg { USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_RTL8153B },
8411bacf69Sjsg { USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_RTL8156B },
8511bacf69Sjsg { USB_VENDOR_IOI, USB_PRODUCT_IOI_RTL8153 },
860a68adefSjcs { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_DOCK_ETHERNET },
8711bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_ONELINK },
8811bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_ONELINKPLUS },
8911bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_ONELINKPRO },
9011bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153B_1 },
9111bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153B_2 },
9211bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153B_3 },
9311bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153B_4 },
9411bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153B_5 },
9511bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153B_6 },
9611bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153B_7 },
9711bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153B_8 },
9811bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153B_9 },
9911bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153_1 },
10011bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153_2 },
10111bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_RTL8153_3 },
10211bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_TABLETDOCK },
10311bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_TB3DOCK },
10411bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_TB3DOCKGEN2 },
10511bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_TB3GFXDOCK },
10611bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_USBCDOCKGEN2 },
10711bacf69Sjsg { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_WIGIGDOCK },
10811bacf69Sjsg { USB_VENDOR_LG, USB_PRODUCT_LG_RTL8153 },
10911bacf69Sjsg { USB_VENDOR_LG, USB_PRODUCT_LG_RTL8153B },
11011bacf69Sjsg { USB_VENDOR_LUXSHARE, USB_PRODUCT_LUXSHARE_RTL8153 },
11111bacf69Sjsg { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_DOCKETH },
11211bacf69Sjsg { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_DOCKETH2 },
11311bacf69Sjsg { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_SURFETH },
1140e1617aaSpatrick { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WINDEVETH },
11511bacf69Sjsg { USB_VENDOR_NVIDIA, USB_PRODUCT_NVIDIA_TEGRAETH },
11611bacf69Sjsg { USB_VENDOR_PIONEERDJ, USB_PRODUCT_PIONEERDJ_RTL8152B },
11711bacf69Sjsg { USB_VENDOR_PIONEERDJ, USB_PRODUCT_PIONEERDJ_RTL8153B },
118794a317fSkettenis { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8152 },
11911bacf69Sjsg { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8152B },
120c096a1a3Skevlo { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8153 },
121d19edd3aSkevlo { USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8156 },
12211bacf69Sjsg { USB_VENDOR_SAMSUNG2, USB_PRODUCT_SAMSUNG2_RTL8153 },
12311bacf69Sjsg { USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_RTL8153B },
12411bacf69Sjsg { USB_VENDOR_TPLINK, USB_PRODUCT_TPLINK_EU300 },
12511bacf69Sjsg { USB_VENDOR_TPLINK, USB_PRODUCT_TPLINK_RTL8152B_1 },
12611bacf69Sjsg { USB_VENDOR_TPLINK, USB_PRODUCT_TPLINK_RTL8152B_2 },
12711bacf69Sjsg { USB_VENDOR_TRENDNET, USB_PRODUCT_TRENDNET_RTL8156 },
12811bacf69Sjsg { USB_VENDOR_TTL, USB_PRODUCT_TTL_RTL8153 },
12911bacf69Sjsg { USB_VENDOR_TWINHEAD, USB_PRODUCT_TWINHEAD_RTL8153B },
13011bacf69Sjsg { USB_VENDOR_XIAOMI, USB_PRODUCT_XIAOMI_RTL8152B },
13142c54c93Sjmatthew };
13242c54c93Sjmatthew
13342c54c93Sjmatthew int ure_match(struct device *, void *, void *);
13442c54c93Sjmatthew void ure_attach(struct device *, struct device *, void *);
13542c54c93Sjmatthew int ure_detach(struct device *, int);
13642c54c93Sjmatthew
13742c54c93Sjmatthew struct cfdriver ure_cd = {
13842c54c93Sjmatthew NULL, "ure", DV_IFNET
13942c54c93Sjmatthew };
14042c54c93Sjmatthew
14142c54c93Sjmatthew const struct cfattach ure_ca = {
14242c54c93Sjmatthew sizeof(struct ure_softc), ure_match, ure_attach, ure_detach
14342c54c93Sjmatthew };
14442c54c93Sjmatthew
14542c54c93Sjmatthew int ure_ctl(struct ure_softc *, uint8_t, uint16_t, uint16_t,
14642c54c93Sjmatthew void *, int);
14742c54c93Sjmatthew int ure_read_mem(struct ure_softc *, uint16_t, uint16_t, void *,
14842c54c93Sjmatthew int);
14942c54c93Sjmatthew int ure_write_mem(struct ure_softc *, uint16_t, uint16_t, void *,
15042c54c93Sjmatthew int);
15142c54c93Sjmatthew uint8_t ure_read_1(struct ure_softc *, uint16_t, uint16_t);
15242c54c93Sjmatthew uint16_t ure_read_2(struct ure_softc *, uint16_t, uint16_t);
15342c54c93Sjmatthew uint32_t ure_read_4(struct ure_softc *, uint16_t, uint16_t);
15442c54c93Sjmatthew int ure_write_1(struct ure_softc *, uint16_t, uint16_t, uint32_t);
15542c54c93Sjmatthew int ure_write_2(struct ure_softc *, uint16_t, uint16_t, uint32_t);
15642c54c93Sjmatthew int ure_write_4(struct ure_softc *, uint16_t, uint16_t, uint32_t);
15742c54c93Sjmatthew uint16_t ure_ocp_reg_read(struct ure_softc *, uint16_t);
15842c54c93Sjmatthew void ure_ocp_reg_write(struct ure_softc *, uint16_t, uint16_t);
15942c54c93Sjmatthew
16042c54c93Sjmatthew void ure_init(void *);
16142c54c93Sjmatthew void ure_stop(struct ure_softc *);
16242c54c93Sjmatthew void ure_start(struct ifnet *);
16342c54c93Sjmatthew void ure_reset(struct ure_softc *);
164c096a1a3Skevlo void ure_watchdog(struct ifnet *);
16542c54c93Sjmatthew
16642c54c93Sjmatthew void ure_miibus_statchg(struct device *);
16742c54c93Sjmatthew int ure_miibus_readreg(struct device *, int, int);
16842c54c93Sjmatthew void ure_miibus_writereg(struct device *, int, int, int);
16942c54c93Sjmatthew void ure_lock_mii(struct ure_softc *);
17042c54c93Sjmatthew void ure_unlock_mii(struct ure_softc *);
17142c54c93Sjmatthew
172fd07ab7eSkevlo int ure_encap_txpkt(struct mbuf *, char *, uint32_t);
173fd07ab7eSkevlo int ure_encap_xfer(struct ifnet *, struct ure_softc *,
174fd07ab7eSkevlo struct ure_chain *);
17542c54c93Sjmatthew void ure_rxeof(struct usbd_xfer *, void *, usbd_status);
17642c54c93Sjmatthew void ure_txeof(struct usbd_xfer *, void *, usbd_status);
177fd07ab7eSkevlo int ure_xfer_list_init(struct ure_softc *, struct ure_chain *,
178fd07ab7eSkevlo uint32_t, int);
179fd07ab7eSkevlo void ure_xfer_list_free(struct ure_softc *, struct ure_chain *, int);
18042c54c93Sjmatthew
18142c54c93Sjmatthew void ure_tick_task(void *);
18242c54c93Sjmatthew void ure_tick(void *);
18342c54c93Sjmatthew
184c0ad8833Smglocker void ure_ifmedia_init(struct ifnet *);
18542c54c93Sjmatthew int ure_ifmedia_upd(struct ifnet *);
18642c54c93Sjmatthew void ure_ifmedia_sts(struct ifnet *, struct ifmediareq *);
187c096a1a3Skevlo void ure_add_media_types(struct ure_softc *);
188c096a1a3Skevlo void ure_link_state(struct ure_softc *);
189c096a1a3Skevlo int ure_get_link_status(struct ure_softc *);
19055929a15Skevlo void ure_iff(struct ure_softc *);
19155929a15Skevlo void ure_rxvlan(struct ure_softc *);
19242c54c93Sjmatthew int ure_ioctl(struct ifnet *, u_long, caddr_t);
19342c54c93Sjmatthew void ure_rtl8152_init(struct ure_softc *);
194794a317fSkettenis void ure_rtl8153_init(struct ure_softc *);
19555929a15Skevlo void ure_rtl8153b_init(struct ure_softc *);
19655929a15Skevlo void ure_rtl8152_nic_reset(struct ure_softc *);
19755929a15Skevlo void ure_rtl8153_nic_reset(struct ure_softc *);
1988a3a1b1fSkevlo uint16_t ure_rtl8153_phy_status(struct ure_softc *, int);
1998a3a1b1fSkevlo void ure_wait_for_flash(struct ure_softc *);
20055929a15Skevlo void ure_reset_bmu(struct ure_softc *);
20142c54c93Sjmatthew void ure_disable_teredo(struct ure_softc *);
20242c54c93Sjmatthew
20355929a15Skevlo #define URE_SETBIT_1(sc, reg, index, x) \
20455929a15Skevlo ure_write_1(sc, reg, index, ure_read_1(sc, reg, index) | (x))
20555929a15Skevlo #define URE_SETBIT_2(sc, reg, index, x) \
20655929a15Skevlo ure_write_2(sc, reg, index, ure_read_2(sc, reg, index) | (x))
20755929a15Skevlo #define URE_SETBIT_4(sc, reg, index, x) \
20855929a15Skevlo ure_write_4(sc, reg, index, ure_read_4(sc, reg, index) | (x))
20942c54c93Sjmatthew
21055929a15Skevlo #define URE_CLRBIT_1(sc, reg, index, x) \
21155929a15Skevlo ure_write_1(sc, reg, index, ure_read_1(sc, reg, index) & ~(x))
21255929a15Skevlo #define URE_CLRBIT_2(sc, reg, index, x) \
21355929a15Skevlo ure_write_2(sc, reg, index, ure_read_2(sc, reg, index) & ~(x))
21455929a15Skevlo #define URE_CLRBIT_4(sc, reg, index, x) \
21555929a15Skevlo ure_write_4(sc, reg, index, ure_read_4(sc, reg, index) & ~(x))
21642c54c93Sjmatthew
21742c54c93Sjmatthew int
ure_ctl(struct ure_softc * sc,uint8_t rw,uint16_t val,uint16_t index,void * buf,int len)21842c54c93Sjmatthew ure_ctl(struct ure_softc *sc, uint8_t rw, uint16_t val, uint16_t index,
21942c54c93Sjmatthew void *buf, int len)
22042c54c93Sjmatthew {
22142c54c93Sjmatthew usb_device_request_t req;
22242c54c93Sjmatthew usbd_status err;
22342c54c93Sjmatthew
22442c54c93Sjmatthew if (usbd_is_dying(sc->ure_udev))
225ca35d093Skevlo return 0;
22642c54c93Sjmatthew
22742c54c93Sjmatthew if (rw == URE_CTL_WRITE)
22842c54c93Sjmatthew req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
22942c54c93Sjmatthew else
23042c54c93Sjmatthew req.bmRequestType = UT_READ_VENDOR_DEVICE;
23142c54c93Sjmatthew req.bRequest = UR_SET_ADDRESS;
23242c54c93Sjmatthew USETW(req.wValue, val);
23342c54c93Sjmatthew USETW(req.wIndex, index);
23442c54c93Sjmatthew USETW(req.wLength, len);
23542c54c93Sjmatthew
23642c54c93Sjmatthew DPRINTFN(5, ("ure_ctl: rw %d, val 0x%04hu, index 0x%04hu, len %d\n",
23742c54c93Sjmatthew rw, val, index, len));
23842c54c93Sjmatthew err = usbd_do_request(sc->ure_udev, &req, buf);
23942c54c93Sjmatthew if (err) {
24042c54c93Sjmatthew DPRINTF(("ure_ctl: error %d\n", err));
24142c54c93Sjmatthew return -1;
24242c54c93Sjmatthew }
24342c54c93Sjmatthew
24442c54c93Sjmatthew return 0;
24542c54c93Sjmatthew }
24642c54c93Sjmatthew
24742c54c93Sjmatthew int
ure_read_mem(struct ure_softc * sc,uint16_t addr,uint16_t index,void * buf,int len)24842c54c93Sjmatthew ure_read_mem(struct ure_softc *sc, uint16_t addr, uint16_t index,
24942c54c93Sjmatthew void *buf, int len)
25042c54c93Sjmatthew {
25142c54c93Sjmatthew return (ure_ctl(sc, URE_CTL_READ, addr, index, buf, len));
25242c54c93Sjmatthew }
25342c54c93Sjmatthew
25442c54c93Sjmatthew int
ure_write_mem(struct ure_softc * sc,uint16_t addr,uint16_t index,void * buf,int len)25542c54c93Sjmatthew ure_write_mem(struct ure_softc *sc, uint16_t addr, uint16_t index,
25642c54c93Sjmatthew void *buf, int len)
25742c54c93Sjmatthew {
25842c54c93Sjmatthew return (ure_ctl(sc, URE_CTL_WRITE, addr, index, buf, len));
25942c54c93Sjmatthew }
26042c54c93Sjmatthew
26142c54c93Sjmatthew uint8_t
ure_read_1(struct ure_softc * sc,uint16_t reg,uint16_t index)26242c54c93Sjmatthew ure_read_1(struct ure_softc *sc, uint16_t reg, uint16_t index)
26342c54c93Sjmatthew {
26442c54c93Sjmatthew uint32_t val;
26542c54c93Sjmatthew uint8_t temp[4];
26642c54c93Sjmatthew uint8_t shift;
26742c54c93Sjmatthew
26842c54c93Sjmatthew shift = (reg & 3) << 3;
26942c54c93Sjmatthew reg &= ~3;
27042c54c93Sjmatthew
27142c54c93Sjmatthew ure_read_mem(sc, reg, index, &temp, 4);
27242c54c93Sjmatthew val = UGETDW(temp);
27342c54c93Sjmatthew val >>= shift;
27442c54c93Sjmatthew
27542c54c93Sjmatthew return (val & 0xff);
27642c54c93Sjmatthew }
27742c54c93Sjmatthew
27842c54c93Sjmatthew uint16_t
ure_read_2(struct ure_softc * sc,uint16_t reg,uint16_t index)27942c54c93Sjmatthew ure_read_2(struct ure_softc *sc, uint16_t reg, uint16_t index)
28042c54c93Sjmatthew {
28142c54c93Sjmatthew uint32_t val;
28242c54c93Sjmatthew uint8_t temp[4];
28342c54c93Sjmatthew uint8_t shift;
28442c54c93Sjmatthew
28542c54c93Sjmatthew shift = (reg & 2) << 3;
28642c54c93Sjmatthew reg &= ~3;
28742c54c93Sjmatthew
28842c54c93Sjmatthew ure_read_mem(sc, reg, index, &temp, 4);
28942c54c93Sjmatthew val = UGETDW(temp);
29042c54c93Sjmatthew val >>= shift;
29142c54c93Sjmatthew
29242c54c93Sjmatthew return (val & 0xffff);
29342c54c93Sjmatthew }
29442c54c93Sjmatthew
29542c54c93Sjmatthew uint32_t
ure_read_4(struct ure_softc * sc,uint16_t reg,uint16_t index)29642c54c93Sjmatthew ure_read_4(struct ure_softc *sc, uint16_t reg, uint16_t index)
29742c54c93Sjmatthew {
29842c54c93Sjmatthew uint8_t temp[4];
29942c54c93Sjmatthew
30042c54c93Sjmatthew ure_read_mem(sc, reg, index, &temp, 4);
30142c54c93Sjmatthew return (UGETDW(temp));
30242c54c93Sjmatthew }
30342c54c93Sjmatthew
30442c54c93Sjmatthew int
ure_write_1(struct ure_softc * sc,uint16_t reg,uint16_t index,uint32_t val)30542c54c93Sjmatthew ure_write_1(struct ure_softc *sc, uint16_t reg, uint16_t index, uint32_t val)
30642c54c93Sjmatthew {
30742c54c93Sjmatthew uint16_t byen;
30842c54c93Sjmatthew uint8_t temp[4];
30942c54c93Sjmatthew uint8_t shift;
31042c54c93Sjmatthew
31142c54c93Sjmatthew byen = URE_BYTE_EN_BYTE;
31242c54c93Sjmatthew shift = reg & 3;
31342c54c93Sjmatthew val &= 0xff;
31442c54c93Sjmatthew
31542c54c93Sjmatthew if (reg & 3) {
31642c54c93Sjmatthew byen <<= shift;
31742c54c93Sjmatthew val <<= (shift << 3);
31842c54c93Sjmatthew reg &= ~3;
31942c54c93Sjmatthew }
32042c54c93Sjmatthew
32142c54c93Sjmatthew USETDW(temp, val);
32242c54c93Sjmatthew return (ure_write_mem(sc, reg, index | byen, &temp, 4));
32342c54c93Sjmatthew }
32442c54c93Sjmatthew
32542c54c93Sjmatthew int
ure_write_2(struct ure_softc * sc,uint16_t reg,uint16_t index,uint32_t val)32642c54c93Sjmatthew ure_write_2(struct ure_softc *sc, uint16_t reg, uint16_t index, uint32_t val)
32742c54c93Sjmatthew {
32842c54c93Sjmatthew uint16_t byen;
32942c54c93Sjmatthew uint8_t temp[4];
33042c54c93Sjmatthew uint8_t shift;
33142c54c93Sjmatthew
33242c54c93Sjmatthew byen = URE_BYTE_EN_WORD;
33342c54c93Sjmatthew shift = reg & 2;
33442c54c93Sjmatthew val &= 0xffff;
33542c54c93Sjmatthew
33642c54c93Sjmatthew if (reg & 2) {
33742c54c93Sjmatthew byen <<= shift;
33842c54c93Sjmatthew val <<= (shift << 3);
33942c54c93Sjmatthew reg &= ~3;
34042c54c93Sjmatthew }
34142c54c93Sjmatthew
34242c54c93Sjmatthew USETDW(temp, val);
34342c54c93Sjmatthew return (ure_write_mem(sc, reg, index | byen, &temp, 4));
34442c54c93Sjmatthew }
34542c54c93Sjmatthew
34642c54c93Sjmatthew int
ure_write_4(struct ure_softc * sc,uint16_t reg,uint16_t index,uint32_t val)34742c54c93Sjmatthew ure_write_4(struct ure_softc *sc, uint16_t reg, uint16_t index, uint32_t val)
34842c54c93Sjmatthew {
34942c54c93Sjmatthew uint8_t temp[4];
35042c54c93Sjmatthew
35142c54c93Sjmatthew USETDW(temp, val);
35242c54c93Sjmatthew return (ure_write_mem(sc, reg, index | URE_BYTE_EN_DWORD, &temp, 4));
35342c54c93Sjmatthew }
35442c54c93Sjmatthew
35542c54c93Sjmatthew uint16_t
ure_ocp_reg_read(struct ure_softc * sc,uint16_t addr)35642c54c93Sjmatthew ure_ocp_reg_read(struct ure_softc *sc, uint16_t addr)
35742c54c93Sjmatthew {
35842c54c93Sjmatthew uint16_t reg;
35942c54c93Sjmatthew
36042c54c93Sjmatthew ure_write_2(sc, URE_PLA_OCP_GPHY_BASE, URE_MCU_TYPE_PLA, addr & 0xf000);
36142c54c93Sjmatthew reg = (addr & 0x0fff) | 0xb000;
36242c54c93Sjmatthew
36342c54c93Sjmatthew return (ure_read_2(sc, reg, URE_MCU_TYPE_PLA));
36442c54c93Sjmatthew }
36542c54c93Sjmatthew
36642c54c93Sjmatthew void
ure_ocp_reg_write(struct ure_softc * sc,uint16_t addr,uint16_t data)36742c54c93Sjmatthew ure_ocp_reg_write(struct ure_softc *sc, uint16_t addr, uint16_t data)
36842c54c93Sjmatthew {
36942c54c93Sjmatthew uint16_t reg;
37042c54c93Sjmatthew
37142c54c93Sjmatthew ure_write_2(sc, URE_PLA_OCP_GPHY_BASE, URE_MCU_TYPE_PLA, addr & 0xf000);
37242c54c93Sjmatthew reg = (addr & 0x0fff) | 0xb000;
37342c54c93Sjmatthew
37442c54c93Sjmatthew ure_write_2(sc, reg, URE_MCU_TYPE_PLA, data);
37542c54c93Sjmatthew }
37642c54c93Sjmatthew
37742c54c93Sjmatthew int
ure_miibus_readreg(struct device * dev,int phy,int reg)37842c54c93Sjmatthew ure_miibus_readreg(struct device *dev, int phy, int reg)
37942c54c93Sjmatthew {
38042c54c93Sjmatthew struct ure_softc *sc = (void *)dev;
38142c54c93Sjmatthew uint16_t val;
38242c54c93Sjmatthew
38342c54c93Sjmatthew if (usbd_is_dying(sc->ure_udev))
38442c54c93Sjmatthew return 0;
38542c54c93Sjmatthew
386794a317fSkettenis /* Let the rgephy driver read the URE_PLA_PHYSTATUS register. */
387794a317fSkettenis if (reg == RL_GMEDIASTAT)
388794a317fSkettenis return ure_read_1(sc, URE_PLA_PHYSTATUS, URE_MCU_TYPE_PLA);
389794a317fSkettenis
39042c54c93Sjmatthew ure_lock_mii(sc);
39142c54c93Sjmatthew val = ure_ocp_reg_read(sc, URE_OCP_BASE_MII + reg * 2);
39242c54c93Sjmatthew ure_unlock_mii(sc);
39342c54c93Sjmatthew
39442c54c93Sjmatthew return val; /* letoh16? */
39542c54c93Sjmatthew }
39642c54c93Sjmatthew
39742c54c93Sjmatthew void
ure_miibus_writereg(struct device * dev,int phy,int reg,int val)39842c54c93Sjmatthew ure_miibus_writereg(struct device *dev, int phy, int reg, int val)
39942c54c93Sjmatthew {
40042c54c93Sjmatthew struct ure_softc *sc = (void *)dev;
40142c54c93Sjmatthew
40242c54c93Sjmatthew ure_lock_mii(sc);
40342c54c93Sjmatthew ure_ocp_reg_write(sc, URE_OCP_BASE_MII + reg * 2, val); /* htole16? */
40442c54c93Sjmatthew ure_unlock_mii(sc);
40542c54c93Sjmatthew }
40642c54c93Sjmatthew
40742c54c93Sjmatthew void
ure_miibus_statchg(struct device * dev)40842c54c93Sjmatthew ure_miibus_statchg(struct device *dev)
40942c54c93Sjmatthew {
41042c54c93Sjmatthew struct ure_softc *sc = (void *)dev;
41142c54c93Sjmatthew struct mii_data *mii = &sc->ure_mii;
41242c54c93Sjmatthew struct ifnet *ifp = &sc->ure_ac.ac_if;
41342c54c93Sjmatthew
41442c54c93Sjmatthew if ((ifp->if_flags & IFF_RUNNING) == 0)
41542c54c93Sjmatthew return;
41642c54c93Sjmatthew
41742c54c93Sjmatthew sc->ure_flags &= ~URE_FLAG_LINK;
41842c54c93Sjmatthew if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
41942c54c93Sjmatthew (IFM_ACTIVE | IFM_AVALID)) {
42042c54c93Sjmatthew switch (IFM_SUBTYPE(mii->mii_media_active)) {
42142c54c93Sjmatthew case IFM_10_T:
42242c54c93Sjmatthew case IFM_100_TX:
42342c54c93Sjmatthew sc->ure_flags |= URE_FLAG_LINK;
42442c54c93Sjmatthew break;
425794a317fSkettenis case IFM_1000_T:
426794a317fSkettenis if ((sc->ure_flags & URE_FLAG_8152) != 0)
427794a317fSkettenis break;
428794a317fSkettenis sc->ure_flags |= URE_FLAG_LINK;
429794a317fSkettenis break;
43042c54c93Sjmatthew default:
43142c54c93Sjmatthew break;
43242c54c93Sjmatthew }
43342c54c93Sjmatthew }
43455929a15Skevlo
43555929a15Skevlo /* Lost link, do nothing. */
43655929a15Skevlo if ((sc->ure_flags & URE_FLAG_LINK) == 0)
43755929a15Skevlo return;
438c0ad8833Smglocker
439c0ad8833Smglocker /*
440c0ad8833Smglocker * After a link change the media settings are getting reset on the
441c0ad8833Smglocker * hardware, and need to be re-initialized again for communication
442c0ad8833Smglocker * to continue work.
443c0ad8833Smglocker */
444c0ad8833Smglocker ure_ifmedia_init(ifp);
445c0ad8833Smglocker }
446c0ad8833Smglocker
447c0ad8833Smglocker void
ure_ifmedia_init(struct ifnet * ifp)448c0ad8833Smglocker ure_ifmedia_init(struct ifnet *ifp)
449c0ad8833Smglocker {
450c0ad8833Smglocker struct ure_softc *sc = ifp->if_softc;
451c0ad8833Smglocker uint32_t reg = 0;
452c0ad8833Smglocker
453c0ad8833Smglocker /* Set MAC address. */
454c0ad8833Smglocker ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_CONFIG);
455c0ad8833Smglocker ure_write_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA | URE_BYTE_EN_SIX_BYTES,
456c0ad8833Smglocker sc->ure_ac.ac_enaddr, 8);
457c0ad8833Smglocker ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_NORAML);
458c0ad8833Smglocker
459c0ad8833Smglocker if (!(sc->ure_flags & URE_FLAG_8152)) {
4608a3a1b1fSkevlo if (sc->ure_flags & URE_FLAG_8156B)
4618a3a1b1fSkevlo URE_CLRBIT_2(sc, URE_USB_RX_AGGR_NUM, URE_MCU_TYPE_USB,
4628a3a1b1fSkevlo URE_RX_AGGR_NUM_MASK);
4638a3a1b1fSkevlo
464c0ad8833Smglocker reg = sc->ure_rxbufsz - URE_FRAMELEN(ifp->if_mtu) -
465c0ad8833Smglocker sizeof(struct ure_rxpkt) - URE_RX_BUF_ALIGN;
4663dd6ed5fSkevlo if (sc->ure_flags &
4673dd6ed5fSkevlo (URE_FLAG_8153B | URE_FLAG_8156 | URE_FLAG_8156B)) {
468c0ad8833Smglocker ure_write_2(sc, URE_USB_RX_EARLY_SIZE, URE_MCU_TYPE_USB,
469c0ad8833Smglocker reg / 8);
470c0ad8833Smglocker
471c0ad8833Smglocker ure_write_2(sc, URE_USB_RX_EARLY_AGG, URE_MCU_TYPE_USB,
4728a3a1b1fSkevlo (sc->ure_flags & URE_FLAG_8153B) ? 158 : 80);
473c0ad8833Smglocker ure_write_2(sc, URE_USB_PM_CTRL_STATUS,
474c0ad8833Smglocker URE_MCU_TYPE_USB, 1875);
475c0ad8833Smglocker } else {
476c0ad8833Smglocker ure_write_2(sc, URE_USB_RX_EARLY_SIZE, URE_MCU_TYPE_USB,
477c0ad8833Smglocker reg / 4);
478c0ad8833Smglocker switch (sc->ure_udev->speed) {
479c0ad8833Smglocker case USB_SPEED_SUPER:
480c0ad8833Smglocker reg = URE_COALESCE_SUPER / 8;
481c0ad8833Smglocker break;
482c0ad8833Smglocker case USB_SPEED_HIGH:
483c0ad8833Smglocker reg = URE_COALESCE_HIGH / 8;
484c0ad8833Smglocker break;
485c0ad8833Smglocker default:
486c0ad8833Smglocker reg = URE_COALESCE_SLOW / 8;
487c0ad8833Smglocker break;
488c0ad8833Smglocker }
489c0ad8833Smglocker ure_write_2(sc, URE_USB_RX_EARLY_AGG, URE_MCU_TYPE_USB,
490c0ad8833Smglocker reg);
491c0ad8833Smglocker }
4928a3a1b1fSkevlo
4933dd6ed5fSkevlo if (sc->ure_chip & URE_CHIP_VER_7420) {
4943dd6ed5fSkevlo URE_SETBIT_2(sc, URE_PLA_MAC_PWR_CTRL4,
4953dd6ed5fSkevlo URE_MCU_TYPE_PLA, URE_IDLE_SPDWN_EN);
4963dd6ed5fSkevlo }
4973dd6ed5fSkevlo
4988a3a1b1fSkevlo if ((sc->ure_chip & URE_CHIP_VER_6010) ||
4998a3a1b1fSkevlo (sc->ure_flags & URE_FLAG_8156B)) {
5008a3a1b1fSkevlo URE_CLRBIT_2(sc, URE_USB_FW_TASK, URE_MCU_TYPE_USB,
5018a3a1b1fSkevlo URE_FC_PATCH_TASK);
5028a3a1b1fSkevlo usbd_delay_ms(sc->ure_udev, 1);
5038a3a1b1fSkevlo URE_SETBIT_2(sc, URE_USB_FW_TASK, URE_MCU_TYPE_USB,
5048a3a1b1fSkevlo URE_FC_PATCH_TASK);
5058a3a1b1fSkevlo }
506c0ad8833Smglocker }
507c0ad8833Smglocker
508c0ad8833Smglocker /* Reset the packet filter. */
509c0ad8833Smglocker URE_CLRBIT_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA, URE_FMC_FCR_MCU_EN);
510c0ad8833Smglocker URE_SETBIT_2(sc, URE_PLA_FMC, URE_MCU_TYPE_PLA, URE_FMC_FCR_MCU_EN);
511c0ad8833Smglocker
512c0ad8833Smglocker /* Enable transmit and receive. */
513c0ad8833Smglocker URE_SETBIT_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, URE_CR_RE | URE_CR_TE);
514c0ad8833Smglocker
5158a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156 | URE_FLAG_8156B)) {
516c0ad8833Smglocker ure_write_1(sc, URE_USB_UPT_RXDMA_OWN, URE_MCU_TYPE_USB,
517c0ad8833Smglocker URE_OWN_UPDATE | URE_OWN_CLEAR);
518c0ad8833Smglocker }
519c0ad8833Smglocker
520c0ad8833Smglocker URE_CLRBIT_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA, URE_RXDY_GATED_EN);
52142c54c93Sjmatthew }
52242c54c93Sjmatthew
52342c54c93Sjmatthew int
ure_ifmedia_upd(struct ifnet * ifp)52442c54c93Sjmatthew ure_ifmedia_upd(struct ifnet *ifp)
52542c54c93Sjmatthew {
52642c54c93Sjmatthew struct ure_softc *sc = ifp->if_softc;
52742c54c93Sjmatthew struct mii_data *mii = &sc->ure_mii;
528c096a1a3Skevlo struct ifmedia *ifm = &sc->ure_ifmedia;
529c096a1a3Skevlo int anar, gig, err, reg;
530c096a1a3Skevlo
5318a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B)) {
532c096a1a3Skevlo if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
533c096a1a3Skevlo return (EINVAL);
534c096a1a3Skevlo
5353dd6ed5fSkevlo if (!(sc->ure_chip & URE_CHIP_VER_7420)) {
5363dd6ed5fSkevlo reg = ure_ocp_reg_read(sc, URE_OCP_10GBT_CTRL);
537c096a1a3Skevlo reg &= ~URE_ADV_2500TFDX;
5383dd6ed5fSkevlo }
539c096a1a3Skevlo
540c096a1a3Skevlo anar = gig = 0;
541c096a1a3Skevlo switch (IFM_SUBTYPE(ifm->ifm_media)) {
542c096a1a3Skevlo case IFM_AUTO:
543c096a1a3Skevlo anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
544c096a1a3Skevlo gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
5453dd6ed5fSkevlo if (!(sc->ure_chip & URE_CHIP_VER_7420))
546c096a1a3Skevlo reg |= URE_ADV_2500TFDX;
547c096a1a3Skevlo break;
548c096a1a3Skevlo case IFM_2500_T:
549c096a1a3Skevlo anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
550c096a1a3Skevlo gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
551c096a1a3Skevlo reg |= URE_ADV_2500TFDX;
552c096a1a3Skevlo ifp->if_baudrate = IF_Mbps(2500);
553c096a1a3Skevlo break;
554c096a1a3Skevlo case IFM_1000_T:
555c096a1a3Skevlo anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10;
556c096a1a3Skevlo gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
557c096a1a3Skevlo ifp->if_baudrate = IF_Gbps(1);
558c096a1a3Skevlo break;
559c096a1a3Skevlo case IFM_100_TX:
560c096a1a3Skevlo anar |= ANAR_TX | ANAR_TX_FD;
561c096a1a3Skevlo ifp->if_baudrate = IF_Mbps(100);
562c096a1a3Skevlo break;
563c096a1a3Skevlo case IFM_10_T:
564c096a1a3Skevlo anar |= ANAR_10 | ANAR_10_FD;
565c096a1a3Skevlo ifp->if_baudrate = IF_Mbps(10);
566c096a1a3Skevlo break;
567c096a1a3Skevlo default:
568c096a1a3Skevlo printf("%s: unsupported media type\n",
569c096a1a3Skevlo sc->ure_dev.dv_xname);
570c096a1a3Skevlo return (EINVAL);
571c096a1a3Skevlo }
572c096a1a3Skevlo
573c096a1a3Skevlo ure_ocp_reg_write(sc, URE_OCP_BASE_MII + MII_ANAR * 2,
574c096a1a3Skevlo anar | ANAR_PAUSE_ASYM | ANAR_FC);
575c096a1a3Skevlo ure_ocp_reg_write(sc, URE_OCP_BASE_MII + MII_100T2CR * 2, gig);
5763dd6ed5fSkevlo if (!(sc->ure_chip & URE_CHIP_VER_7420))
5773dd6ed5fSkevlo ure_ocp_reg_write(sc, URE_OCP_10GBT_CTRL, reg);
578c096a1a3Skevlo ure_ocp_reg_write(sc, URE_OCP_BASE_MII + MII_BMCR,
579c096a1a3Skevlo BMCR_AUTOEN | BMCR_STARTNEG);
580c096a1a3Skevlo
581c096a1a3Skevlo return (0);
582c096a1a3Skevlo }
58342c54c93Sjmatthew
58442c54c93Sjmatthew if (mii->mii_instance) {
58542c54c93Sjmatthew struct mii_softc *miisc;
58642c54c93Sjmatthew LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
58742c54c93Sjmatthew PHY_RESET(miisc);
58842c54c93Sjmatthew }
58942c54c93Sjmatthew
59042c54c93Sjmatthew err = mii_mediachg(mii);
59142c54c93Sjmatthew if (err == ENXIO)
59255929a15Skevlo return (0);
59342c54c93Sjmatthew else
59455929a15Skevlo return (err);
59542c54c93Sjmatthew }
59642c54c93Sjmatthew
59742c54c93Sjmatthew void
ure_ifmedia_sts(struct ifnet * ifp,struct ifmediareq * ifmr)59842c54c93Sjmatthew ure_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
59942c54c93Sjmatthew {
60042c54c93Sjmatthew struct ure_softc *sc = ifp->if_softc;
60142c54c93Sjmatthew struct mii_data *mii = &sc->ure_mii;
602c096a1a3Skevlo uint16_t status = 0;
603c096a1a3Skevlo
6048a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B)) {
605c096a1a3Skevlo ifmr->ifm_status = IFM_AVALID;
606c096a1a3Skevlo if (ure_get_link_status(sc)) {
607c096a1a3Skevlo ifmr->ifm_status |= IFM_ACTIVE;
608c096a1a3Skevlo status = ure_read_2(sc, URE_PLA_PHYSTATUS,
609c096a1a3Skevlo URE_MCU_TYPE_PLA);
610c096a1a3Skevlo if ((status & URE_PHYSTATUS_FDX) ||
611c096a1a3Skevlo (status & URE_PHYSTATUS_2500MBPS))
612c096a1a3Skevlo ifmr->ifm_active |= IFM_FDX;
613c096a1a3Skevlo else
614c096a1a3Skevlo ifmr->ifm_active |= IFM_HDX;
615c096a1a3Skevlo if (status & URE_PHYSTATUS_10MBPS)
616c096a1a3Skevlo ifmr->ifm_active |= IFM_10_T;
617c096a1a3Skevlo else if (status & URE_PHYSTATUS_100MBPS)
618c096a1a3Skevlo ifmr->ifm_active |= IFM_100_TX;
619c096a1a3Skevlo else if (status & URE_PHYSTATUS_1000MBPS)
620c096a1a3Skevlo ifmr->ifm_active |= IFM_1000_T;
621c096a1a3Skevlo else if (status & URE_PHYSTATUS_2500MBPS)
622c096a1a3Skevlo ifmr->ifm_active |= IFM_2500_T;
623c096a1a3Skevlo }
624c096a1a3Skevlo return;
625c096a1a3Skevlo }
62642c54c93Sjmatthew
62742c54c93Sjmatthew mii_pollstat(mii);
62842c54c93Sjmatthew ifmr->ifm_active = mii->mii_media_active;
62942c54c93Sjmatthew ifmr->ifm_status = mii->mii_media_status;
63042c54c93Sjmatthew }
63142c54c93Sjmatthew
63242c54c93Sjmatthew void
ure_add_media_types(struct ure_softc * sc)633c096a1a3Skevlo ure_add_media_types(struct ure_softc *sc)
634c096a1a3Skevlo {
635c096a1a3Skevlo ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL);
636c096a1a3Skevlo ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL);
637c096a1a3Skevlo ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_100_TX, 0, NULL);
638c096a1a3Skevlo ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_100_TX | IFM_FDX, 0,
639c096a1a3Skevlo NULL);
640c096a1a3Skevlo ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_1000_T, 0, NULL);
641c096a1a3Skevlo ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_1000_T | IFM_FDX, 0,
642c096a1a3Skevlo NULL);
6433dd6ed5fSkevlo if (!(sc->ure_chip & URE_CHIP_VER_7420)) {
644c096a1a3Skevlo ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_2500_T, 0, NULL);
6453dd6ed5fSkevlo ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_2500_T | IFM_FDX,
6463dd6ed5fSkevlo 0, NULL);
6473dd6ed5fSkevlo }
648c096a1a3Skevlo }
649c096a1a3Skevlo
650c096a1a3Skevlo void
ure_link_state(struct ure_softc * sc)651c096a1a3Skevlo ure_link_state(struct ure_softc *sc)
652c096a1a3Skevlo {
653c096a1a3Skevlo struct ifnet *ifp = &sc->ure_ac.ac_if;
654c096a1a3Skevlo int link = LINK_STATE_DOWN;
655c096a1a3Skevlo
656c096a1a3Skevlo if (ure_get_link_status(sc))
657c096a1a3Skevlo link = LINK_STATE_UP;
658c096a1a3Skevlo
659c096a1a3Skevlo if (ifp->if_link_state != link) {
660c096a1a3Skevlo ifp->if_link_state = link;
661c096a1a3Skevlo if_link_state_change(ifp);
662c096a1a3Skevlo }
663c096a1a3Skevlo }
664c096a1a3Skevlo
665c096a1a3Skevlo int
ure_get_link_status(struct ure_softc * sc)666c096a1a3Skevlo ure_get_link_status(struct ure_softc *sc)
667c096a1a3Skevlo {
668c096a1a3Skevlo if (ure_read_2(sc, URE_PLA_PHYSTATUS, URE_MCU_TYPE_PLA) &
669c096a1a3Skevlo URE_PHYSTATUS_LINK) {
670c096a1a3Skevlo sc->ure_flags |= URE_FLAG_LINK;
671c096a1a3Skevlo return (1);
672c096a1a3Skevlo } else {
673c096a1a3Skevlo sc->ure_flags &= ~URE_FLAG_LINK;
674c096a1a3Skevlo return (0);
675c096a1a3Skevlo }
676c096a1a3Skevlo }
677c096a1a3Skevlo
678c096a1a3Skevlo void
ure_iff(struct ure_softc * sc)67942c54c93Sjmatthew ure_iff(struct ure_softc *sc)
68042c54c93Sjmatthew {
68142c54c93Sjmatthew struct ifnet *ifp = &sc->ure_ac.ac_if;
68242c54c93Sjmatthew struct ether_multi *enm;
68342c54c93Sjmatthew struct ether_multistep step;
68442c54c93Sjmatthew uint32_t hashes[2] = { 0, 0 };
68542c54c93Sjmatthew uint32_t hash;
68642c54c93Sjmatthew uint32_t rxmode;
68742c54c93Sjmatthew
68842c54c93Sjmatthew if (usbd_is_dying(sc->ure_udev))
68942c54c93Sjmatthew return;
69042c54c93Sjmatthew
69170646515Sjmatthew rxmode = ure_read_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA);
69270646515Sjmatthew rxmode &= ~URE_RCR_ACPT_ALL;
69342c54c93Sjmatthew ifp->if_flags &= ~IFF_ALLMULTI;
69470646515Sjmatthew
69570646515Sjmatthew /*
69670646515Sjmatthew * Always accept frames destined to our station address.
69770646515Sjmatthew * Always accept broadcast frames.
69870646515Sjmatthew */
69970646515Sjmatthew rxmode |= URE_RCR_APM | URE_RCR_AB;
70070646515Sjmatthew
70142c54c93Sjmatthew if (ifp->if_flags & IFF_PROMISC || sc->ure_ac.ac_multirangecnt > 0) {
70242c54c93Sjmatthew ifp->if_flags |= IFF_ALLMULTI;
70370646515Sjmatthew rxmode |= URE_RCR_AM;
70442c54c93Sjmatthew if (ifp->if_flags & IFF_PROMISC)
70542c54c93Sjmatthew rxmode |= URE_RCR_AAP;
70642c54c93Sjmatthew hashes[0] = hashes[1] = 0xffffffff;
70742c54c93Sjmatthew } else {
70870646515Sjmatthew rxmode |= URE_RCR_AM;
70970646515Sjmatthew
71042c54c93Sjmatthew ETHER_FIRST_MULTI(step, &sc->ure_ac, enm);
71142c54c93Sjmatthew while (enm != NULL) {
71242c54c93Sjmatthew hash = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN)
71342c54c93Sjmatthew >> 26;
71442c54c93Sjmatthew if (hash < 32)
71542c54c93Sjmatthew hashes[0] |= (1 << hash);
71642c54c93Sjmatthew else
71742c54c93Sjmatthew hashes[1] |= (1 << (hash - 32));
71842c54c93Sjmatthew
71942c54c93Sjmatthew ETHER_NEXT_MULTI(step, enm);
72042c54c93Sjmatthew }
72142c54c93Sjmatthew
72242c54c93Sjmatthew hash = swap32(hashes[0]);
72342c54c93Sjmatthew hashes[0] = swap32(hashes[1]);
72442c54c93Sjmatthew hashes[1] = hash;
72542c54c93Sjmatthew }
72642c54c93Sjmatthew
72755929a15Skevlo ure_write_mem(sc, URE_PLA_MAR, URE_MCU_TYPE_PLA | URE_BYTE_EN_DWORD,
72855929a15Skevlo hashes, sizeof(hashes));
72942c54c93Sjmatthew ure_write_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, rxmode);
73042c54c93Sjmatthew }
73142c54c93Sjmatthew
73242c54c93Sjmatthew void
ure_rxvlan(struct ure_softc * sc)73355929a15Skevlo ure_rxvlan(struct ure_softc *sc)
73455929a15Skevlo {
73555929a15Skevlo struct ifnet *ifp = &sc->ure_ac.ac_if;
73655929a15Skevlo uint16_t reg;
73755929a15Skevlo
7388a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B)) {
7398a3a1b1fSkevlo reg = ure_read_2(sc, URE_PLA_RCR1, URE_MCU_TYPE_PLA);
7408a3a1b1fSkevlo reg &= ~(URE_INNER_VLAN | URE_OUTER_VLAN);
741c096a1a3Skevlo if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING)
7428a3a1b1fSkevlo reg |= (URE_INNER_VLAN | URE_OUTER_VLAN);
7438a3a1b1fSkevlo ure_write_2(sc, URE_PLA_RCR1, URE_MCU_TYPE_PLA, reg);
744c096a1a3Skevlo } else {
74555929a15Skevlo reg = ure_read_2(sc, URE_PLA_CPCR, URE_MCU_TYPE_PLA);
74655929a15Skevlo reg &= ~URE_CPCR_RX_VLAN;
74755929a15Skevlo if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING)
74855929a15Skevlo reg |= URE_CPCR_RX_VLAN;
74955929a15Skevlo ure_write_2(sc, URE_PLA_CPCR, URE_MCU_TYPE_PLA, reg);
75055929a15Skevlo }
751c096a1a3Skevlo }
75255929a15Skevlo
75355929a15Skevlo void
ure_reset(struct ure_softc * sc)75442c54c93Sjmatthew ure_reset(struct ure_softc *sc)
75542c54c93Sjmatthew {
75642c54c93Sjmatthew int i;
75742c54c93Sjmatthew
7588a3a1b1fSkevlo if (sc->ure_flags & URE_FLAG_8156) {
7598a3a1b1fSkevlo URE_CLRBIT_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, URE_CR_TE);
7608a3a1b1fSkevlo URE_CLRBIT_2(sc, URE_USB_BMU_RESET, URE_MCU_TYPE_USB,
7618a3a1b1fSkevlo BMU_RESET_EP_IN);
7628a3a1b1fSkevlo URE_SETBIT_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB,
7638a3a1b1fSkevlo URE_CDC_ECM_EN);
7648a3a1b1fSkevlo URE_CLRBIT_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, URE_CR_RE);
7658a3a1b1fSkevlo URE_SETBIT_2(sc, URE_USB_BMU_RESET, URE_MCU_TYPE_USB,
7668a3a1b1fSkevlo BMU_RESET_EP_IN);
7678a3a1b1fSkevlo URE_CLRBIT_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB,
7688a3a1b1fSkevlo URE_CDC_ECM_EN);
7698a3a1b1fSkevlo } else {
77042c54c93Sjmatthew ure_write_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, URE_CR_RST);
77142c54c93Sjmatthew
77242c54c93Sjmatthew for (i = 0; i < URE_TIMEOUT; i++) {
77342c54c93Sjmatthew if (!(ure_read_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA) &
77442c54c93Sjmatthew URE_CR_RST))
77542c54c93Sjmatthew break;
77655929a15Skevlo DELAY(100);
77742c54c93Sjmatthew }
77842c54c93Sjmatthew if (i == URE_TIMEOUT)
7798a3a1b1fSkevlo printf("%s: reset never completed\n",
7808a3a1b1fSkevlo sc->ure_dev.dv_xname);
7818a3a1b1fSkevlo }
78242c54c93Sjmatthew }
78342c54c93Sjmatthew
78442c54c93Sjmatthew void
ure_watchdog(struct ifnet * ifp)785c096a1a3Skevlo ure_watchdog(struct ifnet *ifp)
786c096a1a3Skevlo {
787c096a1a3Skevlo struct ure_softc *sc = ifp->if_softc;
788fd07ab7eSkevlo struct ure_chain *c;
789fd07ab7eSkevlo usbd_status err;
790fd07ab7eSkevlo int i, s;
791fd07ab7eSkevlo
792fd07ab7eSkevlo ifp->if_timer = 0;
793c096a1a3Skevlo
794c096a1a3Skevlo if (usbd_is_dying(sc->ure_udev))
795c096a1a3Skevlo return;
796c096a1a3Skevlo
797fd07ab7eSkevlo if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP))
798fd07ab7eSkevlo return;
799fd07ab7eSkevlo
800fd07ab7eSkevlo sc = ifp->if_softc;
801fd07ab7eSkevlo s = splnet();
802fd07ab7eSkevlo
803c096a1a3Skevlo ifp->if_oerrors++;
804fd07ab7eSkevlo DPRINTF(("%s: watchdog timeout\n", sc->ure_dev.dv_xname));
805fd07ab7eSkevlo
806fd07ab7eSkevlo for (i = 0; i < URE_TX_LIST_CNT; i++) {
807fd07ab7eSkevlo c = &sc->ure_cdata.ure_tx_chain[i];
808fd07ab7eSkevlo if (c->uc_cnt > 0) {
809fd07ab7eSkevlo usbd_get_xfer_status(c->uc_xfer, NULL, NULL, NULL,
810fd07ab7eSkevlo &err);
811fd07ab7eSkevlo ure_txeof(c->uc_xfer, c, err);
812fd07ab7eSkevlo }
813fd07ab7eSkevlo }
814fd07ab7eSkevlo
815fd07ab7eSkevlo if (ifq_is_oactive(&ifp->if_snd))
816fd07ab7eSkevlo ifq_restart(&ifp->if_snd);
817fd07ab7eSkevlo splx(s);
818c096a1a3Skevlo }
819c096a1a3Skevlo
820c096a1a3Skevlo void
ure_init(void * xsc)82142c54c93Sjmatthew ure_init(void *xsc)
82242c54c93Sjmatthew {
82342c54c93Sjmatthew struct ure_softc *sc = xsc;
82442c54c93Sjmatthew struct ure_chain *c;
82542c54c93Sjmatthew struct ifnet *ifp = &sc->ure_ac.ac_if;
82642c54c93Sjmatthew usbd_status err;
82742c54c93Sjmatthew int s, i;
82842c54c93Sjmatthew
82942c54c93Sjmatthew s = splnet();
83042c54c93Sjmatthew
83142c54c93Sjmatthew /* Cancel pending I/O. */
83242c54c93Sjmatthew ure_stop(sc);
83342c54c93Sjmatthew
83455929a15Skevlo if (sc->ure_flags & URE_FLAG_8152)
83555929a15Skevlo ure_rtl8152_nic_reset(sc);
83655929a15Skevlo else
83755929a15Skevlo ure_rtl8153_nic_reset(sc);
83855929a15Skevlo
839fd07ab7eSkevlo if (ure_xfer_list_init(sc, sc->ure_cdata.ure_rx_chain,
840fd07ab7eSkevlo sc->ure_rxbufsz, URE_RX_LIST_CNT) == ENOBUFS) {
84142c54c93Sjmatthew printf("%s: rx list init failed\n", sc->ure_dev.dv_xname);
84242c54c93Sjmatthew splx(s);
84342c54c93Sjmatthew return;
84442c54c93Sjmatthew }
84542c54c93Sjmatthew
846fd07ab7eSkevlo if (ure_xfer_list_init(sc, sc->ure_cdata.ure_tx_chain,
847fd07ab7eSkevlo sc->ure_txbufsz, URE_TX_LIST_CNT) == ENOBUFS) {
84842c54c93Sjmatthew printf("%s: tx list init failed\n", sc->ure_dev.dv_xname);
84942c54c93Sjmatthew splx(s);
85042c54c93Sjmatthew return;
85142c54c93Sjmatthew }
85242c54c93Sjmatthew
853fd07ab7eSkevlo /* Initialize the SLIST we are using for the multiple tx buffers */
854fd07ab7eSkevlo SLIST_INIT(&sc->ure_cdata.ure_tx_free);
855fd07ab7eSkevlo for (i = 0; i < URE_TX_LIST_CNT; i++)
856fd07ab7eSkevlo SLIST_INSERT_HEAD(&sc->ure_cdata.ure_tx_free,
857fd07ab7eSkevlo &sc->ure_cdata.ure_tx_chain[i], uc_list);
858fd07ab7eSkevlo
859c0ad8833Smglocker /* Setup MAC address, and enable TX/RX. */
860c0ad8833Smglocker ure_ifmedia_init(ifp);
86142c54c93Sjmatthew
86242c54c93Sjmatthew /* Load the multicast filter. */
86342c54c93Sjmatthew ure_iff(sc);
86442c54c93Sjmatthew
86542c54c93Sjmatthew /* Open RX and TX pipes. */
86642c54c93Sjmatthew err = usbd_open_pipe(sc->ure_iface, sc->ure_ed[URE_ENDPT_RX],
86742c54c93Sjmatthew USBD_EXCLUSIVE_USE, &sc->ure_ep[URE_ENDPT_RX]);
86842c54c93Sjmatthew if (err) {
86942c54c93Sjmatthew printf("%s: open rx pipe failed: %s\n",
87042c54c93Sjmatthew sc->ure_dev.dv_xname, usbd_errstr(err));
87142c54c93Sjmatthew splx(s);
87242c54c93Sjmatthew return;
87342c54c93Sjmatthew }
87442c54c93Sjmatthew
87542c54c93Sjmatthew err = usbd_open_pipe(sc->ure_iface, sc->ure_ed[URE_ENDPT_TX],
87642c54c93Sjmatthew USBD_EXCLUSIVE_USE, &sc->ure_ep[URE_ENDPT_TX]);
87742c54c93Sjmatthew if (err) {
87842c54c93Sjmatthew printf("%s: open tx pipe failed: %s\n",
87942c54c93Sjmatthew sc->ure_dev.dv_xname, usbd_errstr(err));
88042c54c93Sjmatthew splx(s);
88142c54c93Sjmatthew return;
88242c54c93Sjmatthew }
88342c54c93Sjmatthew
88442c54c93Sjmatthew /* Start up the receive pipe. */
88542c54c93Sjmatthew for (i = 0; i < URE_RX_LIST_CNT; i++) {
886fd07ab7eSkevlo c = &sc->ure_cdata.ure_rx_chain[i];
88742c54c93Sjmatthew usbd_setup_xfer(c->uc_xfer, sc->ure_ep[URE_ENDPT_RX],
888fd07ab7eSkevlo c, c->uc_buf, c->uc_bufmax,
88942c54c93Sjmatthew USBD_SHORT_XFER_OK | USBD_NO_COPY,
89042c54c93Sjmatthew USBD_NO_TIMEOUT, ure_rxeof);
89142c54c93Sjmatthew usbd_transfer(c->uc_xfer);
89242c54c93Sjmatthew }
89342c54c93Sjmatthew
894c096a1a3Skevlo ure_ifmedia_upd(ifp);
895c096a1a3Skevlo
89642c54c93Sjmatthew /* Indicate we are up and running. */
89755929a15Skevlo sc->ure_flags &= ~URE_FLAG_LINK;
89842c54c93Sjmatthew ifp->if_flags |= IFF_RUNNING;
89942c54c93Sjmatthew ifq_clr_oactive(&ifp->if_snd);
90042c54c93Sjmatthew
90142c54c93Sjmatthew timeout_add_sec(&sc->ure_stat_ch, 1);
90242c54c93Sjmatthew
90342c54c93Sjmatthew splx(s);
90442c54c93Sjmatthew }
90542c54c93Sjmatthew
90642c54c93Sjmatthew void
ure_start(struct ifnet * ifp)90742c54c93Sjmatthew ure_start(struct ifnet *ifp)
90842c54c93Sjmatthew {
90942c54c93Sjmatthew struct ure_softc *sc = ifp->if_softc;
910fd07ab7eSkevlo struct ure_cdata *cd = &sc->ure_cdata;
911fd07ab7eSkevlo struct ure_chain *c;
912fd07ab7eSkevlo struct mbuf *m = NULL;
913fd07ab7eSkevlo uint32_t new_buflen;
914fd07ab7eSkevlo int s, mlen;
91542c54c93Sjmatthew
916fd07ab7eSkevlo if (!(sc->ure_flags & URE_FLAG_LINK) ||
917fd07ab7eSkevlo (ifp->if_flags & (IFF_RUNNING|IFF_UP)) !=
918fd07ab7eSkevlo (IFF_RUNNING|IFF_UP)) {
91942c54c93Sjmatthew return;
920fd07ab7eSkevlo }
921c096a1a3Skevlo
922fd07ab7eSkevlo s = splnet();
923fd07ab7eSkevlo
924fd07ab7eSkevlo c = SLIST_FIRST(&cd->ure_tx_free);
925fd07ab7eSkevlo while (c != NULL) {
926fd07ab7eSkevlo m = ifq_deq_begin(&ifp->if_snd);
927fd07ab7eSkevlo if (m == NULL)
928fd07ab7eSkevlo break;
929fd07ab7eSkevlo
930fd07ab7eSkevlo mlen = m->m_pkthdr.len;
931fd07ab7eSkevlo
932fd07ab7eSkevlo /* Discard packet larger than buffer. */
933fd07ab7eSkevlo if (mlen + sizeof(struct ure_txpkt) >= c->uc_bufmax) {
934fd07ab7eSkevlo ifq_deq_commit(&ifp->if_snd, m);
935fd07ab7eSkevlo m_freem(m);
936fd07ab7eSkevlo ifp->if_oerrors++;
937fd07ab7eSkevlo continue;
938fd07ab7eSkevlo }
939fd07ab7eSkevlo
940fd07ab7eSkevlo /*
941fd07ab7eSkevlo * If packet larger than remaining space, send buffer and
942fd07ab7eSkevlo * continue.
943fd07ab7eSkevlo */
944fd07ab7eSkevlo new_buflen = roundup(c->uc_buflen, URE_TX_BUF_ALIGN);
945fd07ab7eSkevlo if (new_buflen + sizeof(struct ure_txpkt) + mlen >=
946fd07ab7eSkevlo c->uc_bufmax) {
947fd07ab7eSkevlo ifq_deq_rollback(&ifp->if_snd, m);
948fd07ab7eSkevlo SLIST_REMOVE_HEAD(&cd->ure_tx_free, uc_list);
949fd07ab7eSkevlo if (ure_encap_xfer(ifp, sc, c)) {
950fd07ab7eSkevlo SLIST_INSERT_HEAD(&cd->ure_tx_free, c,
951fd07ab7eSkevlo uc_list);
952fd07ab7eSkevlo break;
953fd07ab7eSkevlo }
954fd07ab7eSkevlo c = SLIST_FIRST(&cd->ure_tx_free);
955fd07ab7eSkevlo continue;
956fd07ab7eSkevlo }
957fd07ab7eSkevlo
958fd07ab7eSkevlo /* Append packet to current buffer. */
959fd07ab7eSkevlo mlen = ure_encap_txpkt(m, c->uc_buf + new_buflen,
960fd07ab7eSkevlo c->uc_bufmax - new_buflen);
961fd07ab7eSkevlo if (mlen <= 0) {
962fd07ab7eSkevlo ifq_deq_rollback(&ifp->if_snd, m);
963c096a1a3Skevlo break;
96442c54c93Sjmatthew }
96542c54c93Sjmatthew
966fd07ab7eSkevlo ifq_deq_commit(&ifp->if_snd, m);
967fd07ab7eSkevlo c->uc_cnt += 1;
968fd07ab7eSkevlo c->uc_buflen = new_buflen + mlen;
96942c54c93Sjmatthew
97042c54c93Sjmatthew #if NBPFILTER > 0
97142c54c93Sjmatthew if (ifp->if_bpf)
972fd07ab7eSkevlo bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
97342c54c93Sjmatthew #endif
974fd07ab7eSkevlo
975fd07ab7eSkevlo m_freem(m);
976c096a1a3Skevlo }
977fd07ab7eSkevlo
978fd07ab7eSkevlo if (c != NULL) {
979fd07ab7eSkevlo /* Send current buffer unless empty */
980fd07ab7eSkevlo if (c->uc_buflen > 0 && c->uc_cnt > 0) {
981fd07ab7eSkevlo SLIST_REMOVE_HEAD(&cd->ure_tx_free, uc_list);
982fd07ab7eSkevlo if (ure_encap_xfer(ifp, sc, c)) {
983fd07ab7eSkevlo SLIST_INSERT_HEAD(&cd->ure_tx_free, c,
984fd07ab7eSkevlo uc_list);
985fd07ab7eSkevlo }
986fd07ab7eSkevlo c = SLIST_FIRST(&cd->ure_tx_free);
987fd07ab7eSkevlo }
988fd07ab7eSkevlo }
989fd07ab7eSkevlo
990fd07ab7eSkevlo ifp->if_timer = 5;
991fd07ab7eSkevlo if (c == NULL)
992fd07ab7eSkevlo ifq_set_oactive(&ifp->if_snd);
993fd07ab7eSkevlo splx(s);
99442c54c93Sjmatthew }
99542c54c93Sjmatthew
99642c54c93Sjmatthew void
ure_tick(void * xsc)99742c54c93Sjmatthew ure_tick(void *xsc)
99842c54c93Sjmatthew {
99942c54c93Sjmatthew struct ure_softc *sc = xsc;
100042c54c93Sjmatthew
100142c54c93Sjmatthew if (sc == NULL)
100242c54c93Sjmatthew return;
100342c54c93Sjmatthew
100442c54c93Sjmatthew if (usbd_is_dying(sc->ure_udev))
100542c54c93Sjmatthew return;
100642c54c93Sjmatthew
100742c54c93Sjmatthew usb_add_task(sc->ure_udev, &sc->ure_tick_task);
100842c54c93Sjmatthew }
100942c54c93Sjmatthew
101042c54c93Sjmatthew void
ure_stop(struct ure_softc * sc)101142c54c93Sjmatthew ure_stop(struct ure_softc *sc)
101242c54c93Sjmatthew {
1013fd07ab7eSkevlo struct ure_cdata *cd;
101442c54c93Sjmatthew struct ifnet *ifp;
1015fd07ab7eSkevlo usbd_status err;
101642c54c93Sjmatthew
101742c54c93Sjmatthew ure_reset(sc);
101842c54c93Sjmatthew
101942c54c93Sjmatthew ifp = &sc->ure_ac.ac_if;
102042c54c93Sjmatthew ifp->if_timer = 0;
102142c54c93Sjmatthew ifp->if_flags &= ~IFF_RUNNING;
102242c54c93Sjmatthew ifq_clr_oactive(&ifp->if_snd);
102342c54c93Sjmatthew
102442c54c93Sjmatthew timeout_del(&sc->ure_stat_ch);
1025c096a1a3Skevlo sc->ure_flags &= ~URE_FLAG_LINK;
102642c54c93Sjmatthew
102742c54c93Sjmatthew if (sc->ure_ep[URE_ENDPT_RX] != NULL) {
102842c54c93Sjmatthew err = usbd_close_pipe(sc->ure_ep[URE_ENDPT_RX]);
102942c54c93Sjmatthew if (err) {
103042c54c93Sjmatthew printf("%s: close rx pipe failed: %s\n",
103142c54c93Sjmatthew sc->ure_dev.dv_xname, usbd_errstr(err));
103242c54c93Sjmatthew }
103342c54c93Sjmatthew sc->ure_ep[URE_ENDPT_RX] = NULL;
103442c54c93Sjmatthew }
103542c54c93Sjmatthew
103642c54c93Sjmatthew if (sc->ure_ep[URE_ENDPT_TX] != NULL) {
103742c54c93Sjmatthew err = usbd_close_pipe(sc->ure_ep[URE_ENDPT_TX]);
103842c54c93Sjmatthew if (err) {
103942c54c93Sjmatthew printf("%s: close tx pipe failed: %s\n",
104042c54c93Sjmatthew sc->ure_dev.dv_xname, usbd_errstr(err));
104142c54c93Sjmatthew }
104242c54c93Sjmatthew sc->ure_ep[URE_ENDPT_TX] = NULL;
104342c54c93Sjmatthew }
104442c54c93Sjmatthew
1045fd07ab7eSkevlo cd = &sc->ure_cdata;
1046fd07ab7eSkevlo ure_xfer_list_free(sc, cd->ure_rx_chain, URE_RX_LIST_CNT);
1047fd07ab7eSkevlo ure_xfer_list_free(sc, cd->ure_tx_chain, URE_TX_LIST_CNT);
104842c54c93Sjmatthew }
1049fd07ab7eSkevlo
1050fd07ab7eSkevlo int
ure_xfer_list_init(struct ure_softc * sc,struct ure_chain * ch,uint32_t bufsize,int listlen)1051fd07ab7eSkevlo ure_xfer_list_init(struct ure_softc *sc, struct ure_chain *ch,
1052fd07ab7eSkevlo uint32_t bufsize, int listlen)
1053fd07ab7eSkevlo {
1054fd07ab7eSkevlo struct ure_chain *c;
1055fd07ab7eSkevlo int i;
1056fd07ab7eSkevlo
1057fd07ab7eSkevlo for (i = 0; i < listlen; i++) {
1058fd07ab7eSkevlo c = &ch[i];
1059fd07ab7eSkevlo c->uc_sc = sc;
1060fd07ab7eSkevlo c->uc_idx = i;
1061fd07ab7eSkevlo c->uc_buflen = 0;
1062fd07ab7eSkevlo c->uc_bufmax = bufsize;
1063fd07ab7eSkevlo c->uc_cnt = 0;
1064fd07ab7eSkevlo if (c->uc_xfer == NULL) {
1065fd07ab7eSkevlo c->uc_xfer = usbd_alloc_xfer(sc->ure_udev);
1066fd07ab7eSkevlo if (c->uc_xfer == NULL)
1067fd07ab7eSkevlo return (ENOBUFS);
1068fd07ab7eSkevlo c->uc_buf = usbd_alloc_buffer(c->uc_xfer, c->uc_bufmax);
1069fd07ab7eSkevlo if (c->uc_buf == NULL) {
1070fd07ab7eSkevlo usbd_free_xfer(c->uc_xfer);
1071fd07ab7eSkevlo c->uc_xfer = NULL;
1072fd07ab7eSkevlo return (ENOBUFS);
1073fd07ab7eSkevlo }
107442c54c93Sjmatthew }
107542c54c93Sjmatthew }
107642c54c93Sjmatthew
1077fd07ab7eSkevlo return (0);
107842c54c93Sjmatthew }
1079fd07ab7eSkevlo
1080fd07ab7eSkevlo void
ure_xfer_list_free(struct ure_softc * sc,struct ure_chain * ch,int listlen)1081fd07ab7eSkevlo ure_xfer_list_free(struct ure_softc *sc, struct ure_chain *ch, int listlen)
1082fd07ab7eSkevlo {
1083fd07ab7eSkevlo int i;
1084fd07ab7eSkevlo
1085fd07ab7eSkevlo for (i = 0; i < listlen; i++) {
1086fd07ab7eSkevlo if (ch[i].uc_buf != NULL) {
1087fd07ab7eSkevlo ch[i].uc_buf = NULL;
1088fd07ab7eSkevlo }
1089fd07ab7eSkevlo ch[i].uc_cnt = 0;
1090fd07ab7eSkevlo if (ch[i].uc_xfer != NULL) {
1091fd07ab7eSkevlo usbd_free_xfer(ch[i].uc_xfer);
1092fd07ab7eSkevlo ch[i].uc_xfer = NULL;
109342c54c93Sjmatthew }
109442c54c93Sjmatthew }
109542c54c93Sjmatthew }
109642c54c93Sjmatthew
109742c54c93Sjmatthew void
ure_rtl8152_init(struct ure_softc * sc)109842c54c93Sjmatthew ure_rtl8152_init(struct ure_softc *sc)
109942c54c93Sjmatthew {
110042c54c93Sjmatthew uint32_t pwrctrl;
110142c54c93Sjmatthew
110242c54c93Sjmatthew /* Disable ALDPS. */
110342c54c93Sjmatthew ure_ocp_reg_write(sc, URE_OCP_ALDPS_CONFIG, URE_ENPDNPS | URE_LINKENA |
110442c54c93Sjmatthew URE_DIS_SDSAVE);
110542c54c93Sjmatthew usbd_delay_ms(sc->ure_udev, 20);
110642c54c93Sjmatthew
110755929a15Skevlo if (sc->ure_chip & URE_CHIP_VER_4C00)
110855929a15Skevlo URE_CLRBIT_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA,
110955929a15Skevlo URE_LED_MODE_MASK);
111042c54c93Sjmatthew
111155929a15Skevlo URE_CLRBIT_2(sc, URE_USB_UPS_CTRL, URE_MCU_TYPE_USB, URE_POWER_CUT);
111255929a15Skevlo URE_CLRBIT_2(sc, URE_USB_PM_CTRL_STATUS, URE_MCU_TYPE_USB,
111355929a15Skevlo URE_RESUME_INDICATE);
111442c54c93Sjmatthew
111555929a15Skevlo URE_SETBIT_2(sc, URE_PLA_PHY_PWR, URE_MCU_TYPE_PLA,
111642c54c93Sjmatthew URE_TX_10M_IDLE_EN | URE_PFM_PWM_SWITCH);
111742c54c93Sjmatthew pwrctrl = ure_read_4(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA);
111842c54c93Sjmatthew pwrctrl &= ~URE_MCU_CLK_RATIO_MASK;
111942c54c93Sjmatthew pwrctrl |= URE_MCU_CLK_RATIO | URE_D3_CLK_GATED_EN;
112042c54c93Sjmatthew ure_write_4(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA, pwrctrl);
112142c54c93Sjmatthew ure_write_2(sc, URE_PLA_GPHY_INTR_IMR, URE_MCU_TYPE_PLA,
112242c54c93Sjmatthew URE_GPHY_STS_MSK | URE_SPEED_DOWN_MSK | URE_SPDWN_RXDV_MSK |
112342c54c93Sjmatthew URE_SPDWN_LINKCHG_MSK);
112442c54c93Sjmatthew
112555929a15Skevlo URE_SETBIT_2(sc, URE_PLA_RSTTALLY, URE_MCU_TYPE_PLA, URE_TALLY_RESET);
112655929a15Skevlo
112793362a8fSmpi /* Enable Rx aggregation. */
112855929a15Skevlo URE_CLRBIT_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB,
112955929a15Skevlo URE_RX_AGG_DISABLE | URE_RX_ZERO_EN);
113055929a15Skevlo }
113155929a15Skevlo
113255929a15Skevlo void
ure_rtl8153_init(struct ure_softc * sc)113355929a15Skevlo ure_rtl8153_init(struct ure_softc *sc)
113455929a15Skevlo {
113555929a15Skevlo uint16_t reg;
113655929a15Skevlo uint8_t u1u2[8];
113755929a15Skevlo int i;
113855929a15Skevlo
113955929a15Skevlo memset(u1u2, 0x00, sizeof(u1u2));
114055929a15Skevlo ure_write_mem(sc, URE_USB_TOLERANCE, URE_BYTE_EN_SIX_BYTES, u1u2,
114155929a15Skevlo sizeof(u1u2));
114255929a15Skevlo
114355929a15Skevlo for (i = 0; i < 500; i++) {
114455929a15Skevlo if (ure_read_2(sc, URE_PLA_BOOT_CTRL, URE_MCU_TYPE_PLA) &
114555929a15Skevlo URE_AUTOLOAD_DONE)
114655929a15Skevlo break;
114755929a15Skevlo usbd_delay_ms(sc->ure_udev, 20);
114855929a15Skevlo }
114955929a15Skevlo if (i == 500)
115055929a15Skevlo printf("%s: timeout waiting for chip autoload\n",
115155929a15Skevlo sc->ure_dev.dv_xname);
115255929a15Skevlo
115355929a15Skevlo ure_rtl8153_phy_status(sc, 0);
115455929a15Skevlo
115555929a15Skevlo if (sc->ure_chip & (URE_CHIP_VER_5C00 | URE_CHIP_VER_5C10 |
115655929a15Skevlo URE_CHIP_VER_5C20)) {
115755929a15Skevlo ure_ocp_reg_write(sc, URE_OCP_ADC_CFG,
115855929a15Skevlo URE_CKADSEL_L | URE_ADC_EN | URE_EN_EMI_L);
115955929a15Skevlo }
116055929a15Skevlo
11618a3a1b1fSkevlo ure_rtl8153_phy_status(sc, URE_PHY_STAT_LAN_ON);
116255929a15Skevlo
116355929a15Skevlo URE_CLRBIT_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, URE_U2P3_ENABLE);
116455929a15Skevlo
116555929a15Skevlo if (sc->ure_chip & URE_CHIP_VER_5C10) {
116655929a15Skevlo reg = ure_read_2(sc, URE_USB_SSPHYLINK2, URE_MCU_TYPE_USB);
116755929a15Skevlo reg &= ~URE_PWD_DN_SCALE_MASK;
116855929a15Skevlo reg |= URE_PWD_DN_SCALE(96);
116955929a15Skevlo ure_write_2(sc, URE_USB_SSPHYLINK2, URE_MCU_TYPE_USB, reg);
117055929a15Skevlo
117155929a15Skevlo URE_SETBIT_1(sc, URE_USB_USB2PHY, URE_MCU_TYPE_USB,
117255929a15Skevlo URE_USB2PHY_L1 | URE_USB2PHY_SUSPEND);
117355929a15Skevlo } else if (sc->ure_chip & URE_CHIP_VER_5C20) {
117455929a15Skevlo URE_CLRBIT_1(sc, URE_PLA_DMY_REG0, URE_MCU_TYPE_PLA,
117555929a15Skevlo URE_ECM_ALDPS);
117655929a15Skevlo }
117755929a15Skevlo if (sc->ure_chip & (URE_CHIP_VER_5C20 | URE_CHIP_VER_5C30)) {
117855929a15Skevlo if (ure_read_2(sc, URE_USB_BURST_SIZE, URE_MCU_TYPE_USB))
117955929a15Skevlo URE_SETBIT_1(sc, URE_USB_CSR_DUMMY1, URE_MCU_TYPE_USB,
118055929a15Skevlo URE_DYNAMIC_BURST);
118155929a15Skevlo else
118255929a15Skevlo URE_CLRBIT_1(sc, URE_USB_CSR_DUMMY1, URE_MCU_TYPE_USB,
118355929a15Skevlo URE_DYNAMIC_BURST);
118455929a15Skevlo }
118555929a15Skevlo
118655929a15Skevlo URE_SETBIT_1(sc, URE_USB_CSR_DUMMY2, URE_MCU_TYPE_USB, URE_EP4_FULL_FC);
118755929a15Skevlo
118855929a15Skevlo URE_CLRBIT_2(sc, URE_USB_WDT11_CTRL, URE_MCU_TYPE_USB, URE_TIMER11_EN);
118955929a15Skevlo
119055929a15Skevlo URE_CLRBIT_2(sc, URE_PLA_LED_FEATURE, URE_MCU_TYPE_PLA,
119155929a15Skevlo URE_LED_MODE_MASK);
119255929a15Skevlo
119355929a15Skevlo if ((sc->ure_chip & URE_CHIP_VER_5C10) &&
119455929a15Skevlo sc->ure_udev->speed != USB_SPEED_SUPER)
119555929a15Skevlo reg = URE_LPM_TIMER_500MS;
119655929a15Skevlo else
119755929a15Skevlo reg = URE_LPM_TIMER_500US;
119855929a15Skevlo ure_write_1(sc, URE_USB_LPM_CTRL, URE_MCU_TYPE_USB,
119955929a15Skevlo URE_FIFO_EMPTY_1FB | URE_ROK_EXIT_LPM | reg);
120055929a15Skevlo
120155929a15Skevlo reg = ure_read_2(sc, URE_USB_AFE_CTRL2, URE_MCU_TYPE_USB);
120255929a15Skevlo reg &= ~URE_SEN_VAL_MASK;
120355929a15Skevlo reg |= URE_SEN_VAL_NORMAL | URE_SEL_RXIDLE;
120455929a15Skevlo ure_write_2(sc, URE_USB_AFE_CTRL2, URE_MCU_TYPE_USB, reg);
120555929a15Skevlo
120655929a15Skevlo ure_write_2(sc, URE_USB_CONNECT_TIMER, URE_MCU_TYPE_USB, 0x0001);
120755929a15Skevlo
120855929a15Skevlo URE_CLRBIT_2(sc, URE_USB_POWER_CUT, URE_MCU_TYPE_USB,
120955929a15Skevlo URE_PWR_EN | URE_PHASE2_EN);
121055929a15Skevlo URE_CLRBIT_2(sc, URE_USB_MISC_0, URE_MCU_TYPE_USB, URE_PCUT_STATUS);
121155929a15Skevlo
121255929a15Skevlo memset(u1u2, 0xff, sizeof(u1u2));
121355929a15Skevlo ure_write_mem(sc, URE_USB_TOLERANCE, URE_BYTE_EN_SIX_BYTES, u1u2,
121455929a15Skevlo sizeof(u1u2));
121555929a15Skevlo
121655929a15Skevlo ure_write_2(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA, 0);
121755929a15Skevlo ure_write_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA, 0);
121855929a15Skevlo ure_write_2(sc, URE_PLA_MAC_PWR_CTRL3, URE_MCU_TYPE_PLA, 0);
121955929a15Skevlo ure_write_2(sc, URE_PLA_MAC_PWR_CTRL4, URE_MCU_TYPE_PLA, 0);
122055929a15Skevlo
122155929a15Skevlo /* Enable Rx aggregation. */
122255929a15Skevlo URE_CLRBIT_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB,
122355929a15Skevlo URE_RX_AGG_DISABLE | URE_RX_ZERO_EN);
122455929a15Skevlo
122555929a15Skevlo URE_SETBIT_2(sc, URE_PLA_RSTTALLY, URE_MCU_TYPE_PLA, URE_TALLY_RESET);
122655929a15Skevlo }
122755929a15Skevlo
122855929a15Skevlo void
ure_rtl8153b_init(struct ure_softc * sc)122955929a15Skevlo ure_rtl8153b_init(struct ure_softc *sc)
123055929a15Skevlo {
1231c096a1a3Skevlo uint16_t reg;
123255929a15Skevlo int i;
123355929a15Skevlo
12348a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B)) {
12358a3a1b1fSkevlo URE_CLRBIT_1(sc, URE_USB_ECM_OP, URE_MCU_TYPE_USB,
12368a3a1b1fSkevlo URE_EN_ALL_SPEED);
12378a3a1b1fSkevlo ure_write_2(sc, URE_USB_SPEED_OPTION, URE_MCU_TYPE_USB, 0);
12388a3a1b1fSkevlo URE_SETBIT_2(sc, URE_USB_ECM_OPTION, URE_MCU_TYPE_USB,
12398a3a1b1fSkevlo URE_BYPASS_MAC_RESET);
12408a3a1b1fSkevlo
12418a3a1b1fSkevlo if (sc->ure_flags & URE_FLAG_8156B)
12428a3a1b1fSkevlo URE_SETBIT_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB,
12438a3a1b1fSkevlo URE_RX_DETECT8);
1244c096a1a3Skevlo }
1245c096a1a3Skevlo
124655929a15Skevlo URE_CLRBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB, LPM_U1U2_EN);
124755929a15Skevlo
12488a3a1b1fSkevlo if (sc->ure_flags & URE_FLAG_8156B)
12498a3a1b1fSkevlo ure_wait_for_flash(sc);
12508a3a1b1fSkevlo
125155929a15Skevlo for (i = 0; i < 500; i++) {
125255929a15Skevlo if (ure_read_2(sc, URE_PLA_BOOT_CTRL, URE_MCU_TYPE_PLA) &
125355929a15Skevlo URE_AUTOLOAD_DONE)
125455929a15Skevlo break;
125555929a15Skevlo usbd_delay_ms(sc->ure_udev, 20);
125655929a15Skevlo }
125755929a15Skevlo if (i == 500)
125855929a15Skevlo printf("%s: timeout waiting for chip autoload\n",
125955929a15Skevlo sc->ure_dev.dv_xname);
126055929a15Skevlo
126155929a15Skevlo ure_rtl8153_phy_status(sc, 0);
12628a3a1b1fSkevlo ure_rtl8153_phy_status(sc, URE_PHY_STAT_LAN_ON);
126355929a15Skevlo
126455929a15Skevlo URE_CLRBIT_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, URE_U2P3_ENABLE);
126555929a15Skevlo
126655929a15Skevlo /* MSC timer, 32760 ms. */
12678a3a1b1fSkevlo ure_write_2(sc, URE_USB_MSC_TIMER, URE_MCU_TYPE_USB, 4095);
126855929a15Skevlo
12698a3a1b1fSkevlo if (!(sc->ure_flags & URE_FLAG_8153B)) {
127055929a15Skevlo /* U1/U2/L1 idle timer, 500 us. */
127155929a15Skevlo ure_write_2(sc, URE_USB_U1U2_TIMER, URE_MCU_TYPE_USB, 500);
12728a3a1b1fSkevlo }
127355929a15Skevlo
127455929a15Skevlo URE_CLRBIT_2(sc, URE_USB_POWER_CUT, URE_MCU_TYPE_USB, URE_PWR_EN);
127555929a15Skevlo URE_CLRBIT_2(sc, URE_USB_MISC_0, URE_MCU_TYPE_USB, URE_PCUT_STATUS);
127655929a15Skevlo
127755929a15Skevlo URE_CLRBIT_1(sc, URE_USB_POWER_CUT, URE_MCU_TYPE_USB,
127855929a15Skevlo URE_UPS_EN | URE_USP_PREWAKE);
12798a3a1b1fSkevlo URE_CLRBIT_1(sc, URE_USB_MISC_2, URE_MCU_TYPE_USB,
12803dd6ed5fSkevlo URE_UPS_FORCE_PWR_DOWN | URE_UPS_NO_UPS);
128155929a15Skevlo
128255929a15Skevlo URE_CLRBIT_1(sc, URE_PLA_INDICATE_FALG, URE_MCU_TYPE_PLA,
128355929a15Skevlo URE_UPCOMING_RUNTIME_D3);
128455929a15Skevlo URE_CLRBIT_1(sc, URE_PLA_SUSPEND_FLAG, URE_MCU_TYPE_PLA,
128555929a15Skevlo URE_LINK_CHG_EVENT);
128655929a15Skevlo URE_CLRBIT_2(sc, URE_PLA_EXTRA_STATUS, URE_MCU_TYPE_PLA,
128755929a15Skevlo URE_LINK_CHANGE_FLAG);
128855929a15Skevlo
128955929a15Skevlo ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_CONFIG);
129055929a15Skevlo URE_CLRBIT_2(sc, URE_PLA_CONFIG34, URE_MCU_TYPE_PLA,
129155929a15Skevlo URE_LINK_OFF_WAKE_EN);
129255929a15Skevlo ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_NORAML);
129355929a15Skevlo
12948a3a1b1fSkevlo if (sc->ure_flags & URE_FLAG_8153B) {
12958a3a1b1fSkevlo reg = ure_read_2(sc, URE_PLA_EXTRA_STATUS, URE_MCU_TYPE_PLA);
12968a3a1b1fSkevlo if (ure_read_2(sc, URE_PLA_PHYSTATUS, URE_MCU_TYPE_PLA) &
12978a3a1b1fSkevlo URE_PHYSTATUS_LINK)
12988a3a1b1fSkevlo reg |= URE_CUR_LINK_OK;
12998a3a1b1fSkevlo else
13008a3a1b1fSkevlo reg &= ~URE_CUR_LINK_OK;
13018a3a1b1fSkevlo ure_write_2(sc, URE_PLA_EXTRA_STATUS, URE_MCU_TYPE_PLA,
13028a3a1b1fSkevlo reg | URE_POLL_LINK_CHG);
13038a3a1b1fSkevlo }
13048a3a1b1fSkevlo
13058a3a1b1fSkevlo if (sc->ure_udev->speed == USB_SPEED_SUPER) {
13068a3a1b1fSkevlo URE_SETBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB,
13078a3a1b1fSkevlo LPM_U1U2_EN);
13088a3a1b1fSkevlo }
13098a3a1b1fSkevlo
13108a3a1b1fSkevlo if (sc->ure_flags & URE_FLAG_8156B) {
13118a3a1b1fSkevlo URE_CLRBIT_2(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, URE_SLOT_EN);
13128a3a1b1fSkevlo URE_SETBIT_2(sc, URE_PLA_CPCR, URE_MCU_TYPE_PLA,
13138a3a1b1fSkevlo URE_FLOW_CTRL_EN);
13148a3a1b1fSkevlo
13158a3a1b1fSkevlo /* Enable fc timer and set timer to 600 ms. */
13168a3a1b1fSkevlo ure_write_2(sc, URE_USB_FC_TIMER, URE_MCU_TYPE_USB,
13178a3a1b1fSkevlo URE_CTRL_TIMER_EN | 75);
13188a3a1b1fSkevlo
13198a3a1b1fSkevlo reg = ure_read_2(sc, URE_USB_FW_CTRL, URE_MCU_TYPE_USB);
13208a3a1b1fSkevlo if (!(ure_read_2(sc, URE_PLA_POL_GPIO_CTRL, URE_MCU_TYPE_PLA) &
13218a3a1b1fSkevlo URE_DACK_DET_EN))
13228a3a1b1fSkevlo reg |= URE_FLOW_CTRL_PATCH_2;
13238a3a1b1fSkevlo reg &= ~URE_AUTO_SPEEDUP;
13248a3a1b1fSkevlo ure_write_2(sc, URE_USB_FW_CTRL, URE_MCU_TYPE_USB, reg);
13258a3a1b1fSkevlo
13268a3a1b1fSkevlo URE_SETBIT_2(sc, URE_USB_FW_TASK, URE_MCU_TYPE_USB,
13278a3a1b1fSkevlo URE_FC_PATCH_TASK);
13288a3a1b1fSkevlo }
132955929a15Skevlo
133055929a15Skevlo /* MAC clock speed down. */
13318a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B)) {
1332c096a1a3Skevlo ure_write_2(sc, URE_PLA_MAC_PWR_CTRL, URE_MCU_TYPE_PLA, 0x0403);
13338a3a1b1fSkevlo reg = ure_read_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA);
13348a3a1b1fSkevlo reg &= ~URE_EEE_SPDWN_RATIO_MASK;
1335c096a1a3Skevlo reg |= URE_MAC_CLK_SPDWN_EN | 0x0003;
1336c096a1a3Skevlo ure_write_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA, reg);
1337c096a1a3Skevlo
1338c096a1a3Skevlo URE_CLRBIT_2(sc, URE_PLA_MAC_PWR_CTRL3, URE_MCU_TYPE_PLA,
13398a3a1b1fSkevlo URE_PLA_MCU_SPDWN_EN);
1340c096a1a3Skevlo
1341c096a1a3Skevlo reg = ure_read_2(sc, URE_PLA_EXTRA_STATUS, URE_MCU_TYPE_PLA);
13428a3a1b1fSkevlo if (ure_read_2(sc, URE_PLA_PHYSTATUS, URE_MCU_TYPE_PLA) &
13438a3a1b1fSkevlo URE_PHYSTATUS_LINK)
13448a3a1b1fSkevlo reg |= URE_CUR_LINK_OK;
1345c096a1a3Skevlo else
13468a3a1b1fSkevlo reg &= ~URE_CUR_LINK_OK;
13478a3a1b1fSkevlo ure_write_2(sc, URE_PLA_EXTRA_STATUS, URE_MCU_TYPE_PLA,
13488a3a1b1fSkevlo reg | URE_POLL_LINK_CHG);
1349c096a1a3Skevlo } else
135055929a15Skevlo URE_SETBIT_2(sc, URE_PLA_MAC_PWR_CTRL2, URE_MCU_TYPE_PLA,
135155929a15Skevlo URE_MAC_CLK_SPDWN_EN);
135255929a15Skevlo
135355929a15Skevlo /* Enable Rx aggregation. */
135455929a15Skevlo URE_CLRBIT_2(sc, URE_USB_USB_CTRL, URE_MCU_TYPE_USB,
135555929a15Skevlo URE_RX_AGG_DISABLE | URE_RX_ZERO_EN);
135655929a15Skevlo
1357c096a1a3Skevlo if (sc->ure_flags & URE_FLAG_8156)
13588a3a1b1fSkevlo URE_SETBIT_1(sc, URE_USB_BMU_CONFIG, URE_MCU_TYPE_USB,
13598a3a1b1fSkevlo URE_ACT_ODMA);
1360c096a1a3Skevlo
13613dd6ed5fSkevlo if (!(sc->ure_flags & URE_FLAG_8153B)) {
13623dd6ed5fSkevlo /*
13633dd6ed5fSkevlo * Select force mode through 0xa5b4 bit 15
13643dd6ed5fSkevlo * 0: MDIO force mode
13653dd6ed5fSkevlo * 1: MMD force mode
13663dd6ed5fSkevlo */
13673dd6ed5fSkevlo reg = ure_ocp_reg_read(sc, 0xa5b4);
13683dd6ed5fSkevlo if (reg & 0x8000)
13693dd6ed5fSkevlo ure_ocp_reg_write(sc, 0xa5b4, reg & ~0x8000);
13703dd6ed5fSkevlo }
13713dd6ed5fSkevlo
137255929a15Skevlo URE_SETBIT_2(sc, URE_PLA_RSTTALLY, URE_MCU_TYPE_PLA, URE_TALLY_RESET);
137355929a15Skevlo }
137455929a15Skevlo
137555929a15Skevlo void
ure_rtl8152_nic_reset(struct ure_softc * sc)137655929a15Skevlo ure_rtl8152_nic_reset(struct ure_softc *sc)
137755929a15Skevlo {
137855929a15Skevlo uint32_t rx_fifo1, rx_fifo2;
137955929a15Skevlo int i;
138042c54c93Sjmatthew
138142c54c93Sjmatthew /* Disable ALDPS. */
138242c54c93Sjmatthew ure_ocp_reg_write(sc, URE_OCP_ALDPS_CONFIG, URE_ENPDNPS | URE_LINKENA |
138342c54c93Sjmatthew URE_DIS_SDSAVE);
138442c54c93Sjmatthew usbd_delay_ms(sc->ure_udev, 20);
138542c54c93Sjmatthew
138655929a15Skevlo URE_CLRBIT_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, URE_RCR_ACPT_ALL);
138742c54c93Sjmatthew
138855929a15Skevlo URE_SETBIT_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA, URE_RXDY_GATED_EN);
138942c54c93Sjmatthew ure_disable_teredo(sc);
139055929a15Skevlo ure_write_1(sc, URE_PLA_CRWECR, URE_MCU_TYPE_PLA, URE_CRWECR_NORAML);
139155929a15Skevlo ure_write_1(sc, URE_PLA_CR, URE_MCU_TYPE_PLA, 0);
139242c54c93Sjmatthew
139355929a15Skevlo URE_CLRBIT_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA, URE_NOW_IS_OOB);
139455929a15Skevlo URE_CLRBIT_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA, URE_MCU_BORW_EN);
139555929a15Skevlo for (i = 0; i < URE_TIMEOUT; i++) {
139655929a15Skevlo if (ure_read_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) &
139755929a15Skevlo URE_LINK_LIST_READY)
139855929a15Skevlo break;
139955929a15Skevlo usbd_delay_ms(sc->ure_udev, 1);
1400794a317fSkettenis }
140155929a15Skevlo if (i == URE_TIMEOUT)
140255929a15Skevlo printf("%s: timeout waiting for OOB control\n",
140355929a15Skevlo sc->ure_dev.dv_xname);
140455929a15Skevlo URE_SETBIT_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA, URE_RE_INIT_LL);
140555929a15Skevlo for (i = 0; i < URE_TIMEOUT; i++) {
140655929a15Skevlo if (ure_read_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) &
140755929a15Skevlo URE_LINK_LIST_READY)
140855929a15Skevlo break;
140955929a15Skevlo usbd_delay_ms(sc->ure_udev, 1);
1410794a317fSkettenis }
141155929a15Skevlo if (i == URE_TIMEOUT)
141255929a15Skevlo printf("%s: timeout waiting for OOB control\n",
141355929a15Skevlo sc->ure_dev.dv_xname);
1414794a317fSkettenis
141542c54c93Sjmatthew ure_reset(sc);
141642c54c93Sjmatthew
141755929a15Skevlo /* Configure Rx FIFO threshold. */
141842c54c93Sjmatthew ure_write_4(sc, URE_PLA_RXFIFO_CTRL0, URE_MCU_TYPE_PLA,
141942c54c93Sjmatthew URE_RXFIFO_THR1_NORMAL);
142042c54c93Sjmatthew if (sc->ure_udev->speed == USB_SPEED_FULL) {
142142c54c93Sjmatthew rx_fifo1 = URE_RXFIFO_THR2_FULL;
142242c54c93Sjmatthew rx_fifo2 = URE_RXFIFO_THR3_FULL;
142342c54c93Sjmatthew } else {
142442c54c93Sjmatthew rx_fifo1 = URE_RXFIFO_THR2_HIGH;
142542c54c93Sjmatthew rx_fifo2 = URE_RXFIFO_THR3_HIGH;
142642c54c93Sjmatthew }
142742c54c93Sjmatthew ure_write_4(sc, URE_PLA_RXFIFO_CTRL1, URE_MCU_TYPE_PLA, rx_fifo1);
142842c54c93Sjmatthew ure_write_4(sc, URE_PLA_RXFIFO_CTRL2, URE_MCU_TYPE_PLA, rx_fifo2);
142942c54c93Sjmatthew
143042c54c93Sjmatthew /* Configure Tx FIFO threshold. */
143142c54c93Sjmatthew ure_write_4(sc, URE_PLA_TXFIFO_CTRL, URE_MCU_TYPE_PLA,
143242c54c93Sjmatthew URE_TXFIFO_THR_NORMAL);
143355929a15Skevlo
143455929a15Skevlo ure_write_1(sc, URE_USB_TX_AGG, URE_MCU_TYPE_USB,
143555929a15Skevlo URE_TX_AGG_MAX_THRESHOLD);
143655929a15Skevlo ure_write_4(sc, URE_USB_RX_BUF_TH, URE_MCU_TYPE_USB, URE_RX_THR_HIGH);
143755929a15Skevlo ure_write_4(sc, URE_USB_TX_DMA, URE_MCU_TYPE_USB,
143855929a15Skevlo URE_TEST_MODE_DISABLE | URE_TX_SIZE_ADJUST1);
143955929a15Skevlo
144055929a15Skevlo ure_rxvlan(sc);
144155929a15Skevlo ure_write_2(sc, URE_PLA_RMS, URE_MCU_TYPE_PLA,
144255929a15Skevlo ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
144355929a15Skevlo URE_SETBIT_2(sc, URE_PLA_TCR0, URE_MCU_TYPE_PLA, URE_TCR0_AUTO_FIFO);
144455929a15Skevlo
144555929a15Skevlo /* Enable ALDPS. */
144655929a15Skevlo ure_ocp_reg_write(sc, URE_OCP_ALDPS_CONFIG,
144755929a15Skevlo URE_ENPWRSAVE | URE_ENPDNPS | URE_LINKENA | URE_DIS_SDSAVE);
144855929a15Skevlo }
144955929a15Skevlo
145055929a15Skevlo void
ure_rtl8153_nic_reset(struct ure_softc * sc)145155929a15Skevlo ure_rtl8153_nic_reset(struct ure_softc *sc)
145255929a15Skevlo {
145355929a15Skevlo struct ifnet *ifp = &sc->ure_ac.ac_if;
145455929a15Skevlo uint32_t reg = 0;
145555929a15Skevlo uint8_t u1u2[8] = { 0 };
145655929a15Skevlo int i;
145755929a15Skevlo
14588a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156 | URE_FLAG_8156B)) {
145955929a15Skevlo URE_CLRBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB,
146055929a15Skevlo LPM_U1U2_EN);
146155929a15Skevlo } else {
146255929a15Skevlo memset(u1u2, 0x00, sizeof(u1u2));
146355929a15Skevlo ure_write_mem(sc, URE_USB_TOLERANCE, URE_BYTE_EN_SIX_BYTES,
146455929a15Skevlo u1u2, sizeof(u1u2));
146555929a15Skevlo }
146655929a15Skevlo URE_CLRBIT_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB, URE_U2P3_ENABLE);
146755929a15Skevlo
146855929a15Skevlo /* Disable ALDPS. */
146955929a15Skevlo ure_ocp_reg_write(sc, URE_OCP_POWER_CFG,
147055929a15Skevlo ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) & ~URE_EN_ALDPS);
147155929a15Skevlo for (i = 0; i < 20; i++) {
147255929a15Skevlo usbd_delay_ms(sc->ure_udev, 1);
147355929a15Skevlo if (ure_read_2(sc, 0xe000, URE_MCU_TYPE_PLA) & 0x0100)
147455929a15Skevlo break;
147555929a15Skevlo }
147655929a15Skevlo
147755929a15Skevlo URE_SETBIT_2(sc, URE_PLA_MISC_1, URE_MCU_TYPE_PLA, URE_RXDY_GATED_EN);
147855929a15Skevlo ure_disable_teredo(sc);
147955929a15Skevlo
148055929a15Skevlo URE_CLRBIT_4(sc, URE_PLA_RCR, URE_MCU_TYPE_PLA, URE_RCR_ACPT_ALL);
148155929a15Skevlo
148255929a15Skevlo ure_reset(sc);
148355929a15Skevlo ure_reset_bmu(sc);
148455929a15Skevlo
148555929a15Skevlo URE_CLRBIT_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA, URE_NOW_IS_OOB);
148655929a15Skevlo URE_CLRBIT_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA, URE_MCU_BORW_EN);
148755929a15Skevlo
14888a3a1b1fSkevlo if (!(sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B))) {
1489c096a1a3Skevlo for (i = 0; i < URE_TIMEOUT; i++) {
1490c096a1a3Skevlo if (ure_read_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) &
1491c096a1a3Skevlo URE_LINK_LIST_READY)
1492c096a1a3Skevlo break;
1493c096a1a3Skevlo usbd_delay_ms(sc->ure_udev, 1);
1494c096a1a3Skevlo }
1495c096a1a3Skevlo if (i == URE_TIMEOUT)
1496c096a1a3Skevlo printf("%s: timeout waiting for OOB control\n",
1497c096a1a3Skevlo sc->ure_dev.dv_xname);
1498c096a1a3Skevlo URE_SETBIT_2(sc, URE_PLA_SFF_STS_7, URE_MCU_TYPE_PLA,
1499c096a1a3Skevlo URE_RE_INIT_LL);
1500c096a1a3Skevlo for (i = 0; i < URE_TIMEOUT; i++) {
1501c096a1a3Skevlo if (ure_read_1(sc, URE_PLA_OOB_CTRL, URE_MCU_TYPE_PLA) &
1502c096a1a3Skevlo URE_LINK_LIST_READY)
1503c096a1a3Skevlo break;
1504c096a1a3Skevlo usbd_delay_ms(sc->ure_udev, 1);
1505c096a1a3Skevlo }
1506c096a1a3Skevlo if (i == URE_TIMEOUT)
1507c096a1a3Skevlo printf("%s: timeout waiting for OOB control\n",
1508c096a1a3Skevlo sc->ure_dev.dv_xname);
1509c096a1a3Skevlo }
15108a3a1b1fSkevlo
151155929a15Skevlo ure_rxvlan(sc);
15128a3a1b1fSkevlo
151355929a15Skevlo ure_write_2(sc, URE_PLA_RMS, URE_MCU_TYPE_PLA,
151455929a15Skevlo URE_FRAMELEN(ifp->if_mtu));
151555929a15Skevlo ure_write_1(sc, URE_PLA_MTPS, URE_MCU_TYPE_PLA, MTPS_JUMBO);
151655929a15Skevlo
15178a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B)) {
15188a3a1b1fSkevlo ure_write_2(sc, URE_PLA_RX_FIFO_FULL, URE_MCU_TYPE_PLA,
15198a3a1b1fSkevlo (sc->ure_flags & URE_FLAG_8156) ? 1024 : 512);
15208a3a1b1fSkevlo ure_write_2(sc, URE_PLA_RX_FIFO_EMPTY, URE_MCU_TYPE_PLA,
15218a3a1b1fSkevlo (sc->ure_flags & URE_FLAG_8156) ? 2048 : 1024);
15228a3a1b1fSkevlo
15238a3a1b1fSkevlo /* Tx share fifo free credit full threshold. */
15248a3a1b1fSkevlo ure_write_2(sc, URE_PLA_TXFIFO_CTRL, URE_MCU_TYPE_PLA, 8);
15258a3a1b1fSkevlo ure_write_2(sc, URE_PLA_TXFIFO_FULL, URE_MCU_TYPE_PLA, 128);
15268a3a1b1fSkevlo
15278a3a1b1fSkevlo if (sc->ure_flags & URE_FLAG_8156)
15288a3a1b1fSkevlo URE_SETBIT_2(sc, URE_USB_BMU_CONFIG, URE_MCU_TYPE_USB,
15298a3a1b1fSkevlo URE_ACT_ODMA);
15308a3a1b1fSkevlo
15318a3a1b1fSkevlo /* FIFO settings */
15328a3a1b1fSkevlo reg = ure_read_2(sc, URE_PLA_RXFIFO_FULL, URE_MCU_TYPE_PLA);
15338a3a1b1fSkevlo reg &= ~URE_RXFIFO_FULL_MASK;
15348a3a1b1fSkevlo ure_write_2(sc, URE_PLA_RXFIFO_FULL, URE_MCU_TYPE_PLA,
15358a3a1b1fSkevlo reg | 0x0008);
15368a3a1b1fSkevlo
15378a3a1b1fSkevlo URE_CLRBIT_2(sc, URE_PLA_MAC_PWR_CTRL3, URE_MCU_TYPE_PLA,
15388a3a1b1fSkevlo URE_PLA_MCU_SPDWN_EN);
15398a3a1b1fSkevlo
15408a3a1b1fSkevlo URE_CLRBIT_2(sc, URE_USB_SPEED_OPTION, URE_MCU_TYPE_USB,
15418a3a1b1fSkevlo URE_RG_PWRDN_EN | URE_ALL_SPEED_OFF);
15428a3a1b1fSkevlo
15438a3a1b1fSkevlo ure_write_4(sc, URE_USB_RX_BUF_TH, URE_MCU_TYPE_USB,
15448a3a1b1fSkevlo 0x00600400);
15453dd6ed5fSkevlo } else {
1546c096a1a3Skevlo URE_SETBIT_2(sc, URE_PLA_TCR0, URE_MCU_TYPE_PLA,
1547c096a1a3Skevlo URE_TCR0_AUTO_FIFO);
154855929a15Skevlo ure_reset(sc);
154955929a15Skevlo
155055929a15Skevlo /* Configure Rx FIFO threshold. */
155155929a15Skevlo ure_write_4(sc, URE_PLA_RXFIFO_CTRL0, URE_MCU_TYPE_PLA,
155255929a15Skevlo URE_RXFIFO_THR1_NORMAL);
155355929a15Skevlo ure_write_2(sc, URE_PLA_RXFIFO_CTRL1, URE_MCU_TYPE_PLA,
155455929a15Skevlo URE_RXFIFO_THR2_NORMAL);
155555929a15Skevlo ure_write_2(sc, URE_PLA_RXFIFO_CTRL2, URE_MCU_TYPE_PLA,
155655929a15Skevlo URE_RXFIFO_THR3_NORMAL);
155755929a15Skevlo
155855929a15Skevlo /* Configure Tx FIFO threshold. */
155955929a15Skevlo ure_write_4(sc, URE_PLA_TXFIFO_CTRL, URE_MCU_TYPE_PLA,
156055929a15Skevlo URE_TXFIFO_THR_NORMAL2);
156155929a15Skevlo
15628a3a1b1fSkevlo if (sc->ure_flags & URE_FLAG_8153B) {
156355929a15Skevlo ure_write_4(sc, URE_USB_RX_BUF_TH, URE_MCU_TYPE_USB,
156455929a15Skevlo URE_RX_THR_B);
15658a3a1b1fSkevlo
15668a3a1b1fSkevlo URE_CLRBIT_2(sc, URE_PLA_MAC_PWR_CTRL3,
15678a3a1b1fSkevlo URE_MCU_TYPE_PLA, URE_PLA_MCU_SPDWN_EN);
15688a3a1b1fSkevlo } else {
15698a3a1b1fSkevlo URE_SETBIT_1(sc, URE_PLA_CONFIG6, URE_MCU_TYPE_PLA,
15708a3a1b1fSkevlo URE_LANWAKE_CLR_EN);
15718a3a1b1fSkevlo URE_CLRBIT_1(sc, URE_PLA_LWAKE_CTRL_REG,
15728a3a1b1fSkevlo URE_MCU_TYPE_PLA, URE_LANWAKE_PIN);
15738a3a1b1fSkevlo URE_CLRBIT_2(sc, URE_USB_SSPHYLINK1, URE_MCU_TYPE_USB,
15748a3a1b1fSkevlo URE_DELAY_PHY_PWR_CHG);
15758a3a1b1fSkevlo }
157655929a15Skevlo }
157755929a15Skevlo
157855929a15Skevlo /* Enable ALDPS. */
157955929a15Skevlo ure_ocp_reg_write(sc, URE_OCP_POWER_CFG,
158055929a15Skevlo ure_ocp_reg_read(sc, URE_OCP_POWER_CFG) | URE_EN_ALDPS);
158155929a15Skevlo
158255929a15Skevlo if ((sc->ure_chip & (URE_CHIP_VER_5C20 | URE_CHIP_VER_5C30)) ||
15838a3a1b1fSkevlo (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B)))
158455929a15Skevlo URE_SETBIT_2(sc, URE_USB_U2P3_CTRL, URE_MCU_TYPE_USB,
158555929a15Skevlo URE_U2P3_ENABLE);
158655929a15Skevlo
15878a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156 | URE_FLAG_8156B)) {
15888a3a1b1fSkevlo if (sc->ure_udev->speed == USB_SPEED_SUPER)
158955929a15Skevlo URE_SETBIT_2(sc, URE_USB_LPM_CONFIG, URE_MCU_TYPE_USB,
159055929a15Skevlo LPM_U1U2_EN);
159155929a15Skevlo } else {
159255929a15Skevlo memset(u1u2, 0xff, sizeof(u1u2));
159355929a15Skevlo ure_write_mem(sc, URE_USB_TOLERANCE, URE_BYTE_EN_SIX_BYTES,
159455929a15Skevlo u1u2, sizeof(u1u2));
159555929a15Skevlo }
159655929a15Skevlo }
159755929a15Skevlo
15988a3a1b1fSkevlo uint16_t
ure_rtl8153_phy_status(struct ure_softc * sc,int desired)15998a3a1b1fSkevlo ure_rtl8153_phy_status(struct ure_softc *sc, int desired)
160055929a15Skevlo {
160155929a15Skevlo uint16_t reg;
160255929a15Skevlo int i;
160355929a15Skevlo
160455929a15Skevlo for (i = 0; i < 500; i++) {
160555929a15Skevlo reg = ure_ocp_reg_read(sc, URE_OCP_PHY_STATUS) &
160655929a15Skevlo URE_PHY_STAT_MASK;
16078a3a1b1fSkevlo if (desired) {
16088a3a1b1fSkevlo if (reg == desired)
160955929a15Skevlo break;
161055929a15Skevlo } else {
161155929a15Skevlo if (reg == URE_PHY_STAT_LAN_ON ||
161255929a15Skevlo reg == URE_PHY_STAT_PWRDN ||
161355929a15Skevlo reg == URE_PHY_STAT_EXT_INIT)
161455929a15Skevlo break;
161555929a15Skevlo }
161655929a15Skevlo usbd_delay_ms(sc->ure_udev, 20);
161755929a15Skevlo }
161855929a15Skevlo if (i == 500)
161955929a15Skevlo printf("%s: timeout waiting for phy to stabilize\n",
162055929a15Skevlo sc->ure_dev.dv_xname);
16218a3a1b1fSkevlo
16228a3a1b1fSkevlo return reg;
16238a3a1b1fSkevlo }
16248a3a1b1fSkevlo
16258a3a1b1fSkevlo void
ure_wait_for_flash(struct ure_softc * sc)16268a3a1b1fSkevlo ure_wait_for_flash(struct ure_softc *sc)
16278a3a1b1fSkevlo {
16288a3a1b1fSkevlo int i;
16298a3a1b1fSkevlo
16308a3a1b1fSkevlo if ((ure_read_2(sc, URE_PLA_GPHY_CTRL, URE_MCU_TYPE_PLA) &
16318a3a1b1fSkevlo URE_GPHY_FLASH) &&
16328a3a1b1fSkevlo !(ure_read_2(sc, URE_USB_GPHY_CTRL, URE_MCU_TYPE_USB) &
16338a3a1b1fSkevlo URE_BYPASS_FLASH)) {
16348a3a1b1fSkevlo for (i = 0; i < 100; i++) {
16358a3a1b1fSkevlo if (ure_read_2(sc, URE_USB_GPHY_CTRL,
16368a3a1b1fSkevlo URE_MCU_TYPE_USB) & URE_GPHY_PATCH_DONE)
16378a3a1b1fSkevlo break;
16388a3a1b1fSkevlo DELAY(1000);
16398a3a1b1fSkevlo }
16408a3a1b1fSkevlo if (i == 100)
16418a3a1b1fSkevlo printf("%s: timeout waiting for loading flash\n",
16428a3a1b1fSkevlo sc->ure_dev.dv_xname);
16438a3a1b1fSkevlo }
164455929a15Skevlo }
164555929a15Skevlo
164655929a15Skevlo void
ure_reset_bmu(struct ure_softc * sc)164755929a15Skevlo ure_reset_bmu(struct ure_softc *sc)
164855929a15Skevlo {
16498a3a1b1fSkevlo uint8_t reg;
16508a3a1b1fSkevlo
16518a3a1b1fSkevlo reg = ure_read_1(sc, URE_USB_BMU_RESET, URE_MCU_TYPE_USB);
16528a3a1b1fSkevlo reg &= ~(BMU_RESET_EP_IN | BMU_RESET_EP_OUT);
16538a3a1b1fSkevlo ure_write_1(sc, URE_USB_BMU_RESET, URE_MCU_TYPE_USB, reg);
16548a3a1b1fSkevlo reg |= BMU_RESET_EP_IN | BMU_RESET_EP_OUT;
16558a3a1b1fSkevlo ure_write_1(sc, URE_USB_BMU_RESET, URE_MCU_TYPE_USB, reg);
165655929a15Skevlo }
165755929a15Skevlo
165855929a15Skevlo void
ure_disable_teredo(struct ure_softc * sc)165955929a15Skevlo ure_disable_teredo(struct ure_softc *sc)
166055929a15Skevlo {
16618a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156 | URE_FLAG_8156B))
166255929a15Skevlo ure_write_1(sc, URE_PLA_TEREDO_CFG, URE_MCU_TYPE_PLA, 0xff);
166355929a15Skevlo else {
166455929a15Skevlo URE_CLRBIT_2(sc, URE_PLA_TEREDO_CFG, URE_MCU_TYPE_PLA,
166555929a15Skevlo URE_TEREDO_SEL | URE_TEREDO_RS_EVENT_MASK |
166655929a15Skevlo URE_OOB_TEREDO_EN);
166755929a15Skevlo }
166855929a15Skevlo ure_write_2(sc, URE_PLA_WDT6_CTRL, URE_MCU_TYPE_PLA, URE_WDT6_SET_MODE);
166955929a15Skevlo ure_write_2(sc, URE_PLA_REALWOW_TIMER, URE_MCU_TYPE_PLA, 0);
167055929a15Skevlo ure_write_4(sc, URE_PLA_TEREDO_TIMER, URE_MCU_TYPE_PLA, 0);
167142c54c93Sjmatthew }
167242c54c93Sjmatthew
167342c54c93Sjmatthew int
ure_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data)167442c54c93Sjmatthew ure_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
167542c54c93Sjmatthew {
1676114e9c63Sderaadt struct ure_softc *sc = ifp->if_softc;
167742c54c93Sjmatthew struct ifreq *ifr = (struct ifreq *)data;
167842c54c93Sjmatthew int s, error = 0;
167942c54c93Sjmatthew
168042c54c93Sjmatthew s = splnet();
168142c54c93Sjmatthew
168242c54c93Sjmatthew switch (cmd) {
168342c54c93Sjmatthew case SIOCSIFADDR:
168442c54c93Sjmatthew ifp->if_flags |= IFF_UP;
168542c54c93Sjmatthew if (!(ifp->if_flags & IFF_RUNNING))
168642c54c93Sjmatthew ure_init(sc);
168742c54c93Sjmatthew break;
168842c54c93Sjmatthew
168942c54c93Sjmatthew case SIOCSIFFLAGS:
169042c54c93Sjmatthew if (ifp->if_flags & IFF_UP) {
169142c54c93Sjmatthew if (ifp->if_flags & IFF_RUNNING)
169242c54c93Sjmatthew error = ENETRESET;
169342c54c93Sjmatthew else
169442c54c93Sjmatthew ure_init(sc);
169542c54c93Sjmatthew } else {
169642c54c93Sjmatthew if (ifp->if_flags & IFF_RUNNING)
169742c54c93Sjmatthew ure_stop(sc);
169842c54c93Sjmatthew }
169942c54c93Sjmatthew break;
170042c54c93Sjmatthew
170142c54c93Sjmatthew case SIOCGIFMEDIA:
170242c54c93Sjmatthew case SIOCSIFMEDIA:
17038a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B))
1704c096a1a3Skevlo error = ifmedia_ioctl(ifp, ifr, &sc->ure_ifmedia, cmd);
1705c096a1a3Skevlo else
1706c096a1a3Skevlo error = ifmedia_ioctl(ifp, ifr, &sc->ure_mii.mii_media,
1707c096a1a3Skevlo cmd);
170842c54c93Sjmatthew break;
170942c54c93Sjmatthew
171042c54c93Sjmatthew default:
171142c54c93Sjmatthew error = ether_ioctl(ifp, &sc->ure_ac, cmd, data);
171242c54c93Sjmatthew }
171342c54c93Sjmatthew
171442c54c93Sjmatthew if (error == ENETRESET) {
171542c54c93Sjmatthew if (ifp->if_flags & IFF_RUNNING)
171642c54c93Sjmatthew ure_iff(sc);
171742c54c93Sjmatthew error = 0;
171842c54c93Sjmatthew }
171942c54c93Sjmatthew
172042c54c93Sjmatthew splx(s);
172142c54c93Sjmatthew
172242c54c93Sjmatthew return (error);
172342c54c93Sjmatthew }
172442c54c93Sjmatthew
172542c54c93Sjmatthew int
ure_match(struct device * parent,void * match,void * aux)172642c54c93Sjmatthew ure_match(struct device *parent, void *match, void *aux)
172742c54c93Sjmatthew {
172842c54c93Sjmatthew struct usb_attach_arg *uaa = aux;
172942c54c93Sjmatthew
173042c54c93Sjmatthew if (uaa->iface == NULL || uaa->configno != 1)
173155929a15Skevlo return (UMATCH_NONE);
173242c54c93Sjmatthew
173342c54c93Sjmatthew return (usb_lookup(ure_devs, uaa->vendor, uaa->product) != NULL ?
173442c54c93Sjmatthew UMATCH_VENDOR_PRODUCT_CONF_IFACE : UMATCH_NONE);
173542c54c93Sjmatthew }
173642c54c93Sjmatthew
173742c54c93Sjmatthew void
ure_attach(struct device * parent,struct device * self,void * aux)173842c54c93Sjmatthew ure_attach(struct device *parent, struct device *self, void *aux)
173942c54c93Sjmatthew {
174042c54c93Sjmatthew struct ure_softc *sc = (struct ure_softc *)self;
174142c54c93Sjmatthew struct usb_attach_arg *uaa = aux;
174242c54c93Sjmatthew usb_interface_descriptor_t *id;
174342c54c93Sjmatthew usb_endpoint_descriptor_t *ed;
174442c54c93Sjmatthew u_char eaddr[8]; /* 4byte padded */
174542c54c93Sjmatthew struct ifnet *ifp;
1746c096a1a3Skevlo int i, mii_flags = 0, s;
174742c54c93Sjmatthew uint16_t ver;
174842c54c93Sjmatthew
174942c54c93Sjmatthew sc->ure_udev = uaa->device;
175042c54c93Sjmatthew sc->ure_iface = uaa->iface;
175142c54c93Sjmatthew
175242c54c93Sjmatthew usb_init_task(&sc->ure_tick_task, ure_tick_task, sc,
175342c54c93Sjmatthew USB_TASK_TYPE_GENERIC);
175442c54c93Sjmatthew
175542c54c93Sjmatthew id = usbd_get_interface_descriptor(sc->ure_iface);
175642c54c93Sjmatthew
175742c54c93Sjmatthew for (i = 0; i < id->bNumEndpoints; i++) {
175842c54c93Sjmatthew ed = usbd_interface2endpoint_descriptor(sc->ure_iface, i);
175942c54c93Sjmatthew if (!ed) {
176042c54c93Sjmatthew printf("%s: couldn't get ep %d\n",
176142c54c93Sjmatthew sc->ure_dev.dv_xname, i);
176242c54c93Sjmatthew return;
176342c54c93Sjmatthew }
176442c54c93Sjmatthew if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
176542c54c93Sjmatthew UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
176642c54c93Sjmatthew sc->ure_ed[URE_ENDPT_RX] = ed->bEndpointAddress;
176742c54c93Sjmatthew } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
176842c54c93Sjmatthew UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
176942c54c93Sjmatthew sc->ure_ed[URE_ENDPT_TX] = ed->bEndpointAddress;
177042c54c93Sjmatthew }
177142c54c93Sjmatthew }
177242c54c93Sjmatthew
1773fd07ab7eSkevlo sc->ure_txbufsz = URE_TX_BUFSZ;
1774fd07ab7eSkevlo sc->ure_rxbufsz = URE_8153_RX_BUFSZ;
1775c096a1a3Skevlo
177642c54c93Sjmatthew s = splnet();
177742c54c93Sjmatthew
177842c54c93Sjmatthew sc->ure_phyno = 0;
177942c54c93Sjmatthew printf("%s: ", sc->ure_dev.dv_xname);
178042c54c93Sjmatthew
178142c54c93Sjmatthew ver = ure_read_2(sc, URE_PLA_TCR1, URE_MCU_TYPE_PLA) & URE_VERSION_MASK;
178242c54c93Sjmatthew switch (ver) {
178342c54c93Sjmatthew case 0x4c00:
1784fd07ab7eSkevlo sc->ure_flags = URE_FLAG_8152;
1785fd07ab7eSkevlo sc->ure_rxbufsz = URE_8152_RX_BUFSZ;
178642c54c93Sjmatthew sc->ure_chip |= URE_CHIP_VER_4C00;
1787c096a1a3Skevlo printf("RTL8152 (0x4c00)");
178842c54c93Sjmatthew break;
178942c54c93Sjmatthew case 0x4c10:
1790fd07ab7eSkevlo sc->ure_flags = URE_FLAG_8152;
1791fd07ab7eSkevlo sc->ure_rxbufsz = URE_8152_RX_BUFSZ;
179242c54c93Sjmatthew sc->ure_chip |= URE_CHIP_VER_4C10;
1793c096a1a3Skevlo printf("RTL8152 (0x4c10)");
1794794a317fSkettenis break;
1795794a317fSkettenis case 0x5c00:
1796794a317fSkettenis sc->ure_chip |= URE_CHIP_VER_5C00;
1797c096a1a3Skevlo printf("RTL8153 (0x5c00)");
1798794a317fSkettenis break;
1799794a317fSkettenis case 0x5c10:
1800794a317fSkettenis sc->ure_chip |= URE_CHIP_VER_5C10;
1801c096a1a3Skevlo printf("RTL8153 (0x5c10)");
1802794a317fSkettenis break;
1803794a317fSkettenis case 0x5c20:
1804794a317fSkettenis sc->ure_chip |= URE_CHIP_VER_5C20;
1805c096a1a3Skevlo printf("RTL8153 (0x5c20)");
1806794a317fSkettenis break;
1807794a317fSkettenis case 0x5c30:
1808794a317fSkettenis sc->ure_chip |= URE_CHIP_VER_5C30;
1809c096a1a3Skevlo printf("RTL8153 (0x5c30)");
181042c54c93Sjmatthew break;
181155929a15Skevlo case 0x6000:
181255929a15Skevlo sc->ure_flags = URE_FLAG_8153B;
1813c096a1a3Skevlo printf("RTL8153B (0x6000)");
181455929a15Skevlo break;
181555929a15Skevlo case 0x6010:
181655929a15Skevlo sc->ure_flags = URE_FLAG_8153B;
1817c096a1a3Skevlo printf("RTL8153B (0x6010)");
1818c096a1a3Skevlo break;
1819c096a1a3Skevlo case 0x7020:
1820fd07ab7eSkevlo sc->ure_flags = URE_FLAG_8156;
1821c096a1a3Skevlo printf("RTL8156 (0x7020)");
1822c096a1a3Skevlo break;
1823c096a1a3Skevlo case 0x7030:
1824fd07ab7eSkevlo sc->ure_flags = URE_FLAG_8156;
1825c096a1a3Skevlo printf("RTL8156 (0x7030)");
182655929a15Skevlo break;
18278a3a1b1fSkevlo case 0x7410:
18288a3a1b1fSkevlo sc->ure_flags = URE_FLAG_8156B;
18298a3a1b1fSkevlo printf("RTL8156B (0x7410)");
18308a3a1b1fSkevlo break;
18313dd6ed5fSkevlo case 0x7420:
18323dd6ed5fSkevlo sc->ure_flags = URE_FLAG_8156B;
18333dd6ed5fSkevlo sc->ure_chip = URE_CHIP_VER_7420;
18343dd6ed5fSkevlo printf("RTL8153D (0x7420)");
18353dd6ed5fSkevlo break;
183642c54c93Sjmatthew default:
183742c54c93Sjmatthew printf(", unknown ver %02x", ver);
183842c54c93Sjmatthew break;
183942c54c93Sjmatthew }
184042c54c93Sjmatthew
1841794a317fSkettenis if (sc->ure_flags & URE_FLAG_8152)
1842794a317fSkettenis ure_rtl8152_init(sc);
18438a3a1b1fSkevlo else if (sc->ure_flags & (URE_FLAG_8153B | URE_FLAG_8156 |
18448a3a1b1fSkevlo URE_FLAG_8156B))
184555929a15Skevlo ure_rtl8153b_init(sc);
1846794a317fSkettenis else
1847794a317fSkettenis ure_rtl8153_init(sc);
1848794a317fSkettenis
1849794a317fSkettenis if (sc->ure_chip & URE_CHIP_VER_4C00)
1850794a317fSkettenis ure_read_mem(sc, URE_PLA_IDR, URE_MCU_TYPE_PLA, eaddr,
1851794a317fSkettenis sizeof(eaddr));
1852794a317fSkettenis else
1853794a317fSkettenis ure_read_mem(sc, URE_PLA_BACKUP, URE_MCU_TYPE_PLA, eaddr,
1854794a317fSkettenis sizeof(eaddr));
1855794a317fSkettenis
185642c54c93Sjmatthew printf(", address %s\n", ether_sprintf(eaddr));
185742c54c93Sjmatthew
185842c54c93Sjmatthew bcopy(eaddr, (char *)&sc->ure_ac.ac_enaddr, ETHER_ADDR_LEN);
185942c54c93Sjmatthew
186042c54c93Sjmatthew ifp = &sc->ure_ac.ac_if;
186142c54c93Sjmatthew ifp->if_softc = sc;
186242c54c93Sjmatthew strlcpy(ifp->if_xname, sc->ure_dev.dv_xname, IFNAMSIZ);
186342c54c93Sjmatthew ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
186442c54c93Sjmatthew ifp->if_ioctl = ure_ioctl;
186542c54c93Sjmatthew ifp->if_start = ure_start;
1866c096a1a3Skevlo ifp->if_watchdog = ure_watchdog;
186742c54c93Sjmatthew
1868c096a1a3Skevlo ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_CSUM_IPv4 |
1869c096a1a3Skevlo IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4;
187042c54c93Sjmatthew
1871c096a1a3Skevlo #if NVLAN > 0
1872c096a1a3Skevlo ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
1873c096a1a3Skevlo #endif
1874c096a1a3Skevlo
18758a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B)) {
1876c096a1a3Skevlo ifmedia_init(&sc->ure_ifmedia, IFM_IMASK, ure_ifmedia_upd,
1877c096a1a3Skevlo ure_ifmedia_sts);
1878c096a1a3Skevlo ure_add_media_types(sc);
1879c096a1a3Skevlo ifmedia_add(&sc->ure_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL);
1880c096a1a3Skevlo ifmedia_set(&sc->ure_ifmedia, IFM_ETHER | IFM_AUTO);
1881c096a1a3Skevlo sc->ure_ifmedia.ifm_media = sc->ure_ifmedia.ifm_cur->ifm_media;
1882c096a1a3Skevlo } else {
1883c096a1a3Skevlo rw_init(&sc->ure_mii_lock, "uremii");
1884c096a1a3Skevlo
1885c096a1a3Skevlo sc->ure_mii.mii_ifp = ifp;
1886c096a1a3Skevlo sc->ure_mii.mii_readreg = ure_miibus_readreg;
1887c096a1a3Skevlo sc->ure_mii.mii_writereg = ure_miibus_writereg;
1888c096a1a3Skevlo sc->ure_mii.mii_statchg = ure_miibus_statchg;
1889c096a1a3Skevlo sc->ure_mii.mii_flags = MIIF_AUTOTSLEEP;
1890c096a1a3Skevlo
1891c096a1a3Skevlo ifmedia_init(&sc->ure_mii.mii_media, 0, ure_ifmedia_upd,
1892c096a1a3Skevlo ure_ifmedia_sts);
189355929a15Skevlo if (!(sc->ure_flags & URE_FLAG_8152))
189455929a15Skevlo mii_flags |= MIIF_DOPAUSE;
1895c096a1a3Skevlo mii_attach(self, &sc->ure_mii, 0xffffffff, sc->ure_phyno,
1896c096a1a3Skevlo MII_OFFSET_ANY, mii_flags);
1897c096a1a3Skevlo if (LIST_FIRST(&sc->ure_mii.mii_phys) == NULL) {
1898c096a1a3Skevlo ifmedia_add(&sc->ure_mii.mii_media,
1899c096a1a3Skevlo IFM_ETHER | IFM_NONE, 0, NULL);
1900c096a1a3Skevlo ifmedia_set(&sc->ure_mii.mii_media,
1901c096a1a3Skevlo IFM_ETHER | IFM_NONE);
190242c54c93Sjmatthew } else
1903c096a1a3Skevlo ifmedia_set(&sc->ure_mii.mii_media,
1904c096a1a3Skevlo IFM_ETHER | IFM_AUTO);
1905c096a1a3Skevlo }
190642c54c93Sjmatthew
190742c54c93Sjmatthew if_attach(ifp);
190842c54c93Sjmatthew ether_ifattach(ifp);
190942c54c93Sjmatthew
191042c54c93Sjmatthew timeout_set(&sc->ure_stat_ch, ure_tick, sc);
191142c54c93Sjmatthew
191242c54c93Sjmatthew splx(s);
191342c54c93Sjmatthew }
191442c54c93Sjmatthew
191542c54c93Sjmatthew int
ure_detach(struct device * self,int flags)191642c54c93Sjmatthew ure_detach(struct device *self, int flags)
191742c54c93Sjmatthew {
191842c54c93Sjmatthew struct ure_softc *sc = (struct ure_softc *)self;
191942c54c93Sjmatthew struct ifnet *ifp = &sc->ure_ac.ac_if;
192042c54c93Sjmatthew int s;
192142c54c93Sjmatthew
192242c54c93Sjmatthew if (timeout_initialized(&sc->ure_stat_ch))
192342c54c93Sjmatthew timeout_del(&sc->ure_stat_ch);
192442c54c93Sjmatthew
192542c54c93Sjmatthew if (sc->ure_ep[URE_ENDPT_TX] != NULL)
192642c54c93Sjmatthew usbd_abort_pipe(sc->ure_ep[URE_ENDPT_TX]);
192742c54c93Sjmatthew if (sc->ure_ep[URE_ENDPT_RX] != NULL)
192842c54c93Sjmatthew usbd_abort_pipe(sc->ure_ep[URE_ENDPT_RX]);
192942c54c93Sjmatthew
193042c54c93Sjmatthew usb_rem_task(sc->ure_udev, &sc->ure_tick_task);
193142c54c93Sjmatthew
193242c54c93Sjmatthew s = splusb();
193342c54c93Sjmatthew
193442c54c93Sjmatthew if (--sc->ure_refcnt >= 0) {
193542c54c93Sjmatthew usb_detach_wait(&sc->ure_dev);
193642c54c93Sjmatthew }
193742c54c93Sjmatthew
193842c54c93Sjmatthew if (ifp->if_flags & IFF_RUNNING)
193942c54c93Sjmatthew ure_stop(sc);
194042c54c93Sjmatthew
194142c54c93Sjmatthew mii_detach(&sc->ure_mii, MII_PHY_ANY, MII_OFFSET_ANY);
194242c54c93Sjmatthew ifmedia_delete_instance(&sc->ure_mii.mii_media, IFM_INST_ANY);
194342c54c93Sjmatthew if (ifp->if_softc != NULL) {
194442c54c93Sjmatthew ether_ifdetach(ifp);
194542c54c93Sjmatthew if_detach(ifp);
194642c54c93Sjmatthew }
194742c54c93Sjmatthew
194842c54c93Sjmatthew splx(s);
194942c54c93Sjmatthew
195042c54c93Sjmatthew return 0;
195142c54c93Sjmatthew }
195242c54c93Sjmatthew
195342c54c93Sjmatthew void
ure_tick_task(void * xsc)195442c54c93Sjmatthew ure_tick_task(void *xsc)
195542c54c93Sjmatthew {
195642c54c93Sjmatthew struct ure_softc *sc = xsc;
195742c54c93Sjmatthew struct mii_data *mii;
1958fd07ab7eSkevlo int s;
195942c54c93Sjmatthew
196042c54c93Sjmatthew if (sc == NULL)
196142c54c93Sjmatthew return;
196242c54c93Sjmatthew
196342c54c93Sjmatthew if (usbd_is_dying(sc->ure_udev))
196442c54c93Sjmatthew return;
196542c54c93Sjmatthew mii = &sc->ure_mii;
196642c54c93Sjmatthew
196742c54c93Sjmatthew s = splnet();
19688a3a1b1fSkevlo if (sc->ure_flags & (URE_FLAG_8156 | URE_FLAG_8156B))
1969c096a1a3Skevlo ure_link_state(sc);
1970c096a1a3Skevlo else {
197142c54c93Sjmatthew mii_tick(mii);
197242c54c93Sjmatthew if ((sc->ure_flags & URE_FLAG_LINK) == 0)
197342c54c93Sjmatthew ure_miibus_statchg(&sc->ure_dev);
1974c096a1a3Skevlo }
197542c54c93Sjmatthew timeout_add_sec(&sc->ure_stat_ch, 1);
197642c54c93Sjmatthew splx(s);
197742c54c93Sjmatthew }
197842c54c93Sjmatthew
197942c54c93Sjmatthew void
ure_lock_mii(struct ure_softc * sc)198042c54c93Sjmatthew ure_lock_mii(struct ure_softc *sc)
198142c54c93Sjmatthew {
198242c54c93Sjmatthew sc->ure_refcnt++;
198342c54c93Sjmatthew rw_enter_write(&sc->ure_mii_lock);
198442c54c93Sjmatthew }
198542c54c93Sjmatthew
198642c54c93Sjmatthew void
ure_unlock_mii(struct ure_softc * sc)198742c54c93Sjmatthew ure_unlock_mii(struct ure_softc *sc)
198842c54c93Sjmatthew {
198942c54c93Sjmatthew rw_exit_write(&sc->ure_mii_lock);
199042c54c93Sjmatthew if (--sc->ure_refcnt < 0)
199142c54c93Sjmatthew usb_detach_wakeup(&sc->ure_dev);
199242c54c93Sjmatthew }
199342c54c93Sjmatthew
199442c54c93Sjmatthew void
ure_rxeof(struct usbd_xfer * xfer,void * priv,usbd_status status)199542c54c93Sjmatthew ure_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
199642c54c93Sjmatthew {
199742c54c93Sjmatthew struct ure_chain *c = (struct ure_chain *)priv;
199842c54c93Sjmatthew struct ure_softc *sc = c->uc_sc;
199942c54c93Sjmatthew struct ifnet *ifp = &sc->ure_ac.ac_if;
200042c54c93Sjmatthew u_char *buf = c->uc_buf;
2001c096a1a3Skevlo uint32_t cflags, rxvlan, total_len;
200242c54c93Sjmatthew struct mbuf_list ml = MBUF_LIST_INITIALIZER();
200342c54c93Sjmatthew struct mbuf *m;
2004c096a1a3Skevlo int pktlen = 0, s;
200542c54c93Sjmatthew struct ure_rxpkt rxhdr;
200642c54c93Sjmatthew
200742c54c93Sjmatthew if (usbd_is_dying(sc->ure_udev))
200842c54c93Sjmatthew return;
200942c54c93Sjmatthew
201042c54c93Sjmatthew if (!(ifp->if_flags & IFF_RUNNING))
201142c54c93Sjmatthew return;
201242c54c93Sjmatthew
201342c54c93Sjmatthew if (status != USBD_NORMAL_COMPLETION) {
201442c54c93Sjmatthew if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
201542c54c93Sjmatthew return;
201642c54c93Sjmatthew if (usbd_ratecheck(&sc->ure_rx_notice)) {
201742c54c93Sjmatthew printf("%s: usb errors on rx: %s\n",
201842c54c93Sjmatthew sc->ure_dev.dv_xname, usbd_errstr(status));
201942c54c93Sjmatthew }
202042c54c93Sjmatthew if (status == USBD_STALLED)
2021c096a1a3Skevlo usbd_clear_endpoint_stall_async(
2022c096a1a3Skevlo sc->ure_ep[URE_ENDPT_RX]);
202342c54c93Sjmatthew goto done;
202442c54c93Sjmatthew }
202542c54c93Sjmatthew
202642c54c93Sjmatthew usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
202742c54c93Sjmatthew DPRINTFN(3, ("received %d bytes\n", total_len));
202842c54c93Sjmatthew
202942c54c93Sjmatthew do {
203042c54c93Sjmatthew if (total_len < sizeof(rxhdr)) {
203142c54c93Sjmatthew DPRINTF(("too few bytes left for a packet header\n"));
203242c54c93Sjmatthew ifp->if_ierrors++;
203342c54c93Sjmatthew goto done;
203442c54c93Sjmatthew }
203542c54c93Sjmatthew
2036fd07ab7eSkevlo buf += roundup(pktlen, URE_RX_BUF_ALIGN);
203742c54c93Sjmatthew
203842c54c93Sjmatthew memcpy(&rxhdr, buf, sizeof(rxhdr));
203942c54c93Sjmatthew total_len -= sizeof(rxhdr);
204042c54c93Sjmatthew
2041c096a1a3Skevlo pktlen = letoh32(rxhdr.ure_pktlen) & URE_RXPKT_LEN_MASK;
204242c54c93Sjmatthew DPRINTFN(4, ("next packet is %d bytes\n", pktlen));
204342c54c93Sjmatthew if (pktlen > total_len) {
204442c54c93Sjmatthew DPRINTF(("not enough bytes left for next packet\n"));
204542c54c93Sjmatthew ifp->if_ierrors++;
204642c54c93Sjmatthew goto done;
204742c54c93Sjmatthew }
204842c54c93Sjmatthew
2049fd07ab7eSkevlo total_len -= roundup(pktlen, URE_RX_BUF_ALIGN);
205042c54c93Sjmatthew buf += sizeof(rxhdr);
205142c54c93Sjmatthew
20528a3a1b1fSkevlo m = m_devget(buf, pktlen - ETHER_CRC_LEN, ETHER_ALIGN);
205342c54c93Sjmatthew if (m == NULL) {
205442c54c93Sjmatthew DPRINTF(("unable to allocate mbuf for next packet\n"));
205542c54c93Sjmatthew ifp->if_ierrors++;
205642c54c93Sjmatthew goto done;
205742c54c93Sjmatthew }
205842c54c93Sjmatthew
2059c096a1a3Skevlo cflags = letoh32(rxhdr.ure_csum);
2060c096a1a3Skevlo rxvlan = letoh32(rxhdr.ure_vlan);
2061c096a1a3Skevlo
2062c096a1a3Skevlo /* Check IP header checksum. */
2063c096a1a3Skevlo if ((rxvlan & URE_RXPKT_IPV4) &&
2064c096a1a3Skevlo !(cflags & URE_RXPKT_IPSUMBAD))
2065c096a1a3Skevlo m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
2066c096a1a3Skevlo
2067c096a1a3Skevlo /* Check TCP/UDP checksum. */
2068c096a1a3Skevlo if ((rxvlan & (URE_RXPKT_IPV4 | URE_RXPKT_IPV6)) &&
2069c096a1a3Skevlo (((rxvlan & URE_RXPKT_TCP) &&
2070c096a1a3Skevlo !(cflags & URE_RXPKT_TCPSUMBAD)) ||
2071c096a1a3Skevlo ((rxvlan & URE_RXPKT_UDP) &&
2072c096a1a3Skevlo !(cflags & URE_RXPKT_UDPSUMBAD))))
2073c096a1a3Skevlo m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK |
2074c096a1a3Skevlo M_UDP_CSUM_IN_OK;
2075c096a1a3Skevlo #if NVLAN > 0
2076c096a1a3Skevlo if (rxvlan & URE_RXPKT_VLAN_TAG) {
2077c096a1a3Skevlo m->m_pkthdr.ether_vtag =
2078c096a1a3Skevlo swap16(rxvlan & URE_RXPKT_VLAN_DATA);
2079c096a1a3Skevlo m->m_flags |= M_VLANTAG;
2080c096a1a3Skevlo }
2081c096a1a3Skevlo #endif
2082c096a1a3Skevlo
208342c54c93Sjmatthew ml_enqueue(&ml, m);
208442c54c93Sjmatthew } while (total_len > 0);
208542c54c93Sjmatthew
208642c54c93Sjmatthew done:
208742c54c93Sjmatthew s = splnet();
208842c54c93Sjmatthew if_input(ifp, &ml);
208942c54c93Sjmatthew splx(s);
2090c096a1a3Skevlo memset(c->uc_buf, 0, sc->ure_rxbufsz);
209142c54c93Sjmatthew
209242c54c93Sjmatthew usbd_setup_xfer(xfer, sc->ure_ep[URE_ENDPT_RX], c, c->uc_buf,
2093c096a1a3Skevlo sc->ure_rxbufsz, USBD_SHORT_XFER_OK | USBD_NO_COPY,
209442c54c93Sjmatthew USBD_NO_TIMEOUT, ure_rxeof);
209542c54c93Sjmatthew usbd_transfer(xfer);
209642c54c93Sjmatthew }
209742c54c93Sjmatthew
209842c54c93Sjmatthew
209942c54c93Sjmatthew void
ure_txeof(struct usbd_xfer * xfer,void * priv,usbd_status status)210042c54c93Sjmatthew ure_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
210142c54c93Sjmatthew {
210242c54c93Sjmatthew struct ure_softc *sc;
210342c54c93Sjmatthew struct ure_chain *c;
210442c54c93Sjmatthew struct ifnet *ifp;
210542c54c93Sjmatthew int s;
210642c54c93Sjmatthew
210742c54c93Sjmatthew c = priv;
210842c54c93Sjmatthew sc = c->uc_sc;
210942c54c93Sjmatthew ifp = &sc->ure_ac.ac_if;
211042c54c93Sjmatthew
211142c54c93Sjmatthew if (usbd_is_dying(sc->ure_udev))
211242c54c93Sjmatthew return;
211342c54c93Sjmatthew
2114fd07ab7eSkevlo if (status != USBD_NORMAL_COMPLETION)
2115fd07ab7eSkevlo DPRINTF(("%s: %s uc_idx=%u : %s\n", sc->ure_dev.dv_xname,
2116fd07ab7eSkevlo __func__, c->uc_idx, usbd_errstr(status)));
211742c54c93Sjmatthew
211842c54c93Sjmatthew s = splnet();
2119fd07ab7eSkevlo
2120fd07ab7eSkevlo c->uc_cnt = 0;
2121fd07ab7eSkevlo c->uc_buflen = 0;
2122fd07ab7eSkevlo
2123fd07ab7eSkevlo SLIST_INSERT_HEAD(&sc->ure_cdata.ure_tx_free, c, uc_list);
2124fd07ab7eSkevlo
212542c54c93Sjmatthew if (status != USBD_NORMAL_COMPLETION) {
212642c54c93Sjmatthew if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
212742c54c93Sjmatthew splx(s);
212842c54c93Sjmatthew return;
212942c54c93Sjmatthew }
2130fd07ab7eSkevlo
213142c54c93Sjmatthew ifp->if_oerrors++;
213242c54c93Sjmatthew printf("%s: usb error on tx: %s\n", sc->ure_dev.dv_xname,
213342c54c93Sjmatthew usbd_errstr(status));
2134fd07ab7eSkevlo
213542c54c93Sjmatthew if (status == USBD_STALLED)
2136c096a1a3Skevlo usbd_clear_endpoint_stall_async(
2137c096a1a3Skevlo sc->ure_ep[URE_ENDPT_TX]);
213842c54c93Sjmatthew splx(s);
213942c54c93Sjmatthew return;
214042c54c93Sjmatthew }
214142c54c93Sjmatthew
214242c54c93Sjmatthew ifp->if_timer = 0;
2143fd07ab7eSkevlo if (ifq_is_oactive(&ifp->if_snd))
2144fd07ab7eSkevlo ifq_restart(&ifp->if_snd);
214542c54c93Sjmatthew splx(s);
214642c54c93Sjmatthew }
214742c54c93Sjmatthew
214842c54c93Sjmatthew int
ure_encap_txpkt(struct mbuf * m,char * buf,uint32_t maxlen)2149fd07ab7eSkevlo ure_encap_txpkt(struct mbuf *m, char *buf, uint32_t maxlen)
215042c54c93Sjmatthew {
215142c54c93Sjmatthew struct ure_txpkt txhdr;
2152fd07ab7eSkevlo uint32_t len = sizeof(txhdr), cflags = 0;
2153fd07ab7eSkevlo
2154fd07ab7eSkevlo if (len + m->m_pkthdr.len > maxlen)
2155fd07ab7eSkevlo return (-1);
215642c54c93Sjmatthew
2157c096a1a3Skevlo if ((m->m_pkthdr.csum_flags &
2158c096a1a3Skevlo (M_IPV4_CSUM_OUT | M_TCP_CSUM_OUT | M_UDP_CSUM_OUT)) != 0) {
2159c096a1a3Skevlo cflags |= URE_TXPKT_IPV4;
2160c096a1a3Skevlo if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT)
2161c096a1a3Skevlo cflags |= URE_TXPKT_TCP;
2162c096a1a3Skevlo if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT)
2163c096a1a3Skevlo cflags |= URE_TXPKT_UDP;
2164c096a1a3Skevlo }
2165c096a1a3Skevlo
2166c096a1a3Skevlo #if NVLAN > 0
2167c096a1a3Skevlo if (m->m_flags & M_VLANTAG)
2168fe07c298Ssthen cflags |= URE_TXPKT_VLAN_TAG | swap16(m->m_pkthdr.ether_vtag);
2169c096a1a3Skevlo #endif
2170c096a1a3Skevlo
2171c096a1a3Skevlo txhdr.ure_pktlen = htole32(m->m_pkthdr.len | URE_TXPKT_TX_FS |
217242c54c93Sjmatthew URE_TXPKT_TX_LS);
2173c096a1a3Skevlo txhdr.ure_vlan = htole32(cflags);
2174fd07ab7eSkevlo memcpy(buf, &txhdr, len);
217542c54c93Sjmatthew
2176fd07ab7eSkevlo m_copydata(m, 0, m->m_pkthdr.len, buf + len);
2177fd07ab7eSkevlo len += m->m_pkthdr.len;
217842c54c93Sjmatthew
2179fd07ab7eSkevlo return (len);
2180fd07ab7eSkevlo }
218142c54c93Sjmatthew
2182fd07ab7eSkevlo int
ure_encap_xfer(struct ifnet * ifp,struct ure_softc * sc,struct ure_chain * c)2183fd07ab7eSkevlo ure_encap_xfer(struct ifnet *ifp, struct ure_softc *sc, struct ure_chain *c)
2184fd07ab7eSkevlo {
2185fd07ab7eSkevlo usbd_status err;
2186fd07ab7eSkevlo
218742c54c93Sjmatthew usbd_setup_xfer(c->uc_xfer, sc->ure_ep[URE_ENDPT_TX], c, c->uc_buf,
2188fd07ab7eSkevlo c->uc_buflen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 10000,
2189fd07ab7eSkevlo ure_txeof);
219042c54c93Sjmatthew
219142c54c93Sjmatthew err = usbd_transfer(c->uc_xfer);
2192fd07ab7eSkevlo if (err != USBD_IN_PROGRESS) {
2193fd07ab7eSkevlo c->uc_cnt = 0;
2194fd07ab7eSkevlo c->uc_buflen = 0;
219542c54c93Sjmatthew ure_stop(sc);
2196c096a1a3Skevlo return (EIO);
219742c54c93Sjmatthew }
219842c54c93Sjmatthew
2199c096a1a3Skevlo return (0);
220042c54c93Sjmatthew }
2201