[384] | 1 | /*-
|
---|
| 2 | * Copyright (c) 2011 Rick van der Zwet <info@rickvanderzwet.nl>
|
---|
| 3 | *
|
---|
| 4 | * Permission to use, copy, modify, and distribute this software for any
|
---|
| 5 | * purpose with or without fee is hereby granted, provided that the above
|
---|
| 6 | * copyright notice and this permission notice appear in all copies.
|
---|
| 7 | *
|
---|
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
---|
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
---|
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
---|
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
---|
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
---|
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
---|
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
---|
| 15 | */
|
---|
| 16 |
|
---|
| 17 | /*-
|
---|
| 18 | * Copyright (c) 2001-2003, Shunsuke Akiyama <akiyama@FreeBSD.org>.
|
---|
| 19 | * Copyright (c) 1997, 1998, 1999, 2000 Bill Paul <wpaul@ee.columbia.edu>.
|
---|
| 20 | * All rights reserved.
|
---|
| 21 | *
|
---|
| 22 | * Redistribution and use in source and binary forms, with or without
|
---|
| 23 | * modification, are permitted provided that the following conditions
|
---|
| 24 | * are met:
|
---|
| 25 | * 1. Redistributions of source code must retain the above copyright
|
---|
| 26 | * notice, this list of conditions and the following disclaimer.
|
---|
| 27 | * 2. Redistributions in binary form must reproduce the above copyright
|
---|
| 28 | * notice, this list of conditions and the following disclaimer in the
|
---|
| 29 | * documentation and/or other materials provided with the distribution.
|
---|
| 30 | *
|
---|
| 31 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
---|
| 32 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
---|
| 33 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
---|
| 34 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
---|
| 35 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
---|
| 36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
---|
| 37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
---|
| 38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
---|
| 39 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
---|
| 40 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
---|
| 41 | * SUCH DAMAGE.
|
---|
| 42 | */
|
---|
| 43 | /*-
|
---|
| 44 | * Copyright (c) 1997, 1998, 1999, 2000
|
---|
| 45 | * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
|
---|
| 46 | *
|
---|
| 47 | * Redistribution and use in source and binary forms, with or without
|
---|
| 48 | * modification, are permitted provided that the following conditions
|
---|
| 49 | * are met:
|
---|
| 50 | * 1. Redistributions of source code must retain the above copyright
|
---|
| 51 | * notice, this list of conditions and the following disclaimer.
|
---|
| 52 | * 2. Redistributions in binary form must reproduce the above copyright
|
---|
| 53 | * notice, this list of conditions and the following disclaimer in the
|
---|
| 54 | * documentation and/or other materials provided with the distribution.
|
---|
| 55 | * 3. All advertising materials mentioning features or use of this software
|
---|
| 56 | * must display the following acknowledgement:
|
---|
| 57 | * This product includes software developed by Bill Paul.
|
---|
| 58 | * 4. Neither the name of the author nor the names of any co-contributors
|
---|
| 59 | * may be used to endorse or promote products derived from this software
|
---|
| 60 | * without specific prior written permission.
|
---|
| 61 | *
|
---|
| 62 | * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
|
---|
| 63 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
---|
| 64 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
---|
| 65 | * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
|
---|
| 66 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
---|
| 67 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
---|
| 68 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
---|
| 69 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
---|
| 70 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
---|
| 71 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
---|
| 72 | * THE POSSIBILITY OF SUCH DAMAGE.
|
---|
| 73 | */
|
---|
| 74 |
|
---|
| 75 | #include <sys/cdefs.h>
|
---|
| 76 | __FBSDID("$FreeBSD: release/10.1.0/sys/dev/usb/net/if_rtl.c 251734 2013-06-14 05:36:47Z kevlo $");
|
---|
| 77 |
|
---|
| 78 | /*
|
---|
| 79 | * RealTek RTL8152 USB to fast ethernet controller driver.
|
---|
| 80 | * http://www.realtek.com.tw/products/productsView.aspx?Langid=1&PFid=55&Level=5&Conn=4&ProdID=323
|
---|
| 81 | *
|
---|
| 82 | * /TODO: With some modification the RealTek RTL8153 USB to fast ethernet
|
---|
| 83 | * controller driver. should also be supported, but yet no hardware to test it
|
---|
| 84 | * http://www.realtek.com.tw/products/productsView.aspx?Langid=1&PFid=56&Level=5&Conn=4&ProdID=326
|
---|
| 85 | *
|
---|
| 86 | */
|
---|
| 87 |
|
---|
| 88 | #include <sys/stdint.h>
|
---|
| 89 | #include <sys/stddef.h>
|
---|
| 90 | #include <sys/param.h>
|
---|
| 91 | #include <sys/queue.h>
|
---|
| 92 | #include <sys/types.h>
|
---|
| 93 | #include <sys/systm.h>
|
---|
| 94 | #include <sys/kernel.h>
|
---|
| 95 | #include <sys/bus.h>
|
---|
| 96 | #include <sys/module.h>
|
---|
| 97 | #include <sys/lock.h>
|
---|
| 98 | #include <sys/mutex.h>
|
---|
| 99 | #include <sys/condvar.h>
|
---|
| 100 | #include <sys/sysctl.h>
|
---|
| 101 | #include <sys/sx.h>
|
---|
| 102 | #include <sys/unistd.h>
|
---|
| 103 | #include <sys/callout.h>
|
---|
| 104 | #include <sys/malloc.h>
|
---|
| 105 | #include <sys/priv.h>
|
---|
| 106 |
|
---|
| 107 | #include <dev/usb/usb.h>
|
---|
| 108 | #include <dev/usb/usbdi.h>
|
---|
| 109 | #include <dev/usb/usbdi_util.h>
|
---|
| 110 | #include "usbdevs.h"
|
---|
| 111 |
|
---|
| 112 | #define USB_DEBUG_VAR rtl_debug
|
---|
| 113 | #include <dev/usb/usb_debug.h>
|
---|
| 114 | #include <dev/usb/usb_process.h>
|
---|
| 115 |
|
---|
| 116 | #include <dev/usb/net/usb_ethernet.h>
|
---|
| 117 | #include <dev/usb/net/if_rtlreg.h>
|
---|
| 118 |
|
---|
| 119 | #ifdef USB_DEBUG
|
---|
| 120 | static int rtl_debug = 1;
|
---|
| 121 |
|
---|
| 122 | static SYSCTL_NODE(_hw_usb, OID_AUTO, rtl, CTLFLAG_RW, 0, "USB rtl");
|
---|
| 123 | SYSCTL_INT(_hw_usb_rtl, OID_AUTO, debug, CTLFLAG_RW,
|
---|
| 124 | &rtl_debug, 0, "Debug level");
|
---|
| 125 | #endif
|
---|
| 126 |
|
---|
| 127 | /*
|
---|
| 128 | * Various supported device vendors/products.
|
---|
| 129 | */
|
---|
| 130 |
|
---|
| 131 | static const STRUCT_USB_HOST_ID rtl_devs[] = {
|
---|
| 132 | {USB_VPI(USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8152, 0)},
|
---|
| 133 | };
|
---|
| 134 |
|
---|
| 135 | /* prototypes */
|
---|
| 136 |
|
---|
| 137 | static device_probe_t rtl_probe;
|
---|
| 138 | static device_attach_t rtl_attach;
|
---|
| 139 | static device_detach_t rtl_detach;
|
---|
| 140 |
|
---|
| 141 | static miibus_readreg_t rtl_miibus_readreg;
|
---|
| 142 | static miibus_writereg_t rtl_miibus_writereg;
|
---|
| 143 | static miibus_statchg_t rtl_miibus_statchg;
|
---|
| 144 |
|
---|
| 145 | static usb_callback_t rtl_intr_callback;
|
---|
| 146 | static usb_callback_t rtl_bulk_read_callback;
|
---|
| 147 | static usb_callback_t rtl_bulk_write_callback;
|
---|
| 148 |
|
---|
| 149 | static uether_fn_t rtl_attach_post;
|
---|
| 150 | static uether_fn_t rtl_init;
|
---|
| 151 | static uether_fn_t rtl_stop;
|
---|
| 152 | static uether_fn_t rtl_start;
|
---|
| 153 | static uether_fn_t rtl_tick;
|
---|
| 154 | static uether_fn_t rtl_setpromisc_and_multi;
|
---|
| 155 |
|
---|
| 156 | static void rtl_reset(struct rtl_softc *);
|
---|
| 157 | static int rtl_ifmedia_upd(struct ifnet *);
|
---|
| 158 | static void rtl_ifmedia_sts(struct ifnet *, struct ifmediareq *);
|
---|
| 159 |
|
---|
| 160 | static const struct usb_config rtl_config[RTL_N_TRANSFER] = {
|
---|
| 161 |
|
---|
| 162 | [RTL_BULK_DT_RD] = {
|
---|
| 163 | .type = UE_BULK,
|
---|
| 164 | .endpoint = UE_ADDR_ANY,
|
---|
| 165 | .direction = UE_DIR_IN,
|
---|
| 166 | .bufsize = 16384,
|
---|
| 167 | .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
|
---|
| 168 | .callback = rtl_bulk_read_callback,
|
---|
| 169 | .timeout = 0, /* no timeout */
|
---|
| 170 | },
|
---|
| 171 |
|
---|
| 172 | [RTL_BULK_DT_WR] = {
|
---|
| 173 | .type = UE_BULK,
|
---|
| 174 | .endpoint = UE_ADDR_ANY,
|
---|
| 175 | .direction = UE_DIR_OUT,
|
---|
| 176 | .bufsize = 16384,
|
---|
| 177 | .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
|
---|
| 178 | .callback = rtl_bulk_write_callback,
|
---|
| 179 | .timeout = 1000, /* 1 seconds */
|
---|
| 180 | },
|
---|
| 181 |
|
---|
| 182 | [RTL_INTR_DT_RD] = {
|
---|
| 183 | .type = UE_INTERRUPT,
|
---|
| 184 | .endpoint = UE_ADDR_ANY,
|
---|
| 185 | .direction = UE_DIR_IN,
|
---|
| 186 | .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
|
---|
| 187 | .bufsize = 0, /* use wMaxPacketSize */
|
---|
| 188 | .callback = rtl_intr_callback,
|
---|
| 189 | },
|
---|
| 190 | };
|
---|
| 191 |
|
---|
| 192 | static device_method_t rtl_methods[] = {
|
---|
| 193 | /* Device interface */
|
---|
| 194 | DEVMETHOD(device_probe, rtl_probe),
|
---|
| 195 | DEVMETHOD(device_attach, rtl_attach),
|
---|
| 196 | DEVMETHOD(device_detach, rtl_detach),
|
---|
| 197 |
|
---|
| 198 | /* MII interface */
|
---|
| 199 | DEVMETHOD(miibus_readreg, rtl_miibus_readreg),
|
---|
| 200 | DEVMETHOD(miibus_writereg, rtl_miibus_writereg),
|
---|
| 201 | DEVMETHOD(miibus_statchg, rtl_miibus_statchg),
|
---|
| 202 |
|
---|
| 203 | DEVMETHOD_END
|
---|
| 204 | };
|
---|
| 205 |
|
---|
| 206 | static driver_t rtl_driver = {
|
---|
| 207 | .name = "rtl",
|
---|
| 208 | .methods = rtl_methods,
|
---|
| 209 | .size = sizeof(struct rtl_softc),
|
---|
| 210 | };
|
---|
| 211 |
|
---|
| 212 | static devclass_t rtl_devclass;
|
---|
| 213 |
|
---|
| 214 | DRIVER_MODULE_ORDERED(rtl, uhub, rtl_driver, rtl_devclass, NULL, NULL,
|
---|
| 215 | SI_ORDER_ANY);
|
---|
| 216 | DRIVER_MODULE(miibus, rtl, miibus_driver, miibus_devclass, NULL, NULL);
|
---|
| 217 | MODULE_DEPEND(rtl, uether, 1, 1, 1);
|
---|
| 218 | MODULE_DEPEND(rtl, usb, 1, 1, 1);
|
---|
| 219 | MODULE_DEPEND(rtl, ether, 1, 1, 1);
|
---|
| 220 | MODULE_DEPEND(rtl, miibus, 1, 1, 1);
|
---|
| 221 | MODULE_VERSION(rtl, 1);
|
---|
| 222 |
|
---|
| 223 | static const struct usb_ether_methods rtl_ue_methods = {
|
---|
| 224 | .ue_attach_post = rtl_attach_post,
|
---|
| 225 | .ue_start = rtl_start,
|
---|
| 226 | .ue_init = rtl_init,
|
---|
| 227 | .ue_stop = rtl_stop,
|
---|
| 228 | .ue_tick = rtl_tick,
|
---|
| 229 | .ue_setmulti = rtl_setpromisc_and_multi,
|
---|
| 230 | .ue_setpromisc = rtl_setpromisc_and_multi,
|
---|
| 231 | .ue_mii_upd = rtl_ifmedia_upd,
|
---|
| 232 | .ue_mii_sts = rtl_ifmedia_sts,
|
---|
| 233 | };
|
---|
| 234 |
|
---|
| 235 | static int
|
---|
| 236 | generic_ocp_read(struct rtl_softc *sc, uint16_t index, uint16_t addr, void *buf, int len)
|
---|
| 237 | {
|
---|
| 238 | struct usb_device_request req;
|
---|
| 239 | // TODO: This seems to be a global defined variable
|
---|
| 240 | uint16_t limit = 64;
|
---|
| 241 | int ret = 0;
|
---|
| 242 |
|
---|
| 243 | /* both size and indix must be 4 bytes align */
|
---|
| 244 | // TODO: Argue whether are supposed to be non-fatal values
|
---|
| 245 | if ((len & 3) || !len || (index & 3) || (!buf)) {
|
---|
| 246 | printf("[foo] generic_ocp_read(len=%x index=%x): not alligned error\n",
|
---|
| 247 | len, index);
|
---|
| 248 | return (ENXIO);
|
---|
| 249 | }
|
---|
| 250 |
|
---|
| 251 | if ((uint32_t)index + (uint32_t)addr > 0xffff) {
|
---|
| 252 | printf("[foo] generic_ocp_read(index=%x addr=%x): overflow error\n",
|
---|
| 253 | len, index);
|
---|
| 254 | return (ENXIO);
|
---|
| 255 | }
|
---|
| 256 |
|
---|
| 257 | //TODO: Deal with the fact if len > limit (block fetching)
|
---|
| 258 | if (len > limit) {
|
---|
| 259 | printf("[foo] generic_ocp_read(len=%x limit=%x): size overflow\n",
|
---|
| 260 | len, limit);
|
---|
| 261 | return (ENXIO);
|
---|
| 262 | }
|
---|
| 263 |
|
---|
| 264 | req.bmRequestType = UT_READ_VENDOR_DEVICE;
|
---|
| 265 | req.bRequest = UR_SET_ADDRESS;
|
---|
| 266 | USETW(req.wIndex, index);
|
---|
| 267 | USETW(req.wValue, addr);
|
---|
| 268 | USETW(req.wLength, len);
|
---|
| 269 |
|
---|
| 270 | ret = uether_do_request(&sc->sc_ue, &req, buf, 500);
|
---|
| 271 | return ret;
|
---|
| 272 | }
|
---|
| 273 |
|
---|
| 274 | static int
|
---|
| 275 | set_registers(struct rtl_softc *sc, uint16_t index, uint16_t addr, void *buf, int len) {
|
---|
| 276 | struct usb_device_request req;
|
---|
| 277 |
|
---|
| 278 | req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
|
---|
| 279 | req.bRequest = UR_SET_ADDRESS;
|
---|
| 280 | USETW(req.wIndex, index);
|
---|
| 281 | USETW(req.wValue, addr);
|
---|
| 282 | USETW(req.wLength, len);
|
---|
| 283 |
|
---|
| 284 | //TODO: Make timeout some kind of define global?
|
---|
| 285 | return (uether_do_request(&sc->sc_ue, &req, buf, 500));
|
---|
| 286 | }
|
---|
| 287 |
|
---|
| 288 | static int
|
---|
| 289 | ocp_write(struct rtl_softc *sc, uint16_t index, uint16_t addr,
|
---|
| 290 | uint16_t byteen, void *buf, int len)
|
---|
| 291 | {
|
---|
| 292 | uint16_t byteen_start, byteen_end, byen;
|
---|
| 293 | uint16_t limit = 512;
|
---|
| 294 | int ret;
|
---|
| 295 |
|
---|
| 296 | /* both size and indix must be 4 bytes align */
|
---|
| 297 | // TODO: Argue whether are supposed to be non-fatal values
|
---|
| 298 | if ((len & 3) || !len || (index & 3) || (!buf)) {
|
---|
| 299 | printf("[foo] ocp_write(len=%x index=%x): not alligned error\n",
|
---|
| 300 | len, index);
|
---|
| 301 | return (ENXIO);
|
---|
| 302 | }
|
---|
| 303 |
|
---|
| 304 | if ((uint32_t)index + (uint32_t)addr > 0xffff) {
|
---|
| 305 | printf("[foo] ocp_write(index=%x addr=%x): overflow error\n",
|
---|
| 306 | len, index);
|
---|
| 307 | return (ENXIO);
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | //TODO: Deal with the fact if len > limit (block fetching)
|
---|
| 311 | if (len > limit) {
|
---|
| 312 | printf("[foo] ocp_write(len=%x limit=%x): size overflow\n",
|
---|
| 313 | len, limit);
|
---|
| 314 | return (ENXIO);
|
---|
| 315 | }
|
---|
| 316 |
|
---|
| 317 | byteen_start = byteen & BYTE_EN_START_MASK;
|
---|
| 318 | byteen_end = byteen & BYTE_EN_END_MASK;
|
---|
| 319 |
|
---|
| 320 | byen = byteen_start | (byteen_start << 4);
|
---|
| 321 |
|
---|
| 322 | ret = set_registers(sc, index, addr | byen , buf, 4);
|
---|
| 323 | if (ret < 0)
|
---|
| 324 | return ret;
|
---|
| 325 |
|
---|
| 326 | //TODO: Implement if size > limit
|
---|
| 327 | return ret;
|
---|
| 328 | }
|
---|
| 329 |
|
---|
| 330 | static uint8_t
|
---|
| 331 | ocp_read_1(struct rtl_softc *sc, uint16_t index, uint16_t addr)
|
---|
| 332 | {
|
---|
| 333 | uint32_t data;
|
---|
| 334 | //TODO: __le32 tmp;
|
---|
| 335 | uint32_t tmp;
|
---|
| 336 |
|
---|
| 337 | generic_ocp_read(sc, index, addr & ~3, &tmp, 4);
|
---|
| 338 |
|
---|
| 339 | //TODO: data = __le32_to_cpu(tmp);
|
---|
| 340 | data = tmp;
|
---|
| 341 | data >>= ((addr & 3) * 8);
|
---|
| 342 | data &= 0xff;
|
---|
| 343 |
|
---|
| 344 | //printf("[foo] ocp_read_1(index=%x, addr=%x) => 0x%x\n", index, addr, data);
|
---|
| 345 |
|
---|
| 346 | return (uint8_t)data;
|
---|
| 347 | }
|
---|
| 348 |
|
---|
| 349 | static uint16_t
|
---|
| 350 | ocp_read_2(struct rtl_softc *sc, uint16_t index, uint16_t addr)
|
---|
| 351 | {
|
---|
| 352 | uint32_t data;
|
---|
| 353 | //TODO: __le32 tmp;
|
---|
| 354 | uint32_t tmp;
|
---|
| 355 |
|
---|
| 356 | generic_ocp_read(sc, index, addr & ~3, &tmp, 4);
|
---|
| 357 |
|
---|
| 358 | //TODO: data = __le32_to_cpu(tmp);
|
---|
| 359 | data = tmp;
|
---|
| 360 | data >>= ((addr & 2) * 8);
|
---|
| 361 | data &= 0xffff;
|
---|
| 362 |
|
---|
| 363 | //printf("[foo] ocp_read_2(index=%x, addr=%x) => tmp=%x data=%x\n", index, addr, tmp, data);
|
---|
| 364 |
|
---|
| 365 | return (uint16_t)data;
|
---|
| 366 | }
|
---|
| 367 |
|
---|
| 368 | static uint32_t
|
---|
| 369 | ocp_read_4(struct rtl_softc *sc, uint16_t index, uint16_t addr)
|
---|
| 370 | {
|
---|
| 371 | uint32_t data;
|
---|
| 372 | //TODO: __le32 tmp;
|
---|
| 373 | uint32_t tmp;
|
---|
| 374 |
|
---|
| 375 | generic_ocp_read(sc, index, addr, &tmp, 4);
|
---|
| 376 |
|
---|
| 377 | //TODO: data = __le32_to_cpu(tmp);
|
---|
| 378 | data = tmp;
|
---|
| 379 |
|
---|
| 380 | return data;
|
---|
| 381 | }
|
---|
| 382 |
|
---|
| 383 | static int
|
---|
| 384 | ocp_write_1(struct rtl_softc *sc, uint16_t index, uint16_t addr, uint8_t val)
|
---|
| 385 | {
|
---|
| 386 | uint32_t mask = 0xff;
|
---|
| 387 | //TODO: __le32 tmp;
|
---|
| 388 | uint32_t tmp;
|
---|
| 389 | uint16_t byten = BYTE_EN_BYTE;
|
---|
| 390 | uint8_t shift = addr & 3;
|
---|
| 391 | uint32_t data = val;
|
---|
| 392 | int ret;
|
---|
| 393 |
|
---|
| 394 | data &= mask;
|
---|
| 395 |
|
---|
| 396 | //printf("[foo] ocp_write_1(index=%x, addr=%x, val=%x)\n", index, addr, val);
|
---|
| 397 |
|
---|
| 398 | if (index & 3) {
|
---|
| 399 | byten <<= shift;
|
---|
| 400 | mask <<= (shift * 8);
|
---|
| 401 | data <<= (shift * 8);
|
---|
| 402 | addr &= ~3;
|
---|
| 403 | }
|
---|
| 404 |
|
---|
| 405 | ret = generic_ocp_read(sc, index, addr, &tmp, 4);
|
---|
| 406 | if (ret < 0)
|
---|
| 407 | return ret;
|
---|
| 408 |
|
---|
| 409 | //TODO: data |= __le32_to_cpu(tmp) & ~mask;
|
---|
| 410 | data |= tmp & ~mask;
|
---|
| 411 | //TODO: tmp = __cpu_to_le32(data);
|
---|
| 412 | tmp = data;
|
---|
| 413 |
|
---|
| 414 | return (ocp_write(sc, index, addr, byten, &tmp, 4));
|
---|
| 415 | }
|
---|
| 416 |
|
---|
| 417 | static int
|
---|
| 418 | ocp_write_2(struct rtl_softc *sc, uint16_t index, uint16_t addr, uint16_t val)
|
---|
| 419 | {
|
---|
| 420 | uint32_t mask = 0xffff;
|
---|
| 421 | //TODO: __le32 tmp;
|
---|
| 422 | uint32_t tmp;
|
---|
| 423 | uint16_t byten = BYTE_EN_WORD;
|
---|
| 424 | uint8_t shift = addr & 2;
|
---|
| 425 | uint32_t data = val;
|
---|
| 426 | int ret;
|
---|
| 427 |
|
---|
| 428 | printf("[foo] ocp_write_2(index=%x, addr=%x, val=%x)\n", index, addr, val);
|
---|
| 429 |
|
---|
| 430 | data &= mask;
|
---|
| 431 |
|
---|
| 432 | if (index & 2) {
|
---|
| 433 | byten <<= shift;
|
---|
| 434 | mask <<= (shift * 8);
|
---|
| 435 | data <<= (shift * 8);
|
---|
| 436 | addr &= ~3;
|
---|
| 437 | }
|
---|
| 438 |
|
---|
| 439 | ret = generic_ocp_read(sc, index, addr, &tmp, 4);
|
---|
| 440 | if (ret < 0)
|
---|
| 441 | return ret;
|
---|
| 442 |
|
---|
| 443 |
|
---|
| 444 | //TODO: data |= __le32_to_cpu(tmp) & ~mask;
|
---|
| 445 | data |= tmp & ~mask;
|
---|
| 446 | //TODO: tmp = __cpu_to_le32(data);
|
---|
| 447 | tmp = data;
|
---|
| 448 |
|
---|
| 449 | return (ocp_write(sc, index, addr, byten, &tmp, 4));
|
---|
| 450 | }
|
---|
| 451 |
|
---|
| 452 |
|
---|
| 453 | static int
|
---|
| 454 | ocp_write_4(struct rtl_softc *sc, uint16_t index, uint16_t addr, uint32_t val)
|
---|
| 455 | {
|
---|
| 456 | //TODO: __le32 tmp;
|
---|
| 457 | uint32_t tmp;
|
---|
| 458 |
|
---|
| 459 | //TODO: tmp = __le32_to_cpu(data);
|
---|
| 460 | tmp = val;
|
---|
| 461 |
|
---|
| 462 | //printf("[foo] ocp_write_4(index=%x, addr=%x, val=%x)\n", index, addr, tmp);
|
---|
| 463 | return (ocp_write(sc, index, addr, BYTE_EN_DWORD, &tmp, 4));
|
---|
| 464 | }
|
---|
| 465 |
|
---|
| 466 | static uint16_t
|
---|
| 467 | ocp_reg_read(struct rtl_softc *sc, uint16_t addr)
|
---|
| 468 | {
|
---|
| 469 | uint16_t ocp_base = addr & 0xf000;
|
---|
| 470 | uint16_t ocp_index = (addr & 0x0fff) | 0xb000;
|
---|
| 471 |
|
---|
| 472 | if (ocp_base != sc->ocp_base) {
|
---|
| 473 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
|
---|
| 474 | sc->ocp_base = ocp_base;
|
---|
| 475 | }
|
---|
| 476 |
|
---|
| 477 | return ocp_read_2(sc, MCU_TYPE_PLA, ocp_index);
|
---|
| 478 | }
|
---|
| 479 |
|
---|
| 480 | static void
|
---|
| 481 | ocp_reg_write(struct rtl_softc *sc, uint16_t addr, uint16_t val)
|
---|
| 482 | {
|
---|
| 483 | uint16_t ocp_base = addr & 0xf000;
|
---|
| 484 | uint16_t ocp_index = (addr & 0x0fff) | 0xb000;
|
---|
| 485 |
|
---|
| 486 | if (ocp_base != sc->ocp_base) {
|
---|
| 487 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
|
---|
| 488 | sc->ocp_base = ocp_base;
|
---|
| 489 | }
|
---|
| 490 |
|
---|
| 491 | ocp_write_2(sc, MCU_TYPE_PLA, ocp_index, val);
|
---|
| 492 | }
|
---|
| 493 |
|
---|
| 494 | static inline void
|
---|
| 495 | r8152_mdio_write(struct rtl_softc *sc, uint32_t addr, uint32_t val)
|
---|
| 496 | {
|
---|
| 497 | ocp_reg_write(sc, OCP_BASE_MII + addr * 2, val);
|
---|
| 498 | }
|
---|
| 499 |
|
---|
| 500 | static inline uint32_t
|
---|
| 501 | r8152_mdio_read(struct rtl_softc *sc, uint32_t addr)
|
---|
| 502 | {
|
---|
| 503 | return ocp_reg_read(sc, OCP_BASE_MII + addr * 2);
|
---|
| 504 | }
|
---|
| 505 |
|
---|
| 506 | static int
|
---|
| 507 | rtl_miibus_readreg(device_t dev, int phy, int reg)
|
---|
| 508 | {
|
---|
| 509 | //printf("[foo] rtl_miibus_readreg(phy=%x, reg=%x)\n", phy, reg);
|
---|
| 510 | struct rtl_softc *sc = device_get_softc(dev);
|
---|
| 511 | uint16_t rval;
|
---|
| 512 | int locked;
|
---|
| 513 |
|
---|
| 514 | if (phy != 0) /* RTL8152 supports PHY == 0, only */
|
---|
| 515 | return (0);
|
---|
| 516 |
|
---|
| 517 | locked = mtx_owned(&sc->sc_mtx);
|
---|
| 518 | if (!locked)
|
---|
| 519 | RTL_LOCK(sc);
|
---|
| 520 |
|
---|
| 521 | rval = r8152_mdio_read(sc, reg);
|
---|
| 522 |
|
---|
| 523 | if (!locked)
|
---|
| 524 | RTL_UNLOCK(sc);
|
---|
| 525 | //printf("[foo] rtl_miibus_readreg(phy=%x, reg=%x) => rval=%x\n", phy, reg, rval);
|
---|
| 526 | return (rval);
|
---|
| 527 | }
|
---|
| 528 |
|
---|
| 529 | static int
|
---|
| 530 | rtl_miibus_writereg(device_t dev, int phy, int reg, int data)
|
---|
| 531 | {
|
---|
| 532 | printf("[foo] rtl_miibus_writereg(phy=%x reg=%x data=%x\n", phy, reg, data);
|
---|
| 533 | return (0);
|
---|
| 534 | struct rtl_softc *sc = device_get_softc(dev);
|
---|
| 535 | int locked;
|
---|
| 536 |
|
---|
| 537 | if (phy != 0) /* RTL8152 supports PHY == 0, only */
|
---|
| 538 | return (0);
|
---|
| 539 |
|
---|
| 540 | locked = mtx_owned(&sc->sc_mtx);
|
---|
| 541 | if (!locked)
|
---|
| 542 | RTL_LOCK(sc);
|
---|
| 543 |
|
---|
| 544 | r8152_mdio_write(sc, reg, data);
|
---|
| 545 |
|
---|
| 546 | if (!locked)
|
---|
| 547 | RTL_UNLOCK(sc);
|
---|
| 548 | return (0);
|
---|
| 549 | }
|
---|
| 550 |
|
---|
| 551 | static void
|
---|
| 552 | rtl_miibus_statchg(device_t dev)
|
---|
| 553 | {
|
---|
| 554 | printf("[foo] %s\n", __func__);
|
---|
| 555 | #if 0
|
---|
| 556 | struct rtl_softc *sc = device_get_softc(dev);
|
---|
| 557 | struct mii_data *mii = GET_MII(sc);
|
---|
| 558 | uint16_t bmcr;
|
---|
| 559 | int locked;
|
---|
| 560 |
|
---|
| 561 | locked = mtx_owned(&sc->sc_mtx);
|
---|
| 562 | if (!locked)
|
---|
| 563 | RTL_LOCK(sc);
|
---|
| 564 |
|
---|
| 565 | RTL_CLRBIT(sc, RTL_CR, (RTL_CR_RE | RTL_CR_TE));
|
---|
| 566 |
|
---|
| 567 | bmcr = rtl_csr_read_2(sc, RTL_BMCR);
|
---|
| 568 |
|
---|
| 569 | if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX)
|
---|
| 570 | bmcr |= RTL_BMCR_SPD_SET;
|
---|
| 571 | else
|
---|
| 572 | bmcr &= ~RTL_BMCR_SPD_SET;
|
---|
| 573 |
|
---|
| 574 | if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
|
---|
| 575 | bmcr |= RTL_BMCR_DUPLEX;
|
---|
| 576 | else
|
---|
| 577 | bmcr &= ~RTL_BMCR_DUPLEX;
|
---|
| 578 |
|
---|
| 579 | rtl_csr_write_2(sc, RTL_BMCR, bmcr);
|
---|
| 580 |
|
---|
| 581 | RTL_SETBIT(sc, RTL_CR, (RTL_CR_RE | RTL_CR_TE));
|
---|
| 582 |
|
---|
| 583 | if (!locked)
|
---|
| 584 | RTL_UNLOCK(sc);
|
---|
| 585 | #endif
|
---|
| 586 | }
|
---|
| 587 |
|
---|
| 588 | //TODO: Make global defines
|
---|
| 589 | static const int multicast_filter_limit = 32;
|
---|
| 590 | //static const unsigned int agg_buf_sz = 16384;
|
---|
| 591 |
|
---|
| 592 |
|
---|
| 593 | /*
|
---|
| 594 | * Program the 64-bit multicast hash filter and promiscuous mode
|
---|
| 595 | */
|
---|
| 596 | static void
|
---|
| 597 | rtl_setpromisc_and_multi(struct usb_ether *ue)
|
---|
| 598 | {
|
---|
| 599 | printf("[foo] %s\n", __func__);
|
---|
| 600 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
| 601 | struct ifnet *ifp = uether_getifp(ue);
|
---|
| 602 | int h = 0;
|
---|
| 603 | uint32_t hashes[2] = { 0, 0 };
|
---|
| 604 | uint32_t tmp[2];
|
---|
| 605 | uint32_t ocp_data;
|
---|
| 606 | struct ifmultiaddr *ifma;
|
---|
| 607 | int mcnt = 0;
|
---|
| 608 |
|
---|
| 609 | RTL_LOCK_ASSERT(sc, MA_OWNED);
|
---|
| 610 |
|
---|
| 611 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_RCR);
|
---|
| 612 | ocp_data &= ~RCR_ACPT_ALL;
|
---|
| 613 | ocp_data |= RCR_AB | RCR_APM;
|
---|
| 614 |
|
---|
| 615 |
|
---|
| 616 | /* Make multicast filter */
|
---|
| 617 | if_maddr_rlock(ifp);
|
---|
| 618 | TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link)
|
---|
| 619 | {
|
---|
| 620 | if (ifma->ifma_addr->sa_family != AF_LINK)
|
---|
| 621 | continue;
|
---|
| 622 | h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
|
---|
| 623 | ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
|
---|
| 624 |
|
---|
| 625 | hashes[h >> 5] |= 1 << (h & 31);
|
---|
| 626 | mcnt++;
|
---|
| 627 | }
|
---|
| 628 | if_maddr_runlock(ifp);
|
---|
| 629 |
|
---|
| 630 |
|
---|
| 631 | if (ifp->if_flags & IFF_PROMISC) {
|
---|
| 632 | ocp_data |= RCR_AM | RCR_AAP;
|
---|
| 633 | hashes[0] = 0xffffffff;
|
---|
| 634 | hashes[1] = 0xffffffff;
|
---|
| 635 | } else if ((mcnt > multicast_filter_limit) ||
|
---|
| 636 | (ifp->if_flags & IFF_ALLMULTI)) {
|
---|
| 637 | /* Too many to filter perfectly -- accept all multicasts. */
|
---|
| 638 | ocp_data |= RCR_AM;
|
---|
| 639 | hashes[0] = 0xffffffff;
|
---|
| 640 | hashes[1] = 0xffffffff;
|
---|
| 641 | } else if (mcnt > 0) {
|
---|
| 642 | ocp_data |= RCR_AM;
|
---|
| 643 | }
|
---|
| 644 |
|
---|
| 645 | //TODO: tmp[0] = __cpu_to_le32(swab32(mc_filter[1]));
|
---|
| 646 | //TODO: tmp[1] = __cpu_to_le32(swab32(mc_filter[0]));
|
---|
| 647 | tmp[0] = hashes[0];
|
---|
| 648 | tmp[1] = hashes[1];
|
---|
| 649 |
|
---|
| 650 | ocp_write(sc, MCU_TYPE_PLA, PLA_MAR, BYTE_EN_DWORD, tmp, sizeof(tmp));
|
---|
| 651 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RCR, ocp_data);
|
---|
| 652 | }
|
---|
| 653 |
|
---|
| 654 | static void
|
---|
| 655 | rtl_reset(struct rtl_softc *sc)
|
---|
| 656 | {
|
---|
| 657 | printf("[foo] %s\n", __func__);
|
---|
| 658 | int i;
|
---|
| 659 |
|
---|
| 660 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CR, CR_RST);
|
---|
| 661 |
|
---|
| 662 | for (i = 0; i != RTL_TIMEOUT; i++) {
|
---|
| 663 | if (uether_pause(&sc->sc_ue, hz / 1000))
|
---|
| 664 | break;
|
---|
| 665 | if (!(ocp_read_1(sc, MCU_TYPE_PLA, PLA_CR) & CR_RST))
|
---|
| 666 | break;
|
---|
| 667 | }
|
---|
| 668 |
|
---|
| 669 | if (i == RTL_TIMEOUT)
|
---|
| 670 | device_printf(sc->sc_ue.ue_dev, "reset never completed\n");
|
---|
| 671 |
|
---|
| 672 | uether_pause(&sc->sc_ue, hz / 100);
|
---|
| 673 | }
|
---|
| 674 |
|
---|
| 675 | static void
|
---|
| 676 | rtl_attach_post(struct usb_ether *ue)
|
---|
| 677 | {
|
---|
| 678 | printf("[foo] %s\n", __func__);
|
---|
| 679 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
| 680 | int ret;
|
---|
| 681 |
|
---|
| 682 | /* reset the adapter */
|
---|
| 683 | rtl_reset(sc);
|
---|
| 684 |
|
---|
| 685 | uint32_t ocp_data;
|
---|
| 686 | uint16_t version;
|
---|
| 687 |
|
---|
| 688 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_TCR1);
|
---|
| 689 | version = (uint16_t)(ocp_data & VERSION_MASK);
|
---|
| 690 | switch (version) {
|
---|
| 691 | case 0x4c00:
|
---|
| 692 | sc->version = RTL_VER_01;
|
---|
| 693 | break;
|
---|
| 694 | case 0x4c10:
|
---|
| 695 | sc->version = RTL_VER_02;
|
---|
| 696 | break;
|
---|
| 697 | case 0x5c00:
|
---|
| 698 | sc->version = RTL_VER_03;
|
---|
| 699 | break;
|
---|
| 700 | case 0x5c10:
|
---|
| 701 | sc->version = RTL_VER_04;
|
---|
| 702 | break;
|
---|
| 703 | case 0x5c20:
|
---|
| 704 | sc->version = RTL_VER_05;
|
---|
| 705 | break;
|
---|
| 706 | default:
|
---|
| 707 | printf("[foo] Unknown version 0x%04x\n", version);
|
---|
| 708 | break;
|
---|
| 709 | }
|
---|
| 710 | printf("[foo] ocp_data=%x version=%x\n", ocp_data, version);
|
---|
| 711 |
|
---|
| 712 | /* Get station address from the EEPROM which needs to be aligned */
|
---|
| 713 | //TODO: Allign automatically(?)
|
---|
| 714 | if (sc->version == RTL_VER_01)
|
---|
| 715 | ret = generic_ocp_read(sc, MCU_TYPE_PLA, PLA_IDR, ue->ue_eaddr, 8);
|
---|
| 716 | else
|
---|
| 717 | ret = generic_ocp_read(sc, MCU_TYPE_PLA, PLA_BACKUP,ue->ue_eaddr, 8);
|
---|
| 718 |
|
---|
| 719 | printf("[foo] attach_post: Read MAC address (version=%x ret=%x mac=%s\n", sc->version, ret, ue->ue_eaddr);
|
---|
| 720 |
|
---|
| 721 | if (ret < 0) {
|
---|
| 722 | //TODO: How-to handle failures and/or invalid MAC addresses
|
---|
| 723 | printf("[foo] attach_post: Get ether addr fail\n");
|
---|
| 724 | //TODO: should we make a random MAC address?
|
---|
| 725 | // } else if (!is_valid_ether_addr(ue->ue_eaddr)) {
|
---|
| 726 | // TODO: If no MAC is returned the device is crashed and needs to be
|
---|
| 727 | // power-cycled, how-to inform user?
|
---|
| 728 | } else {
|
---|
| 729 | /* Later versions needs to have the MAC copied to the working location */
|
---|
| 730 | if (sc->version != RTL_VER_01) {
|
---|
| 731 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
|
---|
| 732 | ocp_write(sc, MCU_TYPE_PLA, PLA_IDR, BYTE_EN_SIX_BYTES,
|
---|
| 733 | ue->ue_eaddr, 8);
|
---|
| 734 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
|
---|
| 735 | }
|
---|
| 736 | }
|
---|
| 737 | }
|
---|
| 738 |
|
---|
| 739 | /*
|
---|
| 740 | * Probe for a RTL8150 chip.
|
---|
| 741 | */
|
---|
| 742 | static int
|
---|
| 743 | rtl_probe(device_t dev)
|
---|
| 744 | {
|
---|
| 745 | printf("[foo] %s\n", __func__);
|
---|
| 746 | struct usb_attach_arg *uaa = device_get_ivars(dev);
|
---|
| 747 |
|
---|
| 748 | if (uaa->usb_mode != USB_MODE_HOST)
|
---|
| 749 | return (ENXIO);
|
---|
| 750 | if (uaa->info.bConfigIndex != RTL_CONFIG_IDX)
|
---|
| 751 | return (ENXIO);
|
---|
| 752 | if (uaa->info.bIfaceIndex != RTL_IFACE_IDX)
|
---|
| 753 | return (ENXIO);
|
---|
| 754 |
|
---|
| 755 | return (usbd_lookup_id_by_uaa(rtl_devs, sizeof(rtl_devs), uaa));
|
---|
| 756 | }
|
---|
| 757 |
|
---|
| 758 | /*
|
---|
| 759 | * Attach the interface. Allocate softc structures, do ifmedia
|
---|
| 760 | * setup and ethernet/BPF attach.
|
---|
| 761 | */
|
---|
| 762 | static int
|
---|
| 763 | rtl_attach(device_t dev)
|
---|
| 764 | {
|
---|
| 765 | printf("[foo] %s\n", __func__);
|
---|
| 766 | struct usb_attach_arg *uaa = device_get_ivars(dev);
|
---|
| 767 | struct rtl_softc *sc = device_get_softc(dev);
|
---|
| 768 | struct usb_ether *ue = &sc->sc_ue;
|
---|
| 769 | uint8_t iface_index;
|
---|
| 770 | int error;
|
---|
| 771 |
|
---|
| 772 | device_set_usb_desc(dev);
|
---|
| 773 | mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
|
---|
| 774 |
|
---|
| 775 | iface_index = RTL_IFACE_IDX;
|
---|
| 776 | error = usbd_transfer_setup(uaa->device, &iface_index,
|
---|
| 777 | sc->sc_xfer, rtl_config, RTL_N_TRANSFER,
|
---|
| 778 | sc, &sc->sc_mtx);
|
---|
| 779 | if (error) {
|
---|
| 780 | device_printf(dev, "allocating USB transfers failed\n");
|
---|
| 781 | goto detach;
|
---|
| 782 | }
|
---|
| 783 |
|
---|
| 784 | ue->ue_sc = sc;
|
---|
| 785 | ue->ue_dev = dev;
|
---|
| 786 | ue->ue_udev = uaa->device;
|
---|
| 787 | ue->ue_mtx = &sc->sc_mtx;
|
---|
| 788 | ue->ue_methods = &rtl_ue_methods;
|
---|
| 789 |
|
---|
| 790 | error = uether_ifattach(ue);
|
---|
| 791 | if (error) {
|
---|
| 792 | device_printf(dev, "could not attach interface\n");
|
---|
| 793 | goto detach;
|
---|
| 794 | }
|
---|
| 795 | return (0); /* success */
|
---|
| 796 |
|
---|
| 797 | detach:
|
---|
| 798 | rtl_detach(dev);
|
---|
| 799 | return (ENXIO); /* failure */
|
---|
| 800 | }
|
---|
| 801 |
|
---|
| 802 | static int
|
---|
| 803 | rtl_detach(device_t dev)
|
---|
| 804 | {
|
---|
| 805 | printf("[foo] %s\n", __func__);
|
---|
| 806 | struct rtl_softc *sc = device_get_softc(dev);
|
---|
| 807 | struct usb_ether *ue = &sc->sc_ue;
|
---|
| 808 |
|
---|
| 809 | usbd_transfer_unsetup(sc->sc_xfer, RTL_N_TRANSFER);
|
---|
| 810 | uether_ifdetach(ue);
|
---|
| 811 | mtx_destroy(&sc->sc_mtx);
|
---|
| 812 |
|
---|
| 813 | return (0);
|
---|
| 814 | }
|
---|
| 815 |
|
---|
| 816 | static void
|
---|
| 817 | rtl_intr_callback(struct usb_xfer *xfer, usb_error_t error)
|
---|
| 818 | {
|
---|
| 819 | //struct rtl_softc *sc = usbd_xfer_softc(xfer);
|
---|
| 820 | //struct ifnet *ifp = uether_getifp(&sc->sc_ue);
|
---|
| 821 | //struct rtl_intrpkt pkt;
|
---|
| 822 | uint32_t pkt;
|
---|
| 823 | struct usb_page_cache *pc;
|
---|
| 824 | int actlen;
|
---|
| 825 |
|
---|
| 826 | usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
|
---|
| 827 |
|
---|
| 828 | //printf("[foo] rtl_intr_callback USB_STATE=%i\n", USB_GET_STATE(xfer));
|
---|
| 829 | switch (USB_GET_STATE(xfer)) {
|
---|
| 830 | case USB_ST_TRANSFERRED:
|
---|
| 831 |
|
---|
| 832 | //if (ifp && (ifp->if_drv_flags & IFF_DRV_RUNNING) &&
|
---|
| 833 | // actlen >= (int)sizeof(pkt)) {
|
---|
| 834 | //if (ifp && (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
---|
| 835 |
|
---|
| 836 | pc = usbd_xfer_get_frame(xfer, 0);
|
---|
| 837 | usbd_copy_out(pc, 0, &pkt, sizeof(pkt));
|
---|
| 838 | //printf("[foo] rtl_intr_callback pkt=%x actlen=%i\n", pkt, actlen);
|
---|
| 839 |
|
---|
| 840 | //ifp->if_ierrors += pkt.rtl_rxlost_cnt;
|
---|
| 841 | //ifp->if_ierrors += pkt.rtl_crcerr_cnt;
|
---|
| 842 | //ifp->if_collisions += pkt.rtl_col_cnt;
|
---|
| 843 | //}
|
---|
| 844 | /* FALLTHROUGH */
|
---|
| 845 | case USB_ST_SETUP:
|
---|
| 846 | tr_setup:
|
---|
| 847 | usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
|
---|
| 848 | usbd_transfer_submit(xfer);
|
---|
| 849 | return;
|
---|
| 850 |
|
---|
| 851 | default:
|
---|
| 852 | if (error != USB_ERR_CANCELLED) {
|
---|
| 853 | usbd_xfer_set_stall(xfer);
|
---|
| 854 | goto tr_setup;
|
---|
| 855 | }
|
---|
| 856 | return;
|
---|
| 857 | }
|
---|
| 858 | }
|
---|
| 859 |
|
---|
| 860 | static void
|
---|
| 861 | rtl_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
---|
| 862 | {
|
---|
| 863 | struct rtl_softc *sc = usbd_xfer_softc(xfer);
|
---|
| 864 | struct usb_ether *ue = &sc->sc_ue;
|
---|
| 865 | //struct ifnet *ifp = uether_getifp(ue);
|
---|
| 866 | struct usb_page_cache *pc;
|
---|
| 867 | struct rx_desc rx_desc;
|
---|
| 868 | //uint16_t status;
|
---|
| 869 | int actlen;
|
---|
| 870 | int pos = 0;
|
---|
| 871 | unsigned int pkt_len;
|
---|
| 872 |
|
---|
| 873 | usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
|
---|
| 874 |
|
---|
| 875 | printf("[foo] rtl_bulk_read_callback USB_STATE=%i actlen=%d\n", USB_GET_STATE(xfer), actlen);
|
---|
| 876 | switch (USB_GET_STATE(xfer)) {
|
---|
| 877 | case USB_ST_TRANSFERRED:
|
---|
| 878 | pc = usbd_xfer_get_frame(xfer, 0);
|
---|
| 879 |
|
---|
| 880 | while (actlen > pos) {
|
---|
| 881 | usbd_copy_out(pc, pos, &rx_desc, sizeof(rx_desc));
|
---|
| 882 | pos += (sizeof rx_desc);
|
---|
| 883 |
|
---|
| 884 | pkt_len = rx_desc.opts1 & RX_LEN_MASK;
|
---|
| 885 | printf("[foo] pkt_len=%d\n", pkt_len);
|
---|
| 886 |
|
---|
| 887 | //ETH_ZLEN (Min. octents in frame sans FCS)
|
---|
| 888 | if (pkt_len < 60)
|
---|
| 889 | break;
|
---|
| 890 |
|
---|
| 891 | // TODO: Should we flag this as errors
|
---|
| 892 | if (actlen < (pos + pkt_len))
|
---|
| 893 | break;
|
---|
| 894 |
|
---|
| 895 | // TODO: Chipset supports CRC and VLAN tagging
|
---|
| 896 | uether_rxbuf(ue, pc, pos, pkt_len - CRC_SIZE);
|
---|
| 897 |
|
---|
| 898 | pos += pkt_len;
|
---|
| 899 | //TODO: Data get aligned?
|
---|
| 900 | }
|
---|
| 901 | /* FALLTHROUGH */
|
---|
| 902 | case USB_ST_SETUP:
|
---|
| 903 | tr_setup:
|
---|
| 904 | usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
|
---|
| 905 | usbd_transfer_submit(xfer);
|
---|
| 906 | uether_rxflush(ue);
|
---|
| 907 | return;
|
---|
| 908 |
|
---|
| 909 | default: /* Error */
|
---|
| 910 | printf("[foo] bulk read error, %s\n",
|
---|
| 911 | usbd_errstr(error));
|
---|
| 912 |
|
---|
| 913 | if (error != USB_ERR_CANCELLED) {
|
---|
| 914 | /* try to clear stall first */
|
---|
| 915 | usbd_xfer_set_stall(xfer);
|
---|
| 916 | goto tr_setup;
|
---|
| 917 | }
|
---|
| 918 | return;
|
---|
| 919 | }
|
---|
| 920 | }
|
---|
| 921 |
|
---|
| 922 | static void
|
---|
| 923 | rtl_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
---|
| 924 | {
|
---|
| 925 | struct rtl_softc *sc = usbd_xfer_softc(xfer);
|
---|
| 926 | struct ifnet *ifp = uether_getifp(&sc->sc_ue);
|
---|
| 927 | struct usb_page_cache *pc;
|
---|
| 928 | struct mbuf *m;
|
---|
| 929 | int pos;
|
---|
| 930 | struct tx_desc tx_desc;
|
---|
| 931 |
|
---|
| 932 | printf("[foo] rtl_bulk_write_callback USB_STATE=%i\n", USB_GET_STATE(xfer));
|
---|
| 933 | switch (USB_GET_STATE(xfer)) {
|
---|
| 934 | case USB_ST_TRANSFERRED:
|
---|
| 935 | printf("[foo] rtl_bulk_write_callback: transfer complete\n");
|
---|
| 936 | DPRINTFN(11, "transfer complete\n");
|
---|
| 937 | ifp->if_opackets++;
|
---|
| 938 |
|
---|
| 939 | /* FALLTHROUGH */
|
---|
| 940 | case USB_ST_SETUP:
|
---|
| 941 | tr_setup:
|
---|
| 942 | //if ((sc->sc_flags & RTL_FLAG_LINK) == 0) {
|
---|
| 943 | // printf("[foo] rtl_bulk_write_callback: error no link!\n");
|
---|
| 944 | // /*
|
---|
| 945 | // * don't send anything if there is no link !
|
---|
| 946 | // */
|
---|
| 947 | // return;
|
---|
| 948 | //}
|
---|
| 949 | IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
---|
| 950 | if (m == NULL)
|
---|
| 951 | return;
|
---|
| 952 |
|
---|
| 953 | //if (m->m_pkthdr.len > MCLBYTES)
|
---|
| 954 | // m->m_pkthdr.len = MCLBYTES;
|
---|
| 955 | //temp_len = m->m_pkthdr.len;
|
---|
| 956 |
|
---|
| 957 | pos = 0;
|
---|
| 958 | pc = usbd_xfer_get_frame(xfer, 0);
|
---|
| 959 |
|
---|
| 960 | // Header description
|
---|
| 961 | // //TODO: Complete CRC
|
---|
| 962 | int transport_offset = 0;
|
---|
| 963 | tx_desc.opts1 = m->m_pkthdr.len | TX_FS | TX_LS;
|
---|
| 964 | tx_desc.opts1 |= transport_offset << GTTCPHO_SHIFT;
|
---|
| 965 | tx_desc.opts1 |= GTSENDV4;
|
---|
| 966 |
|
---|
| 967 | usbd_copy_in(pc, pos, &tx_desc, sizeof(tx_desc));
|
---|
| 968 | pos += sizeof(tx_desc);
|
---|
| 969 |
|
---|
| 970 | // Content
|
---|
| 971 | usbd_m_copy_in(pc, pos, m, 0, m->m_pkthdr.len);
|
---|
| 972 | pos += m->m_pkthdr.len;
|
---|
| 973 |
|
---|
| 974 |
|
---|
| 975 | printf("[foo] rtl_bulk_write_callback len=%i\n", m->m_pkthdr.len);
|
---|
| 976 | int i;
|
---|
| 977 | for (i = 0; i < m->m_pkthdr.len; i++)
|
---|
| 978 | printf("%x", m->m_data[i]);
|
---|
| 979 | printf("\n");
|
---|
| 980 |
|
---|
| 981 | usbd_xfer_set_frame_len(xfer, 0, pos);
|
---|
| 982 |
|
---|
| 983 | /*
|
---|
| 984 | * if there's a BPF listener, bounce a copy
|
---|
| 985 | * of this frame to him:
|
---|
| 986 | */
|
---|
| 987 | BPF_MTAP(ifp, m);
|
---|
| 988 |
|
---|
| 989 | m_freem(m);
|
---|
| 990 |
|
---|
| 991 | usbd_transfer_submit(xfer);
|
---|
| 992 |
|
---|
| 993 | return;
|
---|
| 994 |
|
---|
| 995 | default: /* Error */
|
---|
| 996 | printf("[foo] bulk write: transfer error, %s\n", usbd_errstr(error));
|
---|
| 997 | ifp->if_oerrors++;
|
---|
| 998 |
|
---|
| 999 | if (error != USB_ERR_CANCELLED) {
|
---|
| 1000 | /* try to clear stall first */
|
---|
| 1001 | usbd_xfer_set_stall(xfer);
|
---|
| 1002 | goto tr_setup;
|
---|
| 1003 | }
|
---|
| 1004 | return;
|
---|
| 1005 | }
|
---|
| 1006 | }
|
---|
| 1007 |
|
---|
| 1008 | static void
|
---|
| 1009 | rtl_tick(struct usb_ether *ue)
|
---|
| 1010 | {
|
---|
| 1011 | printf("[foo] %s\n", __func__);
|
---|
| 1012 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
| 1013 | struct mii_data *mii = GET_MII(sc);
|
---|
| 1014 |
|
---|
| 1015 | RTL_LOCK_ASSERT(sc, MA_OWNED);
|
---|
| 1016 |
|
---|
| 1017 | mii_tick(mii);
|
---|
| 1018 | if ((sc->sc_flags & RTL_FLAG_LINK) == 0
|
---|
| 1019 | && mii->mii_media_status & IFM_ACTIVE &&
|
---|
| 1020 | IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
|
---|
| 1021 | sc->sc_flags |= RTL_FLAG_LINK;
|
---|
| 1022 | rtl_start(ue);
|
---|
| 1023 | }
|
---|
| 1024 | }
|
---|
| 1025 |
|
---|
| 1026 | static void
|
---|
| 1027 | rtl8152_set_mac_address(struct usb_ether *ue)
|
---|
| 1028 | {
|
---|
| 1029 | printf("[foo] %s\n", __func__);
|
---|
| 1030 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
| 1031 |
|
---|
| 1032 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
|
---|
| 1033 | ocp_write(sc, MCU_TYPE_PLA, PLA_IDR, BYTE_EN_SIX_BYTES, ue->ue_eaddr, 8);
|
---|
| 1034 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
|
---|
| 1035 | }
|
---|
| 1036 |
|
---|
| 1037 | static void
|
---|
| 1038 | r8152b_reset_packet_filter(struct rtl_softc *sc)
|
---|
| 1039 | {
|
---|
| 1040 | printf("[foo] %s\n", __func__);
|
---|
| 1041 | uint32_t ocp_data;
|
---|
| 1042 |
|
---|
| 1043 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_FMC);
|
---|
| 1044 | ocp_data &= ~FMC_FCR_MCU_EN;
|
---|
| 1045 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_FMC, ocp_data);
|
---|
| 1046 | ocp_data |= FMC_FCR_MCU_EN;
|
---|
| 1047 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_FMC, ocp_data);
|
---|
| 1048 | }
|
---|
| 1049 |
|
---|
| 1050 | static void
|
---|
| 1051 | rtl8152_nic_reset(struct rtl_softc *sc)
|
---|
| 1052 | {
|
---|
| 1053 | printf("[foo] %s\n", __func__);
|
---|
| 1054 | int i;
|
---|
| 1055 |
|
---|
| 1056 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CR, CR_RST);
|
---|
| 1057 |
|
---|
| 1058 | for (i = 0; i < 1000; i++) {
|
---|
| 1059 | if (!(ocp_read_1(sc, MCU_TYPE_PLA, PLA_CR) & CR_RST))
|
---|
| 1060 | break;
|
---|
| 1061 | uether_pause(&sc->sc_ue, hz / 100);
|
---|
| 1062 | }
|
---|
| 1063 | }
|
---|
| 1064 |
|
---|
| 1065 | static inline uint8_t
|
---|
| 1066 | rtl8152_get_speed(struct rtl_softc* sc)
|
---|
| 1067 | {
|
---|
| 1068 | printf("[foo] %s\n", __func__);
|
---|
| 1069 | return ocp_read_1(sc, MCU_TYPE_PLA, PLA_PHYSTATUS);
|
---|
| 1070 | }
|
---|
| 1071 |
|
---|
| 1072 | static void
|
---|
| 1073 | rtl_set_eee_plus(struct rtl_softc *sc)
|
---|
| 1074 | {
|
---|
| 1075 | printf("[foo] %s\n", __func__);
|
---|
| 1076 | uint32_t ocp_data;
|
---|
| 1077 | uint8_t speed;
|
---|
| 1078 |
|
---|
| 1079 | speed = rtl8152_get_speed(sc);
|
---|
| 1080 | //TODO: Find out which bits represent which speed
|
---|
| 1081 | //if (speed & _10bps) {
|
---|
| 1082 | // ocp_data = ocp_read_2(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
|
---|
| 1083 | // ocp_data |= EEEP_CR_EEEP_TX;
|
---|
| 1084 | // ocp_write_2(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
|
---|
| 1085 | //} else {
|
---|
| 1086 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_EEEP_CR);
|
---|
| 1087 | ocp_data &= ~EEEP_CR_EEEP_TX;
|
---|
| 1088 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
|
---|
| 1089 | //}
|
---|
| 1090 | }
|
---|
| 1091 |
|
---|
| 1092 | static void
|
---|
| 1093 | rxdy_gated_en(struct rtl_softc *sc, bool enable)
|
---|
| 1094 | {
|
---|
| 1095 | printf("[foo] %s\n", __func__);
|
---|
| 1096 | uint32_t ocp_data;
|
---|
| 1097 |
|
---|
| 1098 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_MISC_1);
|
---|
| 1099 | if (enable)
|
---|
| 1100 | ocp_data |= RXDY_GATED_EN;
|
---|
| 1101 | else
|
---|
| 1102 | ocp_data &= ~RXDY_GATED_EN;
|
---|
| 1103 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
|
---|
| 1104 | }
|
---|
| 1105 |
|
---|
| 1106 | static int
|
---|
| 1107 | rtl_enable(struct rtl_softc *sc)
|
---|
| 1108 | {
|
---|
| 1109 | printf("[foo] %s\n", __func__);
|
---|
| 1110 | uint32_t ocp_data;
|
---|
| 1111 |
|
---|
| 1112 | r8152b_reset_packet_filter(sc);
|
---|
| 1113 |
|
---|
| 1114 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_CR);
|
---|
| 1115 | ocp_data |= CR_RE | CR_TE;
|
---|
| 1116 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CR, ocp_data);
|
---|
| 1117 |
|
---|
| 1118 | rxdy_gated_en(sc, false);
|
---|
| 1119 |
|
---|
| 1120 | return 0;
|
---|
| 1121 | }
|
---|
| 1122 |
|
---|
| 1123 |
|
---|
| 1124 | static int
|
---|
| 1125 | rtl8152_enable(struct rtl_softc *sc)
|
---|
| 1126 | {
|
---|
| 1127 | printf("[foo] %s\n", __func__);
|
---|
| 1128 | //set_tx_qlen(sc);
|
---|
| 1129 | rtl_set_eee_plus(sc);
|
---|
| 1130 |
|
---|
| 1131 | return rtl_enable(sc);
|
---|
| 1132 | }
|
---|
| 1133 |
|
---|
| 1134 | static void
|
---|
| 1135 | rtl_disable(struct rtl_softc *sc)
|
---|
| 1136 | {
|
---|
| 1137 | printf("[foo] %s\n", __func__);
|
---|
| 1138 | uint32_t ocp_data;
|
---|
| 1139 | int i;
|
---|
| 1140 |
|
---|
| 1141 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_RCR);
|
---|
| 1142 | ocp_data &= ~RCR_ACPT_ALL;
|
---|
| 1143 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RCR, ocp_data);
|
---|
| 1144 |
|
---|
| 1145 | rxdy_gated_en(sc, true);
|
---|
| 1146 |
|
---|
| 1147 | for (i = 0; i < 1000; i++) {
|
---|
| 1148 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
| 1149 | if ((ocp_data & FIFO_EMPTY) == FIFO_EMPTY)
|
---|
| 1150 | break;
|
---|
| 1151 | uether_pause(&sc->sc_ue, hz / 100);
|
---|
| 1152 | }
|
---|
| 1153 |
|
---|
| 1154 | for (i = 0; i < 1000; i++) {
|
---|
| 1155 | if (ocp_read_2(sc, MCU_TYPE_PLA, PLA_TCR0) & TCR0_TX_EMPTY)
|
---|
| 1156 | break;
|
---|
| 1157 | uether_pause(&sc->sc_ue, hz / 100);
|
---|
| 1158 | }
|
---|
| 1159 |
|
---|
| 1160 | rtl8152_nic_reset(sc);
|
---|
| 1161 | }
|
---|
| 1162 |
|
---|
| 1163 | static void
|
---|
| 1164 | r8152_power_cut_en(struct rtl_softc *sc, bool enable)
|
---|
| 1165 | {
|
---|
| 1166 | printf("[foo] %s\n", __func__);
|
---|
| 1167 | uint32_t ocp_data;
|
---|
| 1168 |
|
---|
| 1169 | ocp_data = ocp_read_2(sc, MCU_TYPE_USB, USB_UPS_CTRL);
|
---|
| 1170 | if (enable)
|
---|
| 1171 | ocp_data |= POWER_CUT;
|
---|
| 1172 | else
|
---|
| 1173 | ocp_data &= ~POWER_CUT;
|
---|
| 1174 | ocp_write_2(sc, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
|
---|
| 1175 |
|
---|
| 1176 | ocp_data = ocp_read_2(sc, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
|
---|
| 1177 | ocp_data &= ~RESUME_INDICATE;
|
---|
| 1178 | ocp_write_2(sc, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
|
---|
| 1179 | }
|
---|
| 1180 |
|
---|
| 1181 | static void
|
---|
| 1182 | rtl_rx_vlan_en(struct rtl_softc *sc, bool enable)
|
---|
| 1183 | {
|
---|
| 1184 | printf("[foo] %s\n", __func__);
|
---|
| 1185 | uint32_t ocp_data;
|
---|
| 1186 |
|
---|
| 1187 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CPCR);
|
---|
| 1188 | if (enable)
|
---|
| 1189 | ocp_data |= CPCR_RX_VLAN;
|
---|
| 1190 | else
|
---|
| 1191 | ocp_data &= ~CPCR_RX_VLAN;
|
---|
| 1192 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
|
---|
| 1193 | }
|
---|
| 1194 |
|
---|
| 1195 | //TODO convert
|
---|
| 1196 | //#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
|
---|
| 1197 |
|
---|
| 1198 | static uint32_t
|
---|
| 1199 | __rtl_get_wol(struct rtl_softc *sc)
|
---|
| 1200 | {
|
---|
| 1201 | printf("[foo] %s\n", __func__);
|
---|
| 1202 | uint32_t ocp_data;
|
---|
| 1203 | uint32_t wolopts = 0;
|
---|
| 1204 |
|
---|
| 1205 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_CONFIG5);
|
---|
| 1206 | if (!(ocp_data & LAN_WAKE_EN))
|
---|
| 1207 | return 0;
|
---|
| 1208 |
|
---|
| 1209 | // ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CONFIG34);
|
---|
| 1210 | // if (ocp_data & LINK_ON_WAKE_EN)
|
---|
| 1211 | // wolopts |= WAKE_PHY;
|
---|
| 1212 | //
|
---|
| 1213 | // ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CONFIG5);
|
---|
| 1214 | // if (ocp_data & UWF_EN)
|
---|
| 1215 | // wolopts |= WAKE_UCAST;
|
---|
| 1216 | // if (ocp_data & BWF_EN)
|
---|
| 1217 | // wolopts |= WAKE_BCAST;
|
---|
| 1218 | // if (ocp_data & MWF_EN)
|
---|
| 1219 | // wolopts |= WAKE_MCAST;
|
---|
| 1220 | //
|
---|
| 1221 | // ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CFG_WOL);
|
---|
| 1222 | // if (ocp_data & MAGIC_EN)
|
---|
| 1223 | // wolopts |= WAKE_MAGIC;
|
---|
| 1224 |
|
---|
| 1225 | return wolopts;
|
---|
| 1226 | }
|
---|
| 1227 |
|
---|
| 1228 | static void
|
---|
| 1229 | __rtl_set_wol(struct rtl_softc *sc, uint32_t wolopts)
|
---|
| 1230 | {
|
---|
| 1231 | printf("[foo] %s\n", __func__);
|
---|
| 1232 | uint32_t ocp_data;
|
---|
| 1233 |
|
---|
| 1234 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
|
---|
| 1235 |
|
---|
| 1236 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CONFIG34);
|
---|
| 1237 | ocp_data &= ~LINK_ON_WAKE_EN;
|
---|
| 1238 | // if (wolopts & WAKE_PHY)
|
---|
| 1239 | // ocp_data |= LINK_ON_WAKE_EN;
|
---|
| 1240 | // ocp_write_2(sc, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data);
|
---|
| 1241 | //
|
---|
| 1242 | // ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CONFIG5);
|
---|
| 1243 | // ocp_data &= ~(UWF_EN | BWF_EN | MWF_EN | LAN_WAKE_EN);
|
---|
| 1244 | // if (wolopts & WAKE_UCAST)
|
---|
| 1245 | // ocp_data |= UWF_EN;
|
---|
| 1246 | // if (wolopts & WAKE_BCAST)
|
---|
| 1247 | // ocp_data |= BWF_EN;
|
---|
| 1248 | // if (wolopts & WAKE_MCAST)
|
---|
| 1249 | // ocp_data |= MWF_EN;
|
---|
| 1250 | // if (wolopts & WAKE_ANY)
|
---|
| 1251 | // ocp_data |= LAN_WAKE_EN;
|
---|
| 1252 | // ocp_write_2(sc, MCU_TYPE_PLA, PLA_CONFIG5, ocp_data);
|
---|
| 1253 | //
|
---|
| 1254 | // ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
|
---|
| 1255 | //
|
---|
| 1256 | // ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CFG_WOL);
|
---|
| 1257 | // ocp_data &= ~MAGIC_EN;
|
---|
| 1258 | // if (wolopts & WAKE_MAGIC)
|
---|
| 1259 | // ocp_data |= MAGIC_EN;
|
---|
| 1260 | // ocp_write_2(sc, MCU_TYPE_PLA, PLA_CFG_WOL, ocp_data);
|
---|
| 1261 | }
|
---|
| 1262 |
|
---|
| 1263 | static void
|
---|
| 1264 | rtl_runtime_suspend_enable(struct rtl_softc *sc, bool enable)
|
---|
| 1265 | {
|
---|
| 1266 | printf("[foo] %s\n", __func__);
|
---|
| 1267 | uint32_t ocp_data;
|
---|
| 1268 |
|
---|
| 1269 | if (enable) {
|
---|
| 1270 | //__rtl_set_wol(sc, WAKE_ANY);
|
---|
| 1271 |
|
---|
| 1272 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
|
---|
| 1273 |
|
---|
| 1274 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_CONFIG34);
|
---|
| 1275 | ocp_data |= LINK_OFF_WAKE_EN;
|
---|
| 1276 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_CONFIG34, ocp_data);
|
---|
| 1277 |
|
---|
| 1278 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
|
---|
| 1279 | } else {
|
---|
| 1280 | __rtl_set_wol(sc, sc->saved_wolopts);
|
---|
| 1281 | }
|
---|
| 1282 | }
|
---|
| 1283 |
|
---|
| 1284 | static void
|
---|
| 1285 | rtl_phy_reset(struct rtl_softc *sc)
|
---|
| 1286 | {
|
---|
| 1287 | printf("[foo] %s\n", __func__);
|
---|
| 1288 | uint32_t data;
|
---|
| 1289 | int i;
|
---|
| 1290 |
|
---|
| 1291 | data = r8152_mdio_read(sc, MII_BMCR);
|
---|
| 1292 |
|
---|
| 1293 | /* don't reset again before the previous one complete */
|
---|
| 1294 | if (data & BMCR_RESET)
|
---|
| 1295 | return;
|
---|
| 1296 |
|
---|
| 1297 | data |= BMCR_RESET;
|
---|
| 1298 | r8152_mdio_write(sc, MII_BMCR, data);
|
---|
| 1299 |
|
---|
| 1300 | for (i = 0; i < 50; i++) {
|
---|
| 1301 | uether_pause(&sc->sc_ue, hz / 1000);
|
---|
| 1302 | if ((r8152_mdio_read(sc, MII_BMCR) & BMCR_RESET) == 0)
|
---|
| 1303 | break;
|
---|
| 1304 | }
|
---|
| 1305 | }
|
---|
| 1306 |
|
---|
| 1307 | static void
|
---|
| 1308 | r8153_teredo_off(struct rtl_softc *sc)
|
---|
| 1309 | {
|
---|
| 1310 | printf("[foo] %s\n", __func__);
|
---|
| 1311 | uint32_t ocp_data;
|
---|
| 1312 |
|
---|
| 1313 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_TEREDO_CFG);
|
---|
| 1314 | ocp_data &= ~(TEREDO_SEL | TEREDO_RS_EVENT_MASK | OOB_TEREDO_EN);
|
---|
| 1315 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
|
---|
| 1316 |
|
---|
| 1317 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_WDT6_CTRL, WDT6_SET_MODE);
|
---|
| 1318 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_REALWOW_TIMER, 0);
|
---|
| 1319 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_TEREDO_TIMER, 0);
|
---|
| 1320 | }
|
---|
| 1321 |
|
---|
| 1322 | static void
|
---|
| 1323 | r8152b_disable_aldps(struct rtl_softc *sc)
|
---|
| 1324 | {
|
---|
| 1325 | printf("[foo] %s\n", __func__);
|
---|
| 1326 | ocp_reg_write(sc, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
|
---|
| 1327 | uether_pause(&sc->sc_ue, hz / 100);
|
---|
| 1328 | }
|
---|
| 1329 |
|
---|
| 1330 | static inline void
|
---|
| 1331 | r8152b_enable_aldps(struct rtl_softc *sc)
|
---|
| 1332 | {
|
---|
| 1333 | printf("[foo] %s\n", __func__);
|
---|
| 1334 | ocp_reg_write(sc, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS |
|
---|
| 1335 | LINKENA | DIS_SDSAVE);
|
---|
| 1336 | }
|
---|
| 1337 |
|
---|
| 1338 | static void rtl8152_disable(struct rtl_softc *sc)
|
---|
| 1339 | {
|
---|
| 1340 | printf("[foo] %s\n", __func__);
|
---|
| 1341 | r8152b_disable_aldps(sc);
|
---|
| 1342 | rtl_disable(sc);
|
---|
| 1343 | r8152b_enable_aldps(sc);
|
---|
| 1344 | }
|
---|
| 1345 |
|
---|
| 1346 | static void r8152b_hw_phy_cfg(struct rtl_softc *sc)
|
---|
| 1347 | {
|
---|
| 1348 | printf("[foo] %s\n", __func__);
|
---|
| 1349 | uint16_t data;
|
---|
| 1350 |
|
---|
| 1351 | data = r8152_mdio_read(sc, MII_BMCR);
|
---|
| 1352 | if (data & BMCR_PDOWN) {
|
---|
| 1353 | data &= ~BMCR_PDOWN;
|
---|
| 1354 | r8152_mdio_write(sc, MII_BMCR, data);
|
---|
| 1355 | }
|
---|
| 1356 | }
|
---|
| 1357 |
|
---|
| 1358 | static void
|
---|
| 1359 | r8152b_exit_oob(struct rtl_softc *sc)
|
---|
| 1360 | {
|
---|
| 1361 | printf("[foo] %s\n", __func__);
|
---|
| 1362 | uint32_t ocp_data;
|
---|
| 1363 | int i;
|
---|
| 1364 |
|
---|
| 1365 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_RCR);
|
---|
| 1366 | ocp_data &= ~RCR_ACPT_ALL;
|
---|
| 1367 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RCR, ocp_data);
|
---|
| 1368 |
|
---|
| 1369 | rxdy_gated_en(sc, true);
|
---|
| 1370 | r8153_teredo_off(sc);
|
---|
| 1371 | r8152b_hw_phy_cfg(sc);
|
---|
| 1372 |
|
---|
| 1373 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
|
---|
| 1374 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_CR, 0x00);
|
---|
| 1375 |
|
---|
| 1376 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
| 1377 | ocp_data &= ~NOW_IS_OOB;
|
---|
| 1378 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
|
---|
| 1379 |
|
---|
| 1380 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7);
|
---|
| 1381 | ocp_data &= ~MCU_BORW_EN;
|
---|
| 1382 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
---|
| 1383 |
|
---|
| 1384 | for (i = 0; i < 1000; i++) {
|
---|
| 1385 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
| 1386 | if (ocp_data & LINK_LIST_READY)
|
---|
| 1387 | break;
|
---|
| 1388 | uether_pause(&sc->sc_ue, hz / 10);
|
---|
| 1389 | }
|
---|
| 1390 |
|
---|
| 1391 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7);
|
---|
| 1392 | ocp_data |= RE_INIT_LL;
|
---|
| 1393 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
---|
| 1394 |
|
---|
| 1395 | for (i = 0; i < 1000; i++) {
|
---|
| 1396 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
| 1397 | if (ocp_data & LINK_LIST_READY)
|
---|
| 1398 | break;
|
---|
| 1399 | uether_pause(&sc->sc_ue, hz / 10);
|
---|
| 1400 | }
|
---|
| 1401 |
|
---|
| 1402 | rtl8152_nic_reset(sc);
|
---|
| 1403 |
|
---|
| 1404 | /* rx share fifo credit full threshold */
|
---|
| 1405 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
|
---|
| 1406 |
|
---|
| 1407 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
|
---|
| 1408 | RXFIFO_THR2_FULL);
|
---|
| 1409 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
|
---|
| 1410 | RXFIFO_THR3_FULL);
|
---|
| 1411 | //if (tp->udev->speed == USB_SPEED_FULL ||
|
---|
| 1412 | // tp->udev->speed == USB_SPEED_LOW) {
|
---|
| 1413 | // /* rx share fifo credit near full threshold */
|
---|
| 1414 | // ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
|
---|
| 1415 | // RXFIFO_THR2_FULL);
|
---|
| 1416 | // ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
|
---|
| 1417 | // RXFIFO_THR3_FULL);
|
---|
| 1418 | //} else {
|
---|
| 1419 | // /* rx share fifo credit near full threshold */
|
---|
| 1420 | // ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
|
---|
| 1421 | // RXFIFO_THR2_HIGH);
|
---|
| 1422 | // ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
|
---|
| 1423 | // RXFIFO_THR3_HIGH);
|
---|
| 1424 | //}
|
---|
| 1425 |
|
---|
| 1426 | /* TX share fifo free credit full threshold */
|
---|
| 1427 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL);
|
---|
| 1428 |
|
---|
| 1429 | ocp_write_1(sc, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD);
|
---|
| 1430 | ocp_write_4(sc, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH);
|
---|
| 1431 | ocp_write_4(sc, MCU_TYPE_USB, USB_TX_DMA,
|
---|
| 1432 | TEST_MODE_DISABLE | TX_SIZE_ADJUST1);
|
---|
| 1433 |
|
---|
| 1434 | //rtl_rx_vlan_en(sc, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
|
---|
| 1435 |
|
---|
| 1436 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
|
---|
| 1437 |
|
---|
| 1438 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_TCR0);
|
---|
| 1439 | ocp_data |= TCR0_AUTO_FIFO;
|
---|
| 1440 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_TCR0, ocp_data);
|
---|
| 1441 | }
|
---|
| 1442 |
|
---|
| 1443 | static void
|
---|
| 1444 | r8152b_enter_oob(struct rtl_softc *sc)
|
---|
| 1445 | {
|
---|
| 1446 | printf("[foo] %s\n", __func__);
|
---|
| 1447 | uint32_t ocp_data;
|
---|
| 1448 | int i;
|
---|
| 1449 |
|
---|
| 1450 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
| 1451 | ocp_data &= ~NOW_IS_OOB;
|
---|
| 1452 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
|
---|
| 1453 |
|
---|
| 1454 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_OOB);
|
---|
| 1455 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB);
|
---|
| 1456 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB);
|
---|
| 1457 |
|
---|
| 1458 | rtl_disable(sc);
|
---|
| 1459 |
|
---|
| 1460 | for (i = 0; i < 1000; i++) {
|
---|
| 1461 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
| 1462 | if (ocp_data & LINK_LIST_READY)
|
---|
| 1463 | break;
|
---|
| 1464 | uether_pause(&sc->sc_ue, hz / 10);
|
---|
| 1465 | }
|
---|
| 1466 |
|
---|
| 1467 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7);
|
---|
| 1468 | ocp_data |= RE_INIT_LL;
|
---|
| 1469 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
|
---|
| 1470 |
|
---|
| 1471 | for (i = 0; i < 1000; i++) {
|
---|
| 1472 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
| 1473 | if (ocp_data & LINK_LIST_READY)
|
---|
| 1474 | break;
|
---|
| 1475 | uether_pause(&sc->sc_ue, hz / 10);
|
---|
| 1476 | }
|
---|
| 1477 |
|
---|
| 1478 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
|
---|
| 1479 |
|
---|
| 1480 | rtl_rx_vlan_en(sc, true);
|
---|
| 1481 |
|
---|
| 1482 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PAL_BDC_CR);
|
---|
| 1483 | ocp_data |= ALDPS_PROXY_MODE;
|
---|
| 1484 | ocp_write_2(sc, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
|
---|
| 1485 |
|
---|
| 1486 | ocp_data = ocp_read_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL);
|
---|
| 1487 | ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
|
---|
| 1488 | ocp_write_1(sc, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
|
---|
| 1489 |
|
---|
| 1490 | rxdy_gated_en(sc, false);
|
---|
| 1491 |
|
---|
| 1492 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_RCR);
|
---|
| 1493 | ocp_data |= RCR_APM | RCR_AM | RCR_AB;
|
---|
| 1494 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_RCR, ocp_data);
|
---|
| 1495 | }
|
---|
| 1496 |
|
---|
| 1497 | static void
|
---|
| 1498 | rtl8152_up(struct rtl_softc *sc)
|
---|
| 1499 | {
|
---|
| 1500 | printf("[foo] %s\n", __func__);
|
---|
| 1501 | r8152b_disable_aldps(sc);
|
---|
| 1502 | r8152b_exit_oob(sc);
|
---|
| 1503 | r8152b_enable_aldps(sc);
|
---|
| 1504 | }
|
---|
| 1505 |
|
---|
| 1506 | static void
|
---|
| 1507 | rtl8152_down(struct rtl_softc *sc)
|
---|
| 1508 | {
|
---|
| 1509 | printf("[foo] %s\n", __func__);
|
---|
| 1510 | r8152_power_cut_en(sc, false);
|
---|
| 1511 | r8152b_disable_aldps(sc);
|
---|
| 1512 | r8152b_enter_oob(sc);
|
---|
| 1513 | r8152b_enable_aldps(sc);
|
---|
| 1514 | }
|
---|
| 1515 |
|
---|
| 1516 | static inline void
|
---|
| 1517 | r8152_mmd_indirect(struct rtl_softc *sc, uint16_t dev, uint16_t reg)
|
---|
| 1518 | {
|
---|
| 1519 | printf("[foo] %s\n", __func__);
|
---|
| 1520 | ocp_reg_write(sc, OCP_EEE_AR, FUN_ADDR | dev);
|
---|
| 1521 | ocp_reg_write(sc, OCP_EEE_DATA, reg);
|
---|
| 1522 | ocp_reg_write(sc, OCP_EEE_AR, FUN_DATA | dev);
|
---|
| 1523 | }
|
---|
| 1524 |
|
---|
| 1525 | static uint16_t
|
---|
| 1526 | r8152_mmd_read(struct rtl_softc *sc, uint16_t dev, uint16_t reg)
|
---|
| 1527 | {
|
---|
| 1528 | printf("[foo] %s\n", __func__);
|
---|
| 1529 | uint16_t data;
|
---|
| 1530 |
|
---|
| 1531 | r8152_mmd_indirect(sc, dev, reg);
|
---|
| 1532 | data = ocp_reg_read(sc, OCP_EEE_DATA);
|
---|
| 1533 | ocp_reg_write(sc, OCP_EEE_AR, 0x0000);
|
---|
| 1534 |
|
---|
| 1535 | return data;
|
---|
| 1536 | }
|
---|
| 1537 |
|
---|
| 1538 | static void
|
---|
| 1539 | r8152_mmd_write(struct rtl_softc *sc, uint16_t dev, uint16_t reg, uint16_t data)
|
---|
| 1540 | {
|
---|
| 1541 | printf("[foo] %s\n", __func__);
|
---|
| 1542 | r8152_mmd_indirect(sc, dev, reg);
|
---|
| 1543 | ocp_reg_write(sc, OCP_EEE_DATA, data);
|
---|
| 1544 | ocp_reg_write(sc, OCP_EEE_AR, 0x0000);
|
---|
| 1545 | }
|
---|
| 1546 |
|
---|
| 1547 | static void
|
---|
| 1548 | r8152_eee_en(struct rtl_softc *sc, bool enable)
|
---|
| 1549 | {
|
---|
| 1550 | printf("[foo] %s\n", __func__);
|
---|
| 1551 | uint16_t config1, config2, config3;
|
---|
| 1552 | uint32_t ocp_data;
|
---|
| 1553 |
|
---|
| 1554 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_EEE_CR);
|
---|
| 1555 | config1 = ocp_reg_read(sc, OCP_EEE_CONFIG1) & ~sd_rise_time_mask;
|
---|
| 1556 | config2 = ocp_reg_read(sc, OCP_EEE_CONFIG2);
|
---|
| 1557 | config3 = ocp_reg_read(sc, OCP_EEE_CONFIG3) & ~fast_snr_mask;
|
---|
| 1558 |
|
---|
| 1559 | if (enable) {
|
---|
| 1560 | ocp_data |= EEE_RX_EN | EEE_TX_EN;
|
---|
| 1561 | config1 |= EEE_10_CAP | EEE_NWAY_EN | TX_QUIET_EN | RX_QUIET_EN;
|
---|
| 1562 | //TODO: config1 |= sd_rise_time(1);
|
---|
| 1563 | config2 |= RG_DACQUIET_EN | RG_LDVQUIET_EN;
|
---|
| 1564 | //TODO: config3 |= fast_snr(42);
|
---|
| 1565 | } else {
|
---|
| 1566 | ocp_data &= ~(EEE_RX_EN | EEE_TX_EN);
|
---|
| 1567 | config1 &= ~(EEE_10_CAP | EEE_NWAY_EN | TX_QUIET_EN |
|
---|
| 1568 | RX_QUIET_EN);
|
---|
| 1569 | //TODO: config1 |= sd_rise_time(7);
|
---|
| 1570 | config2 &= ~(RG_DACQUIET_EN | RG_LDVQUIET_EN);
|
---|
| 1571 | //TODO: config3 |= fast_snr(511);
|
---|
| 1572 | }
|
---|
| 1573 |
|
---|
| 1574 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_EEE_CR, ocp_data);
|
---|
| 1575 | ocp_reg_write(sc, OCP_EEE_CONFIG1, config1);
|
---|
| 1576 | ocp_reg_write(sc, OCP_EEE_CONFIG2, config2);
|
---|
| 1577 | ocp_reg_write(sc, OCP_EEE_CONFIG3, config3);
|
---|
| 1578 | }
|
---|
| 1579 |
|
---|
| 1580 | static void
|
---|
| 1581 | r8152b_enable_eee(struct rtl_softc *sc)
|
---|
| 1582 | {
|
---|
| 1583 | printf("[foo] %s\n", __func__);
|
---|
| 1584 | #define MDIO_MMD_AN 7 /* Auto-Negotiation */
|
---|
| 1585 | #define MDIO_AN_EEE_ADV 60 /* EEE advertisement */
|
---|
| 1586 | #define MDIO_EEE_100TX 0x0002 /* Advertise 100TX EEE cap */
|
---|
| 1587 | r8152_eee_en(sc, true);
|
---|
| 1588 | r8152_mmd_write(sc, MDIO_MMD_AN, MDIO_AN_EEE_ADV, MDIO_EEE_100TX);
|
---|
| 1589 | }
|
---|
| 1590 |
|
---|
| 1591 | static void
|
---|
| 1592 | r8152b_enable_fc(struct rtl_softc *sc)
|
---|
| 1593 | {
|
---|
| 1594 | uint16_t anar;
|
---|
| 1595 |
|
---|
| 1596 | anar = r8152_mdio_read(sc, MII_ANAR);
|
---|
| 1597 | anar |= ANAR_FC | ANAR_X_PAUSE_ASYM;
|
---|
| 1598 | r8152_mdio_write(sc, MII_ANAR, anar);
|
---|
| 1599 | }
|
---|
| 1600 |
|
---|
| 1601 | static void
|
---|
| 1602 | rtl_tally_reset(struct rtl_softc *sc)
|
---|
| 1603 | {
|
---|
| 1604 | printf("[foo] %s\n", __func__);
|
---|
| 1605 | uint32_t ocp_data;
|
---|
| 1606 |
|
---|
| 1607 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_RSTTALLY);
|
---|
| 1608 | ocp_data |= TALLY_RESET;
|
---|
| 1609 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data);
|
---|
| 1610 | }
|
---|
| 1611 |
|
---|
| 1612 |
|
---|
| 1613 | static void
|
---|
| 1614 | rtl_init(struct usb_ether *ue)
|
---|
| 1615 | {
|
---|
| 1616 | printf("[foo] %s\n", __func__);
|
---|
| 1617 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
| 1618 | struct ifnet *ifp = uether_getifp(ue);
|
---|
| 1619 | uint32_t ocp_data;
|
---|
| 1620 |
|
---|
| 1621 | RTL_LOCK_ASSERT(sc, MA_OWNED);
|
---|
| 1622 |
|
---|
| 1623 | /*
|
---|
| 1624 | * Cancel pending I/O
|
---|
| 1625 | */
|
---|
| 1626 | //rtl_stop(ue);
|
---|
| 1627 |
|
---|
| 1628 | /* Load the promiscuous & multicast filter */
|
---|
| 1629 | rtl_setpromisc_and_multi(ue);
|
---|
| 1630 |
|
---|
| 1631 | /*
|
---|
| 1632 | * Set the initial TX and RX configuration.
|
---|
| 1633 | */
|
---|
| 1634 | r8152b_disable_aldps(sc);
|
---|
| 1635 |
|
---|
| 1636 | if (sc->version == RTL_VER_01) {
|
---|
| 1637 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_LED_FEATURE);
|
---|
| 1638 | ocp_data &= ~LED_MODE_MASK;
|
---|
| 1639 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
|
---|
| 1640 | }
|
---|
| 1641 |
|
---|
| 1642 | /*
|
---|
| 1643 | * Enable RX and TX
|
---|
| 1644 | */
|
---|
| 1645 | r8152_power_cut_en(sc, false);
|
---|
| 1646 |
|
---|
| 1647 | ocp_data = ocp_read_2(sc, MCU_TYPE_PLA, PLA_PHY_PWR);
|
---|
| 1648 | ocp_data |= TX_10M_IDLE_EN | PFM_PWM_SWITCH;
|
---|
| 1649 | ocp_write_2(sc, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
|
---|
| 1650 |
|
---|
| 1651 | ocp_data = ocp_read_4(sc, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL);
|
---|
| 1652 | ocp_data &= ~MCU_CLK_RATIO_MASK;
|
---|
| 1653 | ocp_data |= MCU_CLK_RATIO | D3_CLK_GATED_EN;
|
---|
| 1654 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ocp_data);
|
---|
| 1655 |
|
---|
| 1656 | ocp_data = GPHY_STS_MSK | SPEED_DOWN_MSK |
|
---|
| 1657 | SPDWN_RXDV_MSK | SPDWN_LINKCHG_MSK;
|
---|
| 1658 | ocp_write_4(sc, MCU_TYPE_PLA, PLA_GPHY_INTR_IMR, ocp_data);
|
---|
| 1659 |
|
---|
| 1660 | //r8152b_enable_eee(sc);
|
---|
| 1661 | r8152b_enable_aldps(sc);
|
---|
| 1662 | r8152b_enable_fc(sc);
|
---|
| 1663 | rtl_tally_reset(sc);
|
---|
| 1664 |
|
---|
| 1665 | /* enable rx aggregation */
|
---|
| 1666 | ocp_data = ocp_read_2(sc, MCU_TYPE_USB, USB_USB_CTRL);
|
---|
| 1667 | ocp_data &= ~RX_AGG_DISABLE;
|
---|
| 1668 | ocp_write_2(sc, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
|
---|
| 1669 |
|
---|
| 1670 | ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
---|
| 1671 |
|
---|
| 1672 | rtl8152_up(sc);
|
---|
| 1673 |
|
---|
| 1674 | rtl_start(ue);
|
---|
| 1675 | }
|
---|
| 1676 |
|
---|
| 1677 | /*
|
---|
| 1678 | * Set media options.
|
---|
| 1679 | */
|
---|
| 1680 | static int
|
---|
| 1681 | rtl_ifmedia_upd(struct ifnet *ifp)
|
---|
| 1682 | {
|
---|
| 1683 | printf("[foo] %s\n", __func__);
|
---|
| 1684 | struct rtl_softc *sc = ifp->if_softc;
|
---|
| 1685 | struct mii_data *mii = GET_MII(sc);
|
---|
| 1686 | struct mii_softc *miisc;
|
---|
| 1687 | int error;
|
---|
| 1688 |
|
---|
| 1689 | RTL_LOCK_ASSERT(sc, MA_OWNED);
|
---|
| 1690 |
|
---|
| 1691 | sc->sc_flags &= ~RTL_FLAG_LINK;
|
---|
| 1692 | LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
|
---|
| 1693 | PHY_RESET(miisc);
|
---|
| 1694 | error = mii_mediachg(mii);
|
---|
| 1695 | return (error);
|
---|
| 1696 | }
|
---|
| 1697 |
|
---|
| 1698 | /*
|
---|
| 1699 | * Report current media status.
|
---|
| 1700 | */
|
---|
| 1701 | static void
|
---|
| 1702 | rtl_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
|
---|
| 1703 | {
|
---|
| 1704 | printf("[foo] %s\n", __func__);
|
---|
| 1705 | struct rtl_softc *sc = ifp->if_softc;
|
---|
| 1706 | struct mii_data *mii = GET_MII(sc);
|
---|
| 1707 |
|
---|
| 1708 | RTL_LOCK(sc);
|
---|
| 1709 | mii_pollstat(mii);
|
---|
| 1710 | ifmr->ifm_active = mii->mii_media_active;
|
---|
| 1711 | ifmr->ifm_status = mii->mii_media_status;
|
---|
| 1712 | RTL_UNLOCK(sc);
|
---|
| 1713 | }
|
---|
| 1714 |
|
---|
| 1715 | static void
|
---|
| 1716 | rtl_start(struct usb_ether *ue)
|
---|
| 1717 | {
|
---|
| 1718 | printf("[foo] %s\n", __func__);
|
---|
| 1719 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
| 1720 |
|
---|
| 1721 | /*
|
---|
| 1722 | * start the USB transfers, if not already started:
|
---|
| 1723 | */
|
---|
| 1724 | usbd_transfer_start(sc->sc_xfer[RTL_INTR_DT_RD]);
|
---|
| 1725 | usbd_transfer_start(sc->sc_xfer[RTL_BULK_DT_RD]);
|
---|
| 1726 | usbd_transfer_start(sc->sc_xfer[RTL_BULK_DT_WR]);
|
---|
| 1727 | }
|
---|
| 1728 |
|
---|
| 1729 | static void
|
---|
| 1730 | rtl_stop(struct usb_ether *ue)
|
---|
| 1731 | {
|
---|
| 1732 | printf("[foo] %s\n", __func__);
|
---|
| 1733 | struct rtl_softc *sc = uether_getsc(ue);
|
---|
| 1734 | struct ifnet *ifp = uether_getifp(ue);
|
---|
| 1735 |
|
---|
| 1736 | RTL_LOCK_ASSERT(sc, MA_OWNED);
|
---|
| 1737 |
|
---|
| 1738 | ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
|
---|
| 1739 | sc->sc_flags &= ~RTL_FLAG_LINK;
|
---|
| 1740 |
|
---|
| 1741 | /*
|
---|
| 1742 | * stop all the transfers, if not already stopped:
|
---|
| 1743 | */
|
---|
| 1744 | usbd_transfer_stop(sc->sc_xfer[RTL_BULK_DT_WR]);
|
---|
| 1745 | usbd_transfer_stop(sc->sc_xfer[RTL_BULK_DT_RD]);
|
---|
| 1746 | usbd_transfer_stop(sc->sc_xfer[RTL_INTR_DT_RD]);
|
---|
| 1747 |
|
---|
| 1748 | rtl8152_down(sc);
|
---|
| 1749 |
|
---|
| 1750 | rtl_reset(sc);
|
---|
| 1751 | }
|
---|