1 /* $NetBSD: if_mos.c,v 1.7 2020/04/02 04:09:36 nisimura 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.7 2020/04/02 04:09:36 nisimura 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 static 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_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); 146 static unsigned mos_uno_tx_prepare(struct usbnet *, struct mbuf *, 147 struct usbnet_chain *); 148 static int mos_uno_ioctl(struct ifnet *, u_long, void *); 149 static int mos_uno_init(struct ifnet *); 150 static void mos_chip_init(struct usbnet *); 151 static void mos_uno_stop(struct ifnet *ifp, int disable); 152 static int mos_uno_mii_read_reg(struct usbnet *, int, int, uint16_t *); 153 static int mos_uno_mii_write_reg(struct usbnet *, int, int, uint16_t); 154 static void mos_uno_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 const struct usbnet_ops mos_ops = { 166 .uno_stop = mos_uno_stop, 167 .uno_ioctl = mos_uno_ioctl, 168 .uno_read_reg = mos_uno_mii_read_reg, 169 .uno_write_reg = mos_uno_mii_write_reg, 170 .uno_statchg = mos_uno_mii_statchg, 171 .uno_tx_prepare = mos_uno_tx_prepare, 172 .uno_rx_loop = mos_uno_rx_loop, 173 .uno_init = mos_uno_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_uno_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_uno_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_uno_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 /* disable RX, TX prior to changing FDX, SPEEDSEL */ 423 val = mos_reg_read_1(un, MOS_CTL); 424 val &= ~(MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); 425 mos_reg_write_1(un, MOS_CTL, val); 426 427 /* reset register which counts dropped frames */ 428 mos_reg_write_1(un, MOS_FRAME_DROP_CNT, 0); 429 430 if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) 431 val |= MOS_CTL_FDX_ENB; 432 else 433 val &= ~(MOS_CTL_FDX_ENB); 434 435 if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 436 (IFM_ACTIVE | IFM_AVALID)) { 437 switch (IFM_SUBTYPE(mii->mii_media_active)) { 438 case IFM_100_TX: 439 val |= MOS_CTL_SPEEDSEL; 440 break; 441 case IFM_10_T: 442 val &= ~(MOS_CTL_SPEEDSEL); 443 break; 444 } 445 usbnet_set_link(un, true); 446 } 447 448 /* re-enable TX, RX */ 449 val |= (MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); 450 err = mos_reg_write_1(un, MOS_CTL, val); 451 452 if (err) 453 aprint_error_dev(un->un_dev, "media change failed\n"); 454 } 455 456 static void 457 mos_rcvfilt_locked(struct usbnet *un) 458 { 459 struct ifnet *ifp = usbnet_ifp(un); 460 struct ethercom *ec = usbnet_ec(un); 461 struct ether_multi *enm; 462 struct ether_multistep step; 463 u_int32_t h = 0; 464 u_int8_t rxmode, mchash[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 465 466 if (usbnet_isdying(un)) 467 return; 468 469 rxmode = mos_reg_read_1(un, MOS_CTL); 470 rxmode &= ~(MOS_CTL_ALLMULTI | MOS_CTL_RX_PROMISC); 471 472 ETHER_LOCK(ec); 473 if (ifp->if_flags & IFF_PROMISC) { 474 ec->ec_flags |= ETHER_F_ALLMULTI; 475 ETHER_UNLOCK(ec); 476 /* run promisc. mode */ 477 rxmode |= MOS_CTL_ALLMULTI; /* ??? */ 478 rxmode |= MOS_CTL_RX_PROMISC; 479 goto update; 480 } 481 ec->ec_flags &= ~ETHER_F_ALLMULTI; 482 ETHER_FIRST_MULTI(step, ec, enm); 483 while (enm != NULL) { 484 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { 485 ec->ec_flags |= ETHER_F_ALLMULTI; 486 ETHER_UNLOCK(ec); 487 memset(mchash, 0, sizeof(mchash)); /* correct ??? */ 488 /* accept all multicast frame */ 489 rxmode |= MOS_CTL_ALLMULTI; 490 goto update; 491 } 492 h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN); 493 /* 3(31:29) and 3(28:26) sampling to have uint8_t[8] */ 494 mchash[h >> 29] |= 1 << ((h >> 26) % 8); 495 ETHER_NEXT_MULTI(step, enm); 496 } 497 ETHER_UNLOCK(ec); 498 /* MOS receive filter is always on */ 499 update: 500 /* 501 * The datasheet claims broadcast frames were always accepted 502 * regardless of filter settings. But the hardware seems to 503 * filter broadcast frames, so pass them explicitly. 504 */ 505 mchash[7] |= 0x80; 506 mos_write_mcast(un, mchash); 507 mos_reg_write_1(un, MOS_CTL, rxmode); 508 } 509 510 static void 511 mos_reset(struct usbnet *un) 512 { 513 u_int8_t ctl; 514 515 if (usbnet_isdying(un)) 516 return; 517 518 ctl = mos_reg_read_1(un, MOS_CTL); 519 ctl &= ~(MOS_CTL_RX_PROMISC | MOS_CTL_ALLMULTI | MOS_CTL_TX_ENB | 520 MOS_CTL_RX_ENB); 521 /* Disable RX, TX, promiscuous and allmulticast mode */ 522 mos_reg_write_1(un, MOS_CTL, ctl); 523 524 /* Reset frame drop counter register to zero */ 525 mos_reg_write_1(un, MOS_FRAME_DROP_CNT, 0); 526 527 /* Wait a little while for the chip to get its brains in order. */ 528 DELAY(1000); 529 } 530 531 void 532 mos_chip_init(struct usbnet *un) 533 { 534 int i; 535 536 /* 537 * Rev.C devices have a pause threshold register which needs to be set 538 * at startup. 539 */ 540 if (mos_reg_read_1(un, MOS_PAUSE_TRHD) != -1) { 541 for (i = 0; i < MOS_PAUSE_REWRITES; i++) 542 mos_reg_write_1(un, MOS_PAUSE_TRHD, 0); 543 } 544 } 545 546 /* 547 * Probe for a MCS7x30 chip. 548 */ 549 static int 550 mos_match(device_t parent, cfdata_t match, void *aux) 551 { 552 struct usb_attach_arg *uaa = aux; 553 554 return (mos_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ? 555 UMATCH_VENDOR_PRODUCT : UMATCH_NONE); 556 } 557 558 /* 559 * Attach the interface. 560 */ 561 static void 562 mos_attach(device_t parent, device_t self, void *aux) 563 { 564 USBNET_MII_DECL_DEFAULT(unm); 565 struct usbnet * un = device_private(self); 566 struct usb_attach_arg *uaa = aux; 567 struct usbd_device *dev = uaa->uaa_device; 568 usbd_status err; 569 usb_interface_descriptor_t *id; 570 usb_endpoint_descriptor_t *ed; 571 char *devinfop; 572 int i; 573 574 aprint_naive("\n"); 575 aprint_normal("\n"); 576 devinfop = usbd_devinfo_alloc(dev, 0); 577 aprint_normal_dev(self, "%s\n", devinfop); 578 usbd_devinfo_free(devinfop); 579 580 un->un_dev = self; 581 un->un_udev = dev; 582 un->un_sc = un; 583 un->un_ops = &mos_ops; 584 un->un_rx_xfer_flags = USBD_SHORT_XFER_OK; 585 un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER; 586 un->un_rx_list_cnt = MOS_RX_LIST_CNT; 587 un->un_tx_list_cnt = MOS_TX_LIST_CNT; 588 un->un_rx_bufsz = un->un_tx_bufsz = MOS_BUFSZ; 589 590 err = usbd_set_config_no(dev, MOS_CONFIG_NO, 1); 591 if (err) { 592 aprint_error_dev(self, "failed to set configuration" 593 ", err=%s\n", usbd_errstr(err)); 594 return; 595 } 596 597 err = usbd_device2interface_handle(dev, MOS_IFACE_IDX, &un->un_iface); 598 if (err) { 599 aprint_error_dev(self, "failed getting interface handle" 600 ", err=%s\n", usbd_errstr(err)); 601 return; 602 } 603 604 un->un_flags = mos_lookup(uaa->uaa_vendor, uaa->uaa_product)->mos_flags; 605 606 id = usbd_get_interface_descriptor(un->un_iface); 607 608 /* Find endpoints. */ 609 for (i = 0; i < id->bNumEndpoints; i++) { 610 ed = usbd_interface2endpoint_descriptor(un->un_iface, i); 611 if (!ed) { 612 aprint_error_dev(self, "couldn't get ep %d\n", i); 613 return; 614 } 615 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 616 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 617 un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress; 618 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 619 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 620 un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress; 621 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 622 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 623 un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress; 624 } 625 } 626 627 if (un->un_flags & MCS7730) 628 aprint_normal_dev(self, "MCS7730\n"); 629 else if (un->un_flags & MCS7830) 630 aprint_normal_dev(self, "MCS7830\n"); 631 else if (un->un_flags & MCS7832) 632 aprint_normal_dev(self, "MCS7832\n"); 633 634 /* Set these up now for register access. */ 635 usbnet_attach(un, "mosdet"); 636 637 mos_chip_init(un); 638 639 /* 640 * Read MAC address, inform the world. 641 */ 642 err = mos_readmac(un); 643 if (err) { 644 aprint_error_dev(self, "couldn't read MAC address\n"); 645 return; 646 } 647 648 struct ifnet *ifp = usbnet_ifp(un); 649 ifp->if_capabilities = ETHERCAP_VLAN_MTU; 650 651 usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 652 0, &unm); 653 } 654 655 /* 656 * A frame has been uploaded: pass the resulting mbuf chain up to 657 * the higher level protocols. 658 */ 659 void 660 mos_uno_rx_loop(struct usbnet * un, struct usbnet_chain *c, uint32_t total_len) 661 { 662 struct ifnet *ifp = usbnet_ifp(un); 663 uint8_t *buf = c->unc_buf; 664 u_int8_t rxstat; 665 u_int16_t pktlen = 0; 666 667 DPRINTFN(5,("%s: %s: enter len %u\n", 668 device_xname(un->un_dev), __func__, total_len)); 669 670 if (total_len <= 1) 671 return; 672 673 /* evaluate status byte at the end */ 674 pktlen = total_len - 1; 675 if (pktlen > un->un_rx_bufsz) { 676 if_statinc(ifp, if_ierrors); 677 return; 678 } 679 rxstat = buf[pktlen] & MOS_RXSTS_MASK; 680 681 if (rxstat != MOS_RXSTS_VALID) { 682 DPRINTF(("%s: erroneous frame received: ", 683 device_xname(un->un_dev))); 684 if (rxstat & MOS_RXSTS_SHORT_FRAME) 685 DPRINTF(("frame size less than 64 bytes\n")); 686 if (rxstat & MOS_RXSTS_LARGE_FRAME) 687 DPRINTF(("frame size larger than 1532 bytes\n")); 688 if (rxstat & MOS_RXSTS_CRC_ERROR) 689 DPRINTF(("CRC error\n")); 690 if (rxstat & MOS_RXSTS_ALIGN_ERROR) 691 DPRINTF(("alignment error\n")); 692 if_statinc(ifp, if_ierrors); 693 return; 694 } 695 696 if (pktlen < sizeof(struct ether_header) ) { 697 if_statinc(ifp, if_ierrors); 698 return; 699 } 700 701 usbnet_enqueue(un, c->unc_buf, pktlen, 0, 0, 0); 702 } 703 704 static unsigned 705 mos_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) 706 { 707 int length; 708 709 if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz) 710 return 0; 711 712 m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf); 713 length = m->m_pkthdr.len; 714 715 DPRINTFN(5,("%s: %s: len %u\n", 716 device_xname(un->un_dev), __func__, length)); 717 718 return length; 719 } 720 721 static int 722 mos_init_locked(struct ifnet *ifp) 723 { 724 struct usbnet * const un = ifp->if_softc; 725 u_int8_t rxmode; 726 unsigned char ipgs[2]; 727 728 if (usbnet_isdying(un)) 729 return EIO; 730 731 /* Cancel pending I/O */ 732 usbnet_stop(un, ifp, 1); 733 734 /* Reset the ethernet interface. */ 735 mos_reset(un); 736 737 /* Write MAC address. */ 738 mos_writemac(un); 739 740 /* Read and set transmitter IPG values */ 741 ipgs[0] = mos_reg_read_1(un, MOS_IPG0); 742 ipgs[1] = mos_reg_read_1(un, MOS_IPG1); 743 mos_reg_write_1(un, MOS_IPG0, ipgs[0]); 744 mos_reg_write_1(un, MOS_IPG1, ipgs[1]); 745 746 /* Accept multicast frame or run promisc. mode */ 747 mos_rcvfilt_locked(un); 748 749 /* Enable receiver and transmitter, bridge controls speed/duplex mode */ 750 rxmode = mos_reg_read_1(un, MOS_CTL); 751 rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB; 752 rxmode &= ~(MOS_CTL_SLEEP); 753 mos_reg_write_1(un, MOS_CTL, rxmode); 754 755 return usbnet_init_rx_tx(un); 756 } 757 758 static int 759 mos_uno_init(struct ifnet *ifp) 760 { 761 struct usbnet * const un = ifp->if_softc; 762 763 usbnet_lock_core(un); 764 usbnet_busy(un); 765 int ret = mos_init_locked(ifp); 766 usbnet_unbusy(un); 767 usbnet_unlock_core(un); 768 769 return ret; 770 } 771 772 static int 773 mos_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) 774 { 775 struct usbnet * const un = ifp->if_softc; 776 777 usbnet_lock_core(un); 778 usbnet_busy(un); 779 780 switch (cmd) { 781 case SIOCADDMULTI: 782 case SIOCDELMULTI: 783 mos_rcvfilt_locked(un); 784 break; 785 default: 786 break; 787 } 788 789 usbnet_unbusy(un); 790 usbnet_unlock_core(un); 791 792 return 0; 793 } 794 795 void 796 mos_uno_stop(struct ifnet *ifp, int disable) 797 { 798 struct usbnet * const un = ifp->if_softc; 799 800 mos_reset(un); 801 } 802