1 /* $NetBSD: if_mos.c,v 1.1 2019/09/20 10:34:54 mrg Exp $ */ 2 /* $OpenBSD: if_mos.c,v 1.40 2019/07/07 06:40:10 kevlo Exp $ */ 3 4 /* 5 * Copyright (c) 2008 Johann Christian Rode <jcrode@gmx.net> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* 21 * Copyright (c) 2005, 2006, 2007 Jonathan Gray <jsg@openbsd.org> 22 * 23 * Permission to use, copy, modify, and distribute this software for any 24 * purpose with or without fee is hereby granted, provided that the above 25 * copyright notice and this permission notice appear in all copies. 26 * 27 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 28 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 29 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 30 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 31 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 32 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 33 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 34 */ 35 36 /* 37 * Copyright (c) 1997, 1998, 1999, 2000-2003 38 * Bill Paul <wpaul@windriver.com>. All rights reserved. 39 * 40 * Redistribution and use in source and binary forms, with or without 41 * modification, are permitted provided that the following conditions 42 * are met: 43 * 1. Redistributions of source code must retain the above copyright 44 * notice, this list of conditions and the following disclaimer. 45 * 2. Redistributions in binary form must reproduce the above copyright 46 * notice, this list of conditions and the following disclaimer in the 47 * documentation and/or other materials provided with the distribution. 48 * 3. All advertising materials mentioning features or use of this software 49 * must display the following acknowledgement: 50 * This product includes software developed by Bill Paul. 51 * 4. Neither the name of the author nor the names of any co-contributors 52 * may be used to endorse or promote products derived from this software 53 * without specific prior written permission. 54 * 55 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 58 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 59 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 60 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 61 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 62 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 63 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 64 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 65 * THE POSSIBILITY OF SUCH DAMAGE. 66 */ 67 68 /* 69 * Moschip MCS7730/MCS7830/MCS7832 USB to Ethernet controller 70 * The datasheet is available at the following URL: 71 * http://www.moschip.com/data/products/MCS7830/Data%20Sheet_7830.pdf 72 */ 73 74 #include <sys/cdefs.h> 75 __KERNEL_RCSID(0, "$NetBSD: if_mos.c,v 1.1 2019/09/20 10:34:54 mrg Exp $"); 76 77 #include <sys/param.h> 78 79 #include <dev/usb/usbnet.h> 80 #include <dev/usb/if_mosreg.h> 81 82 #define MOS_PAUSE_REWRITES 3 83 84 #define MOS_TIMEOUT 1000 85 86 #define MOS_RX_LIST_CNT 1 87 #define MOS_TX_LIST_CNT 1 88 89 /* Maximum size of a fast ethernet frame plus one byte for the status */ 90 #define MOS_BUFSZ (ETHER_MAX_LEN+1) 91 92 /* 93 * USB endpoints. 94 */ 95 #define MOS_ENDPT_RX 0 96 #define MOS_ENDPT_TX 1 97 #define MOS_ENDPT_INTR 2 98 #define MOS_ENDPT_MAX 3 99 100 /* 101 * USB vendor requests. 102 */ 103 #define MOS_UR_READREG 0x0e 104 #define MOS_UR_WRITEREG 0x0d 105 106 #define MOS_CONFIG_NO 1 107 #define MOS_IFACE_IDX 0 108 109 struct mos_type { 110 struct usb_devno mos_dev; 111 u_int16_t mos_flags; 112 #define MCS7730 0x0001 /* MCS7730 */ 113 #define MCS7830 0x0002 /* MCS7830 */ 114 #define MCS7832 0x0004 /* MCS7832 */ 115 }; 116 117 #define MOS_INC(x, y) (x) = (x + 1) % y 118 119 #ifdef MOS_DEBUG 120 #define DPRINTF(x) do { if (mosdebug) printf x; } while (0) 121 #define DPRINTFN(n,x) do { if (mosdebug >= (n)) printf x; } while (0) 122 int mosdebug = 0; 123 #else 124 #define DPRINTF(x) __nothing 125 #define DPRINTFN(n,x) __nothing 126 #endif 127 128 /* 129 * Various supported device vendors/products. 130 */ 131 const struct mos_type mos_devs[] = { 132 { { USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7730 }, MCS7730 }, 133 { { USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7830 }, MCS7830 }, 134 { { USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7832 }, MCS7832 }, 135 { { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN030 }, MCS7830 }, 136 }; 137 #define mos_lookup(v, p) ((const struct mos_type *)usb_lookup(mos_devs, v, p)) 138 139 static int mos_match(device_t, cfdata_t, void *); 140 static void mos_attach(device_t, device_t, void *); 141 142 CFATTACH_DECL_NEW(mos, sizeof(struct usbnet), 143 mos_match, mos_attach, usbnet_detach, usbnet_activate); 144 145 static void mos_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); 146 static unsigned mos_tx_prepare(struct usbnet *, struct mbuf *, 147 struct usbnet_chain *); 148 static int mos_ioctl(struct ifnet *, u_long, void *); 149 static int mos_init(struct ifnet *); 150 static void mos_chip_init(struct usbnet *); 151 static void mos_stop(struct ifnet *ifp, int disable); 152 static int mos_mii_read_reg(struct usbnet *, int, int, uint16_t *); 153 static int mos_mii_write_reg(struct usbnet *, int, int, uint16_t); 154 static void mos_mii_statchg(struct ifnet *); 155 static void mos_reset(struct usbnet *); 156 157 static int mos_reg_read_1(struct usbnet *, int); 158 static int mos_reg_read_2(struct usbnet *, int); 159 static int mos_reg_write_1(struct usbnet *, int, int); 160 static int mos_reg_write_2(struct usbnet *, int, int); 161 static int mos_readmac(struct usbnet *); 162 static int mos_writemac(struct usbnet *); 163 static int mos_write_mcast(struct usbnet *, uint8_t *); 164 165 static struct usbnet_ops mos_ops = { 166 .uno_stop = mos_stop, 167 .uno_ioctl = mos_ioctl, 168 .uno_read_reg = mos_mii_read_reg, 169 .uno_write_reg = mos_mii_write_reg, 170 .uno_statchg = mos_mii_statchg, 171 .uno_tx_prepare = mos_tx_prepare, 172 .uno_rx_loop = mos_rx_loop, 173 .uno_init = mos_init, 174 }; 175 176 static int 177 mos_reg_read_1(struct usbnet *un, int reg) 178 { 179 usb_device_request_t req; 180 usbd_status err; 181 uByte val = 0; 182 183 if (usbnet_isdying(un)) 184 return 0; 185 186 req.bmRequestType = UT_READ_VENDOR_DEVICE; 187 req.bRequest = MOS_UR_READREG; 188 USETW(req.wValue, 0); 189 USETW(req.wIndex, reg); 190 USETW(req.wLength, 1); 191 192 err = usbd_do_request(un->un_udev, &req, &val); 193 194 if (err) { 195 aprint_error_dev(un->un_dev, "read reg %x\n", reg); 196 return 0; 197 } 198 199 return val; 200 } 201 202 static int 203 mos_reg_read_2(struct usbnet *un, int reg) 204 { 205 usb_device_request_t req; 206 usbd_status err; 207 uWord val; 208 209 if (usbnet_isdying(un)) 210 return 0; 211 212 USETW(val,0); 213 214 req.bmRequestType = UT_READ_VENDOR_DEVICE; 215 req.bRequest = MOS_UR_READREG; 216 USETW(req.wValue, 0); 217 USETW(req.wIndex, reg); 218 USETW(req.wLength, 2); 219 220 err = usbd_do_request(un->un_udev, &req, &val); 221 222 if (err) { 223 aprint_error_dev(un->un_dev, "read reg2 %x\n", reg); 224 return 0; 225 } 226 227 return UGETW(val); 228 } 229 230 static int 231 mos_reg_write_1(struct usbnet *un, int reg, int aval) 232 { 233 usb_device_request_t req; 234 usbd_status err; 235 uByte val; 236 237 if (usbnet_isdying(un)) 238 return 0; 239 240 val = aval; 241 242 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 243 req.bRequest = MOS_UR_WRITEREG; 244 USETW(req.wValue, 0); 245 USETW(req.wIndex, reg); 246 USETW(req.wLength, 1); 247 248 err = usbd_do_request(un->un_udev, &req, &val); 249 250 if (err) 251 aprint_error_dev(un->un_dev, "write reg %x <- %x\n", 252 reg, aval); 253 254 return 0; 255 } 256 257 static int 258 mos_reg_write_2(struct usbnet *un, int reg, int aval) 259 { 260 usb_device_request_t req; 261 usbd_status err; 262 uWord val; 263 264 USETW(val, aval); 265 266 if (usbnet_isdying(un)) 267 return EIO; 268 269 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 270 req.bRequest = MOS_UR_WRITEREG; 271 USETW(req.wValue, 0); 272 USETW(req.wIndex, reg); 273 USETW(req.wLength, 2); 274 275 err = usbd_do_request(un->un_udev, &req, &val); 276 277 if (err) 278 aprint_error_dev(un->un_dev, "write reg2 %x <- %x\n", 279 reg, aval); 280 281 return 0; 282 } 283 284 static int 285 mos_readmac(struct usbnet *un) 286 { 287 usb_device_request_t req; 288 usbd_status err; 289 290 if (usbnet_isdying(un)) 291 return 0; 292 293 req.bmRequestType = UT_READ_VENDOR_DEVICE; 294 req.bRequest = MOS_UR_READREG; 295 USETW(req.wValue, 0); 296 USETW(req.wIndex, MOS_MAC); 297 USETW(req.wLength, ETHER_ADDR_LEN); 298 299 err = usbd_do_request(un->un_udev, &req, un->un_eaddr); 300 301 if (err) 302 aprint_error_dev(un->un_dev, "%s: failed", __func__); 303 304 return err; 305 } 306 307 static int 308 mos_writemac(struct usbnet *un) 309 { 310 usb_device_request_t req; 311 usbd_status err; 312 313 if (usbnet_isdying(un)) 314 return 0; 315 316 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 317 req.bRequest = MOS_UR_WRITEREG; 318 USETW(req.wValue, 0); 319 USETW(req.wIndex, MOS_MAC); 320 USETW(req.wLength, ETHER_ADDR_LEN); 321 322 err = usbd_do_request(un->un_udev, &req, un->un_eaddr); 323 324 if (err) 325 aprint_error_dev(un->un_dev, "%s: failed", __func__); 326 327 return 0; 328 } 329 330 static int 331 mos_write_mcast(struct usbnet *un, uint8_t *hashtbl) 332 { 333 usb_device_request_t req; 334 usbd_status err; 335 336 if (usbnet_isdying(un)) 337 return EIO; 338 339 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 340 req.bRequest = MOS_UR_WRITEREG; 341 USETW(req.wValue, 0); 342 USETW(req.wIndex, MOS_MCAST_TABLE); 343 USETW(req.wLength, 8); 344 345 err = usbd_do_request(un->un_udev, &req, hashtbl); 346 347 if (err) { 348 aprint_error_dev(un->un_dev, "%s: failed", __func__); 349 return(-1); 350 } 351 352 return 0; 353 } 354 355 static int 356 mos_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) 357 { 358 int i, res; 359 360 mos_reg_write_2(un, MOS_PHY_DATA, 0); 361 mos_reg_write_1(un, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) | 362 MOS_PHYCTL_READ); 363 mos_reg_write_1(un, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) | 364 MOS_PHYSTS_PENDING); 365 366 for (i = 0; i < MOS_TIMEOUT; i++) { 367 if (mos_reg_read_1(un, MOS_PHY_STS) & MOS_PHYSTS_READY) 368 break; 369 } 370 if (i == MOS_TIMEOUT) { 371 aprint_error_dev(un->un_dev, "read PHY failed\n"); 372 return EIO; 373 } 374 375 res = mos_reg_read_2(un, MOS_PHY_DATA); 376 *val = res; 377 378 DPRINTFN(10,("%s: %s: phy %d reg %d val %u\n", 379 device_xname(un->un_dev), __func__, phy, reg, res)); 380 381 return 0; 382 } 383 384 static int 385 mos_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val) 386 { 387 int i; 388 389 DPRINTFN(10,("%s: %s: phy %d reg %d val %u\n", 390 device_xname(un->un_dev), __func__, phy, reg, val)); 391 392 mos_reg_write_2(un, MOS_PHY_DATA, val); 393 mos_reg_write_1(un, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) | 394 MOS_PHYCTL_WRITE); 395 mos_reg_write_1(un, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) | 396 MOS_PHYSTS_PENDING); 397 398 for (i = 0; i < MOS_TIMEOUT; i++) { 399 if (mos_reg_read_1(un, MOS_PHY_STS) & MOS_PHYSTS_READY) 400 break; 401 } 402 if (i == MOS_TIMEOUT) { 403 aprint_error_dev(un->un_dev, "write PHY failed\n"); 404 return EIO; 405 } 406 407 return 0; 408 } 409 410 void 411 mos_mii_statchg(struct ifnet *ifp) 412 { 413 struct usbnet * const un = ifp->if_softc; 414 struct mii_data * const mii = usbnet_mii(un); 415 int val, err; 416 417 if (usbnet_isdying(un)) 418 return; 419 420 DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 421 422 usbnet_lock_mii(un); 423 424 /* disable RX, TX prior to changing FDX, SPEEDSEL */ 425 val = mos_reg_read_1(un, MOS_CTL); 426 val &= ~(MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); 427 mos_reg_write_1(un, MOS_CTL, val); 428 429 /* reset register which counts dropped frames */ 430 mos_reg_write_1(un, MOS_FRAME_DROP_CNT, 0); 431 432 if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) 433 val |= MOS_CTL_FDX_ENB; 434 else 435 val &= ~(MOS_CTL_FDX_ENB); 436 437 if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 438 (IFM_ACTIVE | IFM_AVALID)) { 439 switch (IFM_SUBTYPE(mii->mii_media_active)) { 440 case IFM_100_TX: 441 val |= MOS_CTL_SPEEDSEL; 442 break; 443 case IFM_10_T: 444 val &= ~(MOS_CTL_SPEEDSEL); 445 break; 446 } 447 usbnet_set_link(un, true); 448 } 449 450 /* re-enable TX, RX */ 451 val |= (MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); 452 err = mos_reg_write_1(un, MOS_CTL, val); 453 usbnet_unlock_mii(un); 454 455 if (err) 456 aprint_error_dev(un->un_dev, "media change failed\n"); 457 } 458 459 static void 460 mos_setiff_locked(struct usbnet *un) 461 { 462 struct ifnet *ifp = usbnet_ifp(un); 463 struct ethercom *ec = usbnet_ec(un); 464 struct ether_multi *enm; 465 struct ether_multistep step; 466 u_int32_t h = 0; 467 u_int8_t rxmode, hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 468 469 if (usbnet_isdying(un)) 470 return; 471 472 rxmode = mos_reg_read_1(un, MOS_CTL); 473 rxmode &= ~(MOS_CTL_ALLMULTI | MOS_CTL_RX_PROMISC); 474 475 if (ifp->if_flags & IFF_PROMISC || ec->ec_multicnt > 0) { 476 allmulti: 477 ETHER_LOCK(ec); 478 ec->ec_flags |= ETHER_F_ALLMULTI; 479 ETHER_UNLOCK(ec); 480 rxmode |= MOS_CTL_ALLMULTI; 481 if (ifp->if_flags & IFF_PROMISC) 482 rxmode |= MOS_CTL_RX_PROMISC; 483 } else { 484 /* now program new ones */ 485 ETHER_LOCK(ec); 486 ec->ec_flags &= ~ETHER_F_ALLMULTI; 487 488 ETHER_FIRST_MULTI(step, ec, enm); 489 while (enm != NULL) { 490 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 491 ETHER_ADDR_LEN)) { 492 memset(hashtbl, 0, sizeof(hashtbl)); 493 ETHER_UNLOCK(ec); 494 goto allmulti; 495 } 496 h = ether_crc32_be(enm->enm_addrlo, 497 ETHER_ADDR_LEN) >> 26; 498 hashtbl[h / 8] |= 1 << (h % 8); 499 500 ETHER_NEXT_MULTI(step, enm); 501 } 502 ETHER_UNLOCK(ec); 503 } 504 505 /* 506 * The datasheet claims broadcast frames were always accepted 507 * regardless of filter settings. But the hardware seems to 508 * filter broadcast frames, so pass them explicitly. 509 */ 510 h = ether_crc32_be(etherbroadcastaddr, ETHER_ADDR_LEN) >> 26; 511 hashtbl[h / 8] |= 1 << (h % 8); 512 513 mos_write_mcast(un, hashtbl); 514 mos_reg_write_1(un, MOS_CTL, rxmode); 515 } 516 517 static void 518 mos_setiff(struct usbnet *un) 519 { 520 usbnet_lock_mii(un); 521 mos_setiff_locked(un); 522 usbnet_unlock_mii(un); 523 } 524 525 static void 526 mos_reset(struct usbnet *un) 527 { 528 u_int8_t ctl; 529 530 if (usbnet_isdying(un)) 531 return; 532 533 ctl = mos_reg_read_1(un, MOS_CTL); 534 ctl &= ~(MOS_CTL_RX_PROMISC | MOS_CTL_ALLMULTI | MOS_CTL_TX_ENB | 535 MOS_CTL_RX_ENB); 536 /* Disable RX, TX, promiscuous and allmulticast mode */ 537 mos_reg_write_1(un, MOS_CTL, ctl); 538 539 /* Reset frame drop counter register to zero */ 540 mos_reg_write_1(un, MOS_FRAME_DROP_CNT, 0); 541 542 /* Wait a little while for the chip to get its brains in order. */ 543 DELAY(1000); 544 } 545 546 void 547 mos_chip_init(struct usbnet *un) 548 { 549 int i; 550 551 /* 552 * Rev.C devices have a pause threshold register which needs to be set 553 * at startup. 554 */ 555 if (mos_reg_read_1(un, MOS_PAUSE_TRHD) != -1) { 556 for (i = 0; i < MOS_PAUSE_REWRITES; i++) 557 mos_reg_write_1(un, MOS_PAUSE_TRHD, 0); 558 } 559 } 560 561 /* 562 * Probe for a MCS7x30 chip. 563 */ 564 static int 565 mos_match(device_t parent, cfdata_t match, void *aux) 566 { 567 struct usb_attach_arg *uaa = aux; 568 569 return (mos_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ? 570 UMATCH_VENDOR_PRODUCT : UMATCH_NONE); 571 } 572 573 /* 574 * Attach the interface. 575 */ 576 static void 577 mos_attach(device_t parent, device_t self, void *aux) 578 { 579 USBNET_MII_DECL_DEFAULT(unm); 580 struct usbnet * un = device_private(self); 581 struct usb_attach_arg *uaa = aux; 582 struct usbd_device *dev = uaa->uaa_device; 583 usbd_status err; 584 usb_interface_descriptor_t *id; 585 usb_endpoint_descriptor_t *ed; 586 char *devinfop; 587 int i; 588 589 aprint_naive("\n"); 590 aprint_normal("\n"); 591 devinfop = usbd_devinfo_alloc(dev, 0); 592 aprint_normal_dev(self, "%s\n", devinfop); 593 usbd_devinfo_free(devinfop); 594 595 un->un_dev = self; 596 un->un_udev = dev; 597 un->un_sc = un; 598 un->un_ops = &mos_ops; 599 un->un_rx_xfer_flags = USBD_SHORT_XFER_OK; 600 un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER; 601 un->un_rx_list_cnt = MOS_RX_LIST_CNT; 602 un->un_tx_list_cnt = MOS_TX_LIST_CNT; 603 un->un_rx_bufsz = un->un_tx_bufsz = MOS_BUFSZ; 604 605 err = usbd_set_config_no(dev, MOS_CONFIG_NO, 1); 606 if (err) { 607 aprint_error_dev(self, "failed to set configuration" 608 ", err=%s\n", usbd_errstr(err)); 609 return; 610 } 611 612 err = usbd_device2interface_handle(dev, MOS_IFACE_IDX, &un->un_iface); 613 if (err) { 614 aprint_error_dev(self, "failed getting interface handle" 615 ", err=%s\n", usbd_errstr(err)); 616 return; 617 } 618 619 un->un_flags = mos_lookup(uaa->uaa_vendor, uaa->uaa_product)->mos_flags; 620 621 id = usbd_get_interface_descriptor(un->un_iface); 622 623 /* Find endpoints. */ 624 for (i = 0; i < id->bNumEndpoints; i++) { 625 ed = usbd_interface2endpoint_descriptor(un->un_iface, i); 626 if (!ed) { 627 aprint_error_dev(self, "couldn't get ep %d\n", i); 628 return; 629 } 630 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 631 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 632 un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress; 633 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 634 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 635 un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress; 636 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 637 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 638 un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress; 639 } 640 } 641 642 if (un->un_flags & MCS7730) 643 aprint_normal_dev(self, "MCS7730\n"); 644 else if (un->un_flags & MCS7830) 645 aprint_normal_dev(self, "MCS7830\n"); 646 else if (un->un_flags & MCS7832) 647 aprint_normal_dev(self, "MCS7832\n"); 648 649 /* Set these up now for register access. */ 650 usbnet_attach(un, "mosdet"); 651 652 mos_chip_init(un); 653 654 /* 655 * Read MAC address, inform the world. 656 */ 657 err = mos_readmac(un); 658 if (err) { 659 aprint_error_dev(self, "couldn't read MAC address\n"); 660 return; 661 } 662 663 struct ifnet *ifp = usbnet_ifp(un); 664 ifp->if_capabilities = ETHERCAP_VLAN_MTU; 665 666 usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 667 0, &unm); 668 } 669 670 /* 671 * A frame has been uploaded: pass the resulting mbuf chain up to 672 * the higher level protocols. 673 */ 674 void 675 mos_rx_loop(struct usbnet * un, struct usbnet_chain *c, uint32_t total_len) 676 { 677 struct ifnet *ifp = usbnet_ifp(un); 678 uint8_t *buf = c->unc_buf; 679 u_int8_t rxstat; 680 u_int16_t pktlen = 0; 681 682 DPRINTFN(5,("%s: %s: enter len %u\n", 683 device_xname(un->un_dev), __func__, total_len)); 684 685 if (total_len <= 1) 686 return; 687 688 /* evaluate status byte at the end */ 689 pktlen = total_len - 1; 690 if (pktlen > un->un_rx_bufsz) { 691 ifp->if_ierrors++; 692 return; 693 } 694 rxstat = buf[pktlen] & MOS_RXSTS_MASK; 695 696 if (rxstat != MOS_RXSTS_VALID) { 697 DPRINTF(("%s: erroneous frame received: ", 698 device_xname(un->un_dev))); 699 if (rxstat & MOS_RXSTS_SHORT_FRAME) 700 DPRINTF(("frame size less than 64 bytes\n")); 701 if (rxstat & MOS_RXSTS_LARGE_FRAME) 702 DPRINTF(("frame size larger than 1532 bytes\n")); 703 if (rxstat & MOS_RXSTS_CRC_ERROR) 704 DPRINTF(("CRC error\n")); 705 if (rxstat & MOS_RXSTS_ALIGN_ERROR) 706 DPRINTF(("alignment error\n")); 707 ifp->if_ierrors++; 708 return; 709 } 710 711 if (pktlen < sizeof(struct ether_header) ) { 712 ifp->if_ierrors++; 713 return; 714 } 715 716 usbnet_enqueue(un, c->unc_buf, pktlen, 0, 0, 0); 717 } 718 719 static unsigned 720 mos_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) 721 { 722 int length; 723 724 usbnet_isowned_tx(un); 725 726 if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz) 727 return 0; 728 729 m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf); 730 length = m->m_pkthdr.len; 731 732 DPRINTFN(5,("%s: %s: len %u\n", 733 device_xname(un->un_dev), __func__, length)); 734 735 return length; 736 } 737 738 static int 739 mos_init_locked(struct ifnet *ifp) 740 { 741 struct usbnet * const un = ifp->if_softc; 742 u_int8_t rxmode; 743 unsigned char ipgs[2]; 744 745 if (usbnet_isdying(un)) 746 return EIO; 747 748 /* Cancel pending I/O */ 749 usbnet_stop(un, ifp, 1); 750 751 usbnet_lock_mii_un_locked(un); 752 753 /* Reset the ethernet interface. */ 754 mos_reset(un); 755 756 /* Write MAC address. */ 757 mos_writemac(un); 758 759 /* Read and set transmitter IPG values */ 760 ipgs[0] = mos_reg_read_1(un, MOS_IPG0); 761 ipgs[1] = mos_reg_read_1(un, MOS_IPG1); 762 mos_reg_write_1(un, MOS_IPG0, ipgs[0]); 763 mos_reg_write_1(un, MOS_IPG1, ipgs[1]); 764 765 /* Program promiscuous mode and multicast filters. */ 766 mos_setiff_locked(un); 767 768 /* Enable receiver and transmitter, bridge controls speed/duplex mode */ 769 rxmode = mos_reg_read_1(un, MOS_CTL); 770 rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB; 771 rxmode &= ~(MOS_CTL_SLEEP); 772 mos_reg_write_1(un, MOS_CTL, rxmode); 773 774 usbnet_unlock_mii_un_locked(un); 775 776 return usbnet_init_rx_tx(un); 777 } 778 779 static int 780 mos_init(struct ifnet *ifp) 781 { 782 struct usbnet * const un = ifp->if_softc; 783 784 usbnet_lock(un); 785 int ret = mos_init_locked(ifp); 786 usbnet_unlock(un); 787 788 return ret; 789 } 790 791 static int 792 mos_ioctl(struct ifnet *ifp, u_long cmd, void *data) 793 { 794 struct usbnet * const un = ifp->if_softc; 795 796 switch (cmd) { 797 case SIOCADDMULTI: 798 case SIOCDELMULTI: 799 mos_setiff(un); 800 break; 801 default: 802 break; 803 } 804 805 return 0; 806 } 807 808 void 809 mos_stop(struct ifnet *ifp, int disable) 810 { 811 struct usbnet * const un = ifp->if_softc; 812 813 usbnet_lock_mii_un_locked(un); 814 mos_reset(un); 815 usbnet_unlock_mii_un_locked(un); 816 } 817