1 /* SPDX-License-Identifier: ISC AND BSD-4-Clause */ 2 3 /*- 4 * Copyright (c) 2011 Rick van der Zwet <info@rickvanderzwet.nl> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /*- 20 * Copyright (c) 2008 Johann Christian Rode <jcrode@gmx.net> 21 * 22 * Permission to use, copy, modify, and distribute this software for any 23 * purpose with or without fee is hereby granted, provided that the above 24 * copyright notice and this permission notice appear in all copies. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 27 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 28 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 29 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 30 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 31 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 32 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 33 */ 34 35 /*- 36 * Copyright (c) 2005, 2006, 2007 Jonathan Gray <jsg@openbsd.org> 37 * 38 * Permission to use, copy, modify, and distribute this software for any 39 * purpose with or without fee is hereby granted, provided that the above 40 * copyright notice and this permission notice appear in all copies. 41 * 42 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 43 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 44 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 45 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 47 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 48 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 49 */ 50 51 /*- 52 * Copyright (c) 1997, 1998, 1999, 2000-2003 53 * Bill Paul <wpaul@windriver.com>. All rights reserved. 54 * 55 * Redistribution and use in source and binary forms, with or without 56 * modification, are permitted provided that the following conditions 57 * are met: 58 * 1. Redistributions of source code must retain the above copyright 59 * notice, this list of conditions and the following disclaimer. 60 * 2. Redistributions in binary form must reproduce the above copyright 61 * notice, this list of conditions and the following disclaimer in the 62 * documentation and/or other materials provided with the distribution. 63 * 3. All advertising materials mentioning features or use of this software 64 * must display the following acknowledgement: 65 * This product includes software developed by Bill Paul. 66 * 4. Neither the name of the author nor the names of any co-contributors 67 * may be used to endorse or promote products derived from this software 68 * without specific prior written permission. 69 * 70 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 71 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 72 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 73 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 74 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 75 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 76 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 77 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 78 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 79 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 80 * THE POSSIBILITY OF SUCH DAMAGE. 81 */ 82 83 /* 84 * Moschip MCS7730/MCS7830/MCS7832 USB to Ethernet controller 85 * The datasheet is available at the following URL: 86 * http://www.moschip.com/data/products/MCS7830/Data%20Sheet_7830.pdf 87 */ 88 89 /* 90 * The FreeBSD if_mos.c driver is based on various different sources: 91 * The vendor provided driver at the following URL: 92 * http://www.moschip.com/data/products/MCS7830/Driver_FreeBSD_7830.tar.gz 93 * 94 * Mixed together with the OpenBSD if_mos.c driver for validation and checking 95 * and the FreeBSD if_reu.c as reference for the USB Ethernet framework. 96 */ 97 98 #include <sys/stdint.h> 99 #include <sys/stddef.h> 100 #include <sys/param.h> 101 #include <sys/queue.h> 102 #include <sys/types.h> 103 #include <sys/systm.h> 104 #include <sys/socket.h> 105 #include <sys/kernel.h> 106 #include <sys/bus.h> 107 #include <sys/module.h> 108 #include <sys/lock.h> 109 #include <sys/mutex.h> 110 #include <sys/condvar.h> 111 #include <sys/sysctl.h> 112 #include <sys/sx.h> 113 #include <sys/unistd.h> 114 #include <sys/callout.h> 115 #include <sys/malloc.h> 116 #include <sys/priv.h> 117 118 #include <net/if.h> 119 #include <net/if_var.h> 120 #include <net/if_media.h> 121 122 #include <dev/mii/mii.h> 123 #include <dev/mii/miivar.h> 124 125 #include <dev/usb/usb.h> 126 #include <dev/usb/usbdi.h> 127 #include <dev/usb/usbdi_util.h> 128 #include "usbdevs.h" 129 130 #define USB_DEBUG_VAR mos_debug 131 #include <dev/usb/usb_debug.h> 132 #include <dev/usb/usb_process.h> 133 134 #include <dev/usb/net/usb_ethernet.h> 135 136 #include "miibus_if.h" 137 138 //#include <dev/usb/net/if_mosreg.h> 139 #include "if_mosreg.h" 140 141 #ifdef USB_DEBUG 142 static int mos_debug = 0; 143 144 static SYSCTL_NODE(_hw_usb, OID_AUTO, mos, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 145 "USB mos"); 146 SYSCTL_INT(_hw_usb_mos, OID_AUTO, debug, CTLFLAG_RWTUN, &mos_debug, 0, 147 "Debug level"); 148 #endif 149 150 #define MOS_DPRINTFN(fmt,...) \ 151 DPRINTF("mos: %s: " fmt "\n",__FUNCTION__,## __VA_ARGS__) 152 153 #define USB_PRODUCT_MOSCHIP_MCS7730 0x7730 154 #define USB_PRODUCT_SITECOMEU_LN030 0x0021 155 156 /* Various supported device vendors/products. */ 157 static const STRUCT_USB_HOST_ID mos_devs[] = { 158 {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7730, MCS7730)}, 159 {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7830, MCS7830)}, 160 {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7832, MCS7832)}, 161 {USB_VPI(USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN030, MCS7830)}, 162 }; 163 164 static int mos_probe(device_t dev); 165 static int mos_attach(device_t dev); 166 static void mos_attach_post(struct usb_ether *ue); 167 static int mos_detach(device_t dev); 168 169 static void mos_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error); 170 static void mos_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error); 171 static void mos_intr_callback(struct usb_xfer *xfer, usb_error_t error); 172 static void mos_tick(struct usb_ether *); 173 static void mos_start(struct usb_ether *); 174 static void mos_init(struct usb_ether *); 175 static void mos_chip_init(struct mos_softc *); 176 static void mos_stop(struct usb_ether *); 177 static int mos_miibus_readreg(device_t, int, int); 178 static int mos_miibus_writereg(device_t, int, int, int); 179 static void mos_miibus_statchg(device_t); 180 static int mos_ifmedia_upd(if_t); 181 static void mos_ifmedia_sts(if_t, struct ifmediareq *); 182 static void mos_reset(struct mos_softc *sc); 183 184 static int mos_reg_read_1(struct mos_softc *, int); 185 static int mos_reg_read_2(struct mos_softc *, int); 186 static int mos_reg_write_1(struct mos_softc *, int, int); 187 static int mos_reg_write_2(struct mos_softc *, int, int); 188 static int mos_readmac(struct mos_softc *, uint8_t *); 189 static int mos_writemac(struct mos_softc *, uint8_t *); 190 static int mos_write_mcast(struct mos_softc *, u_char *); 191 192 static void mos_setmulti(struct usb_ether *); 193 static void mos_setpromisc(struct usb_ether *); 194 195 static const struct usb_config mos_config[MOS_ENDPT_MAX] = { 196 [MOS_ENDPT_TX] = { 197 .type = UE_BULK, 198 .endpoint = UE_ADDR_ANY, 199 .direction = UE_DIR_OUT, 200 .bufsize = (MCLBYTES + 2), 201 .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 202 .callback = mos_bulk_write_callback, 203 .timeout = 10000, 204 }, 205 206 [MOS_ENDPT_RX] = { 207 .type = UE_BULK, 208 .endpoint = UE_ADDR_ANY, 209 .direction = UE_DIR_IN, 210 .bufsize = (MCLBYTES + 4 + ETHER_CRC_LEN), 211 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 212 .callback = mos_bulk_read_callback, 213 }, 214 215 [MOS_ENDPT_INTR] = { 216 .type = UE_INTERRUPT, 217 .endpoint = UE_ADDR_ANY, 218 .direction = UE_DIR_IN, 219 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 220 .bufsize = 0, 221 .callback = mos_intr_callback, 222 }, 223 }; 224 225 static device_method_t mos_methods[] = { 226 /* Device interface */ 227 DEVMETHOD(device_probe, mos_probe), 228 DEVMETHOD(device_attach, mos_attach), 229 DEVMETHOD(device_detach, mos_detach), 230 231 /* MII interface */ 232 DEVMETHOD(miibus_readreg, mos_miibus_readreg), 233 DEVMETHOD(miibus_writereg, mos_miibus_writereg), 234 DEVMETHOD(miibus_statchg, mos_miibus_statchg), 235 236 DEVMETHOD_END 237 }; 238 239 static driver_t mos_driver = { 240 .name = "mos", 241 .methods = mos_methods, 242 .size = sizeof(struct mos_softc) 243 }; 244 245 DRIVER_MODULE(mos, uhub, mos_driver, NULL, NULL); 246 DRIVER_MODULE(miibus, mos, miibus_driver, 0, 0); 247 MODULE_DEPEND(mos, uether, 1, 1, 1); 248 MODULE_DEPEND(mos, usb, 1, 1, 1); 249 MODULE_DEPEND(mos, ether, 1, 1, 1); 250 MODULE_DEPEND(mos, miibus, 1, 1, 1); 251 USB_PNP_HOST_INFO(mos_devs); 252 253 static const struct usb_ether_methods mos_ue_methods = { 254 .ue_attach_post = mos_attach_post, 255 .ue_start = mos_start, 256 .ue_init = mos_init, 257 .ue_stop = mos_stop, 258 .ue_tick = mos_tick, 259 .ue_setmulti = mos_setmulti, 260 .ue_setpromisc = mos_setpromisc, 261 .ue_mii_upd = mos_ifmedia_upd, 262 .ue_mii_sts = mos_ifmedia_sts, 263 }; 264 265 static int 266 mos_reg_read_1(struct mos_softc *sc, int reg) 267 { 268 struct usb_device_request req; 269 usb_error_t err; 270 uByte val = 0; 271 272 req.bmRequestType = UT_READ_VENDOR_DEVICE; 273 req.bRequest = MOS_UR_READREG; 274 USETW(req.wValue, 0); 275 USETW(req.wIndex, reg); 276 USETW(req.wLength, 1); 277 278 err = uether_do_request(&sc->sc_ue, &req, &val, 1000); 279 280 if (err) { 281 MOS_DPRINTFN("mos_reg_read_1 error, reg: %d\n", reg); 282 return (-1); 283 } 284 return (val); 285 } 286 287 static int 288 mos_reg_read_2(struct mos_softc *sc, int reg) 289 { 290 struct usb_device_request req; 291 usb_error_t err; 292 uWord val; 293 294 USETW(val, 0); 295 296 req.bmRequestType = UT_READ_VENDOR_DEVICE; 297 req.bRequest = MOS_UR_READREG; 298 USETW(req.wValue, 0); 299 USETW(req.wIndex, reg); 300 USETW(req.wLength, 2); 301 302 err = uether_do_request(&sc->sc_ue, &req, &val, 1000); 303 304 if (err) { 305 MOS_DPRINTFN("mos_reg_read_2 error, reg: %d", reg); 306 return (-1); 307 } 308 return (UGETW(val)); 309 } 310 311 static int 312 mos_reg_write_1(struct mos_softc *sc, int reg, int aval) 313 { 314 struct usb_device_request req; 315 usb_error_t err; 316 uByte val; 317 val = aval; 318 319 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 320 req.bRequest = MOS_UR_WRITEREG; 321 USETW(req.wValue, 0); 322 USETW(req.wIndex, reg); 323 USETW(req.wLength, 1); 324 325 err = uether_do_request(&sc->sc_ue, &req, &val, 1000); 326 327 if (err) { 328 MOS_DPRINTFN("mos_reg_write_1 error, reg: %d", reg); 329 return (-1); 330 } 331 return (0); 332 } 333 334 static int 335 mos_reg_write_2(struct mos_softc *sc, int reg, int aval) 336 { 337 struct usb_device_request req; 338 usb_error_t err; 339 uWord val; 340 341 USETW(val, aval); 342 343 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 344 req.bRequest = MOS_UR_WRITEREG; 345 USETW(req.wValue, 0); 346 USETW(req.wIndex, reg); 347 USETW(req.wLength, 2); 348 349 err = uether_do_request(&sc->sc_ue, &req, &val, 1000); 350 351 if (err) { 352 MOS_DPRINTFN("mos_reg_write_2 error, reg: %d", reg); 353 return (-1); 354 } 355 return (0); 356 } 357 358 static int 359 mos_readmac(struct mos_softc *sc, u_char *mac) 360 { 361 struct usb_device_request req; 362 usb_error_t err; 363 364 req.bmRequestType = UT_READ_VENDOR_DEVICE; 365 req.bRequest = MOS_UR_READREG; 366 USETW(req.wValue, 0); 367 USETW(req.wIndex, MOS_MAC); 368 USETW(req.wLength, ETHER_ADDR_LEN); 369 370 err = uether_do_request(&sc->sc_ue, &req, mac, 1000); 371 372 if (err) { 373 return (-1); 374 } 375 return (0); 376 } 377 378 static int 379 mos_writemac(struct mos_softc *sc, uint8_t *mac) 380 { 381 struct usb_device_request req; 382 usb_error_t err; 383 384 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 385 req.bRequest = MOS_UR_WRITEREG; 386 USETW(req.wValue, 0); 387 USETW(req.wIndex, MOS_MAC); 388 USETW(req.wLength, ETHER_ADDR_LEN); 389 390 err = uether_do_request(&sc->sc_ue, &req, mac, 1000); 391 392 if (err) { 393 MOS_DPRINTFN("mos_writemac error"); 394 return (-1); 395 } 396 return (0); 397 } 398 399 static int 400 mos_write_mcast(struct mos_softc *sc, u_char *hashtbl) 401 { 402 struct usb_device_request req; 403 usb_error_t err; 404 405 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 406 req.bRequest = MOS_UR_WRITEREG; 407 USETW(req.wValue, 0); 408 USETW(req.wIndex, MOS_MCAST_TABLE); 409 USETW(req.wLength, 8); 410 411 err = uether_do_request(&sc->sc_ue, &req, hashtbl, 1000); 412 413 if (err) { 414 MOS_DPRINTFN("mos_reg_mcast error"); 415 return (-1); 416 } 417 return (0); 418 } 419 420 static int 421 mos_miibus_readreg(device_t dev, int phy, int reg) 422 { 423 struct mos_softc *sc = device_get_softc(dev); 424 int i, res, locked; 425 426 locked = mtx_owned(&sc->sc_mtx); 427 if (!locked) 428 MOS_LOCK(sc); 429 430 mos_reg_write_2(sc, MOS_PHY_DATA, 0); 431 mos_reg_write_1(sc, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) | 432 MOS_PHYCTL_READ); 433 mos_reg_write_1(sc, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) | 434 MOS_PHYSTS_PENDING); 435 436 for (i = 0; i < MOS_TIMEOUT; i++) { 437 if (mos_reg_read_1(sc, MOS_PHY_STS) & MOS_PHYSTS_READY) 438 break; 439 } 440 if (i == MOS_TIMEOUT) { 441 MOS_DPRINTFN("MII read timeout"); 442 } 443 res = mos_reg_read_2(sc, MOS_PHY_DATA); 444 445 if (!locked) 446 MOS_UNLOCK(sc); 447 return (res); 448 } 449 450 static int 451 mos_miibus_writereg(device_t dev, int phy, int reg, int val) 452 { 453 struct mos_softc *sc = device_get_softc(dev); 454 int i, locked; 455 456 locked = mtx_owned(&sc->sc_mtx); 457 if (!locked) 458 MOS_LOCK(sc); 459 460 mos_reg_write_2(sc, MOS_PHY_DATA, val); 461 mos_reg_write_1(sc, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) | 462 MOS_PHYCTL_WRITE); 463 mos_reg_write_1(sc, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) | 464 MOS_PHYSTS_PENDING); 465 466 for (i = 0; i < MOS_TIMEOUT; i++) { 467 if (mos_reg_read_1(sc, MOS_PHY_STS) & MOS_PHYSTS_READY) 468 break; 469 } 470 if (i == MOS_TIMEOUT) 471 MOS_DPRINTFN("MII write timeout"); 472 473 if (!locked) 474 MOS_UNLOCK(sc); 475 return 0; 476 } 477 478 static void 479 mos_miibus_statchg(device_t dev) 480 { 481 struct mos_softc *sc = device_get_softc(dev); 482 struct mii_data *mii = GET_MII(sc); 483 int val, err, locked; 484 485 locked = mtx_owned(&sc->sc_mtx); 486 if (!locked) 487 MOS_LOCK(sc); 488 489 /* disable RX, TX prior to changing FDX, SPEEDSEL */ 490 val = mos_reg_read_1(sc, MOS_CTL); 491 val &= ~(MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); 492 mos_reg_write_1(sc, MOS_CTL, val); 493 494 /* reset register which counts dropped frames */ 495 mos_reg_write_1(sc, MOS_FRAME_DROP_CNT, 0); 496 497 if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) 498 val |= MOS_CTL_FDX_ENB; 499 else 500 val &= ~(MOS_CTL_FDX_ENB); 501 502 switch (IFM_SUBTYPE(mii->mii_media_active)) { 503 case IFM_100_TX: 504 val |= MOS_CTL_SPEEDSEL; 505 break; 506 case IFM_10_T: 507 val &= ~(MOS_CTL_SPEEDSEL); 508 break; 509 } 510 511 /* re-enable TX, RX */ 512 val |= (MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); 513 err = mos_reg_write_1(sc, MOS_CTL, val); 514 515 if (err) 516 MOS_DPRINTFN("media change failed"); 517 518 if (!locked) 519 MOS_UNLOCK(sc); 520 } 521 522 /* 523 * Set media options. 524 */ 525 static int 526 mos_ifmedia_upd(if_t ifp) 527 { 528 struct mos_softc *sc = if_getsoftc(ifp); 529 struct mii_data *mii = GET_MII(sc); 530 struct mii_softc *miisc; 531 int error; 532 533 MOS_LOCK_ASSERT(sc, MA_OWNED); 534 535 sc->mos_link = 0; 536 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 537 PHY_RESET(miisc); 538 error = mii_mediachg(mii); 539 return (error); 540 } 541 542 /* 543 * Report current media status. 544 */ 545 static void 546 mos_ifmedia_sts(if_t ifp, struct ifmediareq *ifmr) 547 { 548 struct mos_softc *sc = if_getsoftc(ifp); 549 struct mii_data *mii = GET_MII(sc); 550 551 MOS_LOCK(sc); 552 mii_pollstat(mii); 553 554 ifmr->ifm_active = mii->mii_media_active; 555 ifmr->ifm_status = mii->mii_media_status; 556 MOS_UNLOCK(sc); 557 } 558 559 static void 560 mos_setpromisc(struct usb_ether *ue) 561 { 562 struct mos_softc *sc = uether_getsc(ue); 563 if_t ifp = uether_getifp(ue); 564 565 uint8_t rxmode; 566 567 MOS_LOCK_ASSERT(sc, MA_OWNED); 568 569 rxmode = mos_reg_read_1(sc, MOS_CTL); 570 571 /* If we want promiscuous mode, set the allframes bit. */ 572 if (if_getflags(ifp) & IFF_PROMISC) { 573 rxmode |= MOS_CTL_RX_PROMISC; 574 } else { 575 rxmode &= ~MOS_CTL_RX_PROMISC; 576 } 577 578 mos_reg_write_1(sc, MOS_CTL, rxmode); 579 } 580 581 static u_int 582 mos_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) 583 { 584 uint8_t *hashtbl = arg; 585 uint32_t h; 586 587 h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26; 588 hashtbl[h / 8] |= 1 << (h % 8); 589 590 return (1); 591 } 592 593 static void 594 mos_setmulti(struct usb_ether *ue) 595 { 596 struct mos_softc *sc = uether_getsc(ue); 597 if_t ifp = uether_getifp(ue); 598 uint8_t rxmode; 599 uint8_t hashtbl[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 600 int allmulti = 0; 601 602 MOS_LOCK_ASSERT(sc, MA_OWNED); 603 604 rxmode = mos_reg_read_1(sc, MOS_CTL); 605 606 if (if_getflags(ifp) & IFF_ALLMULTI || if_getflags(ifp) & IFF_PROMISC) 607 allmulti = 1; 608 609 /* get all new ones */ 610 if_foreach_llmaddr(ifp, mos_hash_maddr, &hashtbl); 611 612 /* now program new ones */ 613 if (allmulti == 1) { 614 rxmode |= MOS_CTL_ALLMULTI; 615 mos_reg_write_1(sc, MOS_CTL, rxmode); 616 } else { 617 rxmode &= ~MOS_CTL_ALLMULTI; 618 mos_write_mcast(sc, (void *)&hashtbl); 619 mos_reg_write_1(sc, MOS_CTL, rxmode); 620 } 621 } 622 623 static void 624 mos_reset(struct mos_softc *sc) 625 { 626 uint8_t ctl; 627 628 ctl = mos_reg_read_1(sc, MOS_CTL); 629 ctl &= ~(MOS_CTL_RX_PROMISC | MOS_CTL_ALLMULTI | MOS_CTL_TX_ENB | 630 MOS_CTL_RX_ENB); 631 /* Disable RX, TX, promiscuous and allmulticast mode */ 632 mos_reg_write_1(sc, MOS_CTL, ctl); 633 634 /* Reset frame drop counter register to zero */ 635 mos_reg_write_1(sc, MOS_FRAME_DROP_CNT, 0); 636 637 /* Wait a little while for the chip to get its brains in order. */ 638 usb_pause_mtx(&sc->sc_mtx, hz / 128); 639 return; 640 } 641 642 static void 643 mos_chip_init(struct mos_softc *sc) 644 { 645 int i; 646 647 /* 648 * Rev.C devices have a pause threshold register which needs to be set 649 * at startup. 650 */ 651 if (mos_reg_read_1(sc, MOS_PAUSE_TRHD) != -1) { 652 for (i = 0; i < MOS_PAUSE_REWRITES; i++) 653 mos_reg_write_1(sc, MOS_PAUSE_TRHD, 0); 654 } 655 sc->mos_phyaddrs[0] = 1; 656 sc->mos_phyaddrs[1] = 0xFF; 657 } 658 659 /* 660 * Probe for a MCS7x30 chip. 661 */ 662 static int 663 mos_probe(device_t dev) 664 { 665 struct usb_attach_arg *uaa = device_get_ivars(dev); 666 int retval; 667 668 if (uaa->usb_mode != USB_MODE_HOST) 669 return (ENXIO); 670 if (uaa->info.bConfigIndex != MOS_CONFIG_IDX) 671 return (ENXIO); 672 if (uaa->info.bIfaceIndex != MOS_IFACE_IDX) 673 return (ENXIO); 674 675 retval = usbd_lookup_id_by_uaa(mos_devs, sizeof(mos_devs), uaa); 676 return (retval); 677 } 678 679 /* 680 * Attach the interface. Allocate softc structures, do ifmedia 681 * setup and ethernet/BPF attach. 682 */ 683 static int 684 mos_attach(device_t dev) 685 { 686 struct usb_attach_arg *uaa = device_get_ivars(dev); 687 struct mos_softc *sc = device_get_softc(dev); 688 struct usb_ether *ue = &sc->sc_ue; 689 uint8_t iface_index; 690 int error; 691 692 sc->mos_flags = USB_GET_DRIVER_INFO(uaa); 693 694 device_set_usb_desc(dev); 695 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 696 697 iface_index = MOS_IFACE_IDX; 698 error = usbd_transfer_setup(uaa->device, &iface_index, 699 sc->sc_xfer, mos_config, MOS_ENDPT_MAX, 700 sc, &sc->sc_mtx); 701 702 if (error) { 703 device_printf(dev, "allocating USB transfers failed\n"); 704 goto detach; 705 } 706 ue->ue_sc = sc; 707 ue->ue_dev = dev; 708 ue->ue_udev = uaa->device; 709 ue->ue_mtx = &sc->sc_mtx; 710 ue->ue_methods = &mos_ue_methods; 711 712 if (sc->mos_flags & MCS7730) { 713 MOS_DPRINTFN("model: MCS7730"); 714 } else if (sc->mos_flags & MCS7830) { 715 MOS_DPRINTFN("model: MCS7830"); 716 } else if (sc->mos_flags & MCS7832) { 717 MOS_DPRINTFN("model: MCS7832"); 718 } 719 error = uether_ifattach(ue); 720 if (error) { 721 device_printf(dev, "could not attach interface\n"); 722 goto detach; 723 } 724 return (0); 725 726 detach: 727 mos_detach(dev); 728 return (ENXIO); 729 } 730 731 static void 732 mos_attach_post(struct usb_ether *ue) 733 { 734 struct mos_softc *sc = uether_getsc(ue); 735 int err; 736 737 /* Read MAC address, inform the world. */ 738 err = mos_readmac(sc, ue->ue_eaddr); 739 740 if (err) 741 MOS_DPRINTFN("couldn't get MAC address"); 742 743 MOS_DPRINTFN("address: %s", ether_sprintf(ue->ue_eaddr)); 744 745 mos_chip_init(sc); 746 } 747 748 static int 749 mos_detach(device_t dev) 750 { 751 struct mos_softc *sc = device_get_softc(dev); 752 struct usb_ether *ue = &sc->sc_ue; 753 754 usbd_transfer_unsetup(sc->sc_xfer, MOS_ENDPT_MAX); 755 uether_ifdetach(ue); 756 mtx_destroy(&sc->sc_mtx); 757 758 return (0); 759 } 760 761 /* 762 * A frame has been uploaded: pass the resulting mbuf chain up to 763 * the higher level protocols. 764 */ 765 static void 766 mos_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 767 { 768 struct mos_softc *sc = usbd_xfer_softc(xfer); 769 struct usb_ether *ue = &sc->sc_ue; 770 if_t ifp = uether_getifp(ue); 771 772 uint8_t rxstat = 0; 773 uint32_t actlen; 774 uint16_t pktlen = 0; 775 struct usb_page_cache *pc; 776 777 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 778 pc = usbd_xfer_get_frame(xfer, 0); 779 780 switch (USB_GET_STATE(xfer)) { 781 case USB_ST_TRANSFERRED: 782 MOS_DPRINTFN("actlen : %d", actlen); 783 if (actlen <= 1) { 784 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 785 goto tr_setup; 786 } 787 /* evaluate status byte at the end */ 788 usbd_copy_out(pc, actlen - sizeof(rxstat), &rxstat, 789 sizeof(rxstat)); 790 791 if (rxstat != MOS_RXSTS_VALID) { 792 MOS_DPRINTFN("erroneous frame received"); 793 if (rxstat & MOS_RXSTS_SHORT_FRAME) 794 MOS_DPRINTFN("frame size less than 64 bytes"); 795 if (rxstat & MOS_RXSTS_LARGE_FRAME) { 796 MOS_DPRINTFN("frame size larger than " 797 "1532 bytes"); 798 } 799 if (rxstat & MOS_RXSTS_CRC_ERROR) 800 MOS_DPRINTFN("CRC error"); 801 if (rxstat & MOS_RXSTS_ALIGN_ERROR) 802 MOS_DPRINTFN("alignment error"); 803 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 804 goto tr_setup; 805 } 806 /* Remember the last byte was used for the status fields */ 807 pktlen = actlen - 1; 808 if (pktlen < sizeof(struct ether_header)) { 809 MOS_DPRINTFN("error: pktlen %d is smaller " 810 "than ether_header %zd", pktlen, 811 sizeof(struct ether_header)); 812 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 813 goto tr_setup; 814 } 815 uether_rxbuf(ue, pc, 0, actlen); 816 /* FALLTHROUGH */ 817 case USB_ST_SETUP: 818 tr_setup: 819 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer)); 820 usbd_transfer_submit(xfer); 821 uether_rxflush(ue); 822 return; 823 default: 824 MOS_DPRINTFN("bulk read error, %s", usbd_errstr(error)); 825 if (error != USB_ERR_CANCELLED) { 826 usbd_xfer_set_stall(xfer); 827 goto tr_setup; 828 } 829 MOS_DPRINTFN("start rx %i", usbd_xfer_max_len(xfer)); 830 return; 831 } 832 } 833 834 /* 835 * A frame was downloaded to the chip. It's safe for us to clean up 836 * the list buffers. 837 */ 838 static void 839 mos_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 840 { 841 struct mos_softc *sc = usbd_xfer_softc(xfer); 842 if_t ifp = uether_getifp(&sc->sc_ue); 843 struct usb_page_cache *pc; 844 struct mbuf *m; 845 846 switch (USB_GET_STATE(xfer)) { 847 case USB_ST_TRANSFERRED: 848 MOS_DPRINTFN("transfer of complete"); 849 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 850 /* FALLTHROUGH */ 851 case USB_ST_SETUP: 852 tr_setup: 853 /* 854 * XXX: don't send anything if there is no link? 855 */ 856 m = if_dequeue(ifp); 857 if (m == NULL) 858 return; 859 860 pc = usbd_xfer_get_frame(xfer, 0); 861 usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len); 862 863 usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len); 864 865 /* 866 * if there's a BPF listener, bounce a copy 867 * of this frame to him: 868 */ 869 BPF_MTAP(ifp, m); 870 871 m_freem(m); 872 873 usbd_transfer_submit(xfer); 874 875 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 876 return; 877 default: 878 MOS_DPRINTFN("usb error on tx: %s\n", usbd_errstr(error)); 879 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 880 if (error != USB_ERR_CANCELLED) { 881 usbd_xfer_set_stall(xfer); 882 goto tr_setup; 883 } 884 return; 885 } 886 } 887 888 static void 889 mos_tick(struct usb_ether *ue) 890 { 891 struct mos_softc *sc = uether_getsc(ue); 892 struct mii_data *mii = GET_MII(sc); 893 894 MOS_LOCK_ASSERT(sc, MA_OWNED); 895 896 mii_tick(mii); 897 if (!sc->mos_link && mii->mii_media_status & IFM_ACTIVE && 898 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 899 MOS_DPRINTFN("got link"); 900 sc->mos_link++; 901 mos_start(ue); 902 } 903 } 904 905 static void 906 mos_start(struct usb_ether *ue) 907 { 908 struct mos_softc *sc = uether_getsc(ue); 909 910 /* 911 * start the USB transfers, if not already started: 912 */ 913 usbd_transfer_start(sc->sc_xfer[MOS_ENDPT_TX]); 914 usbd_transfer_start(sc->sc_xfer[MOS_ENDPT_RX]); 915 usbd_transfer_start(sc->sc_xfer[MOS_ENDPT_INTR]); 916 } 917 918 static void 919 mos_init(struct usb_ether *ue) 920 { 921 struct mos_softc *sc = uether_getsc(ue); 922 if_t ifp = uether_getifp(ue); 923 uint8_t rxmode; 924 925 MOS_LOCK_ASSERT(sc, MA_OWNED); 926 927 /* Cancel pending I/O and free all RX/TX buffers. */ 928 mos_reset(sc); 929 930 /* Write MAC address */ 931 mos_writemac(sc, if_getlladdr(ifp)); 932 933 /* Read and set transmitter IPG values */ 934 sc->mos_ipgs[0] = mos_reg_read_1(sc, MOS_IPG0); 935 sc->mos_ipgs[1] = mos_reg_read_1(sc, MOS_IPG1); 936 mos_reg_write_1(sc, MOS_IPG0, sc->mos_ipgs[0]); 937 mos_reg_write_1(sc, MOS_IPG1, sc->mos_ipgs[1]); 938 939 /* 940 * Enable receiver and transmitter, bridge controls speed/duplex 941 * mode 942 */ 943 rxmode = mos_reg_read_1(sc, MOS_CTL); 944 rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB; 945 rxmode &= ~(MOS_CTL_SLEEP); 946 947 mos_setpromisc(ue); 948 949 /* XXX: broadcast mode? */ 950 mos_reg_write_1(sc, MOS_CTL, rxmode); 951 952 /* Load the multicast filter. */ 953 mos_setmulti(ue); 954 955 if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); 956 mos_start(ue); 957 } 958 959 static void 960 mos_intr_callback(struct usb_xfer *xfer, usb_error_t error) 961 { 962 struct mos_softc *sc = usbd_xfer_softc(xfer); 963 if_t ifp = uether_getifp(&sc->sc_ue); 964 struct usb_page_cache *pc; 965 uint32_t pkt; 966 int actlen; 967 968 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 969 970 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); 971 MOS_DPRINTFN("actlen %i", actlen); 972 973 switch (USB_GET_STATE(xfer)) { 974 case USB_ST_TRANSFERRED: 975 976 pc = usbd_xfer_get_frame(xfer, 0); 977 usbd_copy_out(pc, 0, &pkt, sizeof(pkt)); 978 /* FALLTHROUGH */ 979 case USB_ST_SETUP: 980 tr_setup: 981 return; 982 default: 983 if (error != USB_ERR_CANCELLED) { 984 usbd_xfer_set_stall(xfer); 985 goto tr_setup; 986 } 987 return; 988 } 989 } 990 991 /* 992 * Stop the adapter and free any mbufs allocated to the 993 * RX and TX lists. 994 */ 995 static void 996 mos_stop(struct usb_ether *ue) 997 { 998 struct mos_softc *sc = uether_getsc(ue); 999 if_t ifp = uether_getifp(ue); 1000 1001 mos_reset(sc); 1002 1003 MOS_LOCK_ASSERT(sc, MA_OWNED); 1004 if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); 1005 1006 /* stop all the transfers, if not already stopped */ 1007 usbd_transfer_stop(sc->sc_xfer[MOS_ENDPT_TX]); 1008 usbd_transfer_stop(sc->sc_xfer[MOS_ENDPT_RX]); 1009 usbd_transfer_stop(sc->sc_xfer[MOS_ENDPT_INTR]); 1010 1011 sc->mos_link = 0; 1012 } 1013