1 /* $NetBSD: if_mos.c,v 1.24 2022/10/10 18:30:28 martin 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.24 2022/10/10 18:30:28 martin 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 void mos_uno_mcast(struct ifnet *); 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_mcast = mos_uno_mcast, 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 (usbnet_isdying(un)) { 368 *val = 0; 369 return ENXIO; 370 } 371 if (mos_reg_read_1(un, MOS_PHY_STS) & MOS_PHYSTS_READY) 372 break; 373 } 374 if (i == MOS_TIMEOUT) { 375 aprint_error_dev(un->un_dev, "read PHY failed\n"); 376 *val = 0; 377 return EIO; 378 } 379 380 res = mos_reg_read_2(un, MOS_PHY_DATA); 381 *val = res; 382 383 DPRINTFN(10,("%s: %s: phy %d reg %d val %u\n", 384 device_xname(un->un_dev), __func__, phy, reg, res)); 385 386 return 0; 387 } 388 389 static int 390 mos_uno_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val) 391 { 392 int i; 393 394 DPRINTFN(10,("%s: %s: phy %d reg %d val %u\n", 395 device_xname(un->un_dev), __func__, phy, reg, val)); 396 397 mos_reg_write_2(un, MOS_PHY_DATA, val); 398 mos_reg_write_1(un, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) | 399 MOS_PHYCTL_WRITE); 400 mos_reg_write_1(un, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) | 401 MOS_PHYSTS_PENDING); 402 403 for (i = 0; i < MOS_TIMEOUT; i++) { 404 if (usbnet_isdying(un)) 405 return ENXIO; 406 if (mos_reg_read_1(un, MOS_PHY_STS) & MOS_PHYSTS_READY) 407 break; 408 } 409 if (i == MOS_TIMEOUT) { 410 aprint_error_dev(un->un_dev, "write PHY failed\n"); 411 return EIO; 412 } 413 414 return 0; 415 } 416 417 void 418 mos_uno_mii_statchg(struct ifnet *ifp) 419 { 420 struct usbnet * const un = ifp->if_softc; 421 struct mii_data * const mii = usbnet_mii(un); 422 int val, err; 423 424 if (usbnet_isdying(un)) 425 return; 426 427 DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev), __func__)); 428 429 /* disable RX, TX prior to changing FDX, SPEEDSEL */ 430 val = mos_reg_read_1(un, MOS_CTL); 431 val &= ~(MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); 432 mos_reg_write_1(un, MOS_CTL, val); 433 434 /* reset register which counts dropped frames */ 435 mos_reg_write_1(un, MOS_FRAME_DROP_CNT, 0); 436 437 if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) 438 val |= MOS_CTL_FDX_ENB; 439 else 440 val &= ~(MOS_CTL_FDX_ENB); 441 442 if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 443 (IFM_ACTIVE | IFM_AVALID)) { 444 switch (IFM_SUBTYPE(mii->mii_media_active)) { 445 case IFM_100_TX: 446 val |= MOS_CTL_SPEEDSEL; 447 break; 448 case IFM_10_T: 449 val &= ~(MOS_CTL_SPEEDSEL); 450 break; 451 } 452 usbnet_set_link(un, true); 453 } 454 455 /* re-enable TX, RX */ 456 val |= (MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); 457 err = mos_reg_write_1(un, MOS_CTL, val); 458 459 if (err) 460 aprint_error_dev(un->un_dev, "media change failed\n"); 461 } 462 463 static void 464 mos_uno_mcast(struct ifnet *ifp) 465 { 466 struct usbnet *un = ifp->if_softc; 467 struct ethercom *ec = usbnet_ec(un); 468 struct ether_multi *enm; 469 struct ether_multistep step; 470 u_int32_t h = 0; 471 u_int8_t rxmode, mchash[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 472 473 if (usbnet_isdying(un)) 474 return; 475 476 rxmode = mos_reg_read_1(un, MOS_CTL); 477 rxmode &= ~(MOS_CTL_ALLMULTI | MOS_CTL_RX_PROMISC); 478 479 ETHER_LOCK(ec); 480 if (usbnet_ispromisc(un)) { 481 ec->ec_flags |= ETHER_F_ALLMULTI; 482 ETHER_UNLOCK(ec); 483 /* run promisc. mode */ 484 rxmode |= MOS_CTL_ALLMULTI; /* ??? */ 485 rxmode |= MOS_CTL_RX_PROMISC; 486 goto update; 487 } 488 ec->ec_flags &= ~ETHER_F_ALLMULTI; 489 ETHER_FIRST_MULTI(step, ec, enm); 490 while (enm != NULL) { 491 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { 492 ec->ec_flags |= ETHER_F_ALLMULTI; 493 ETHER_UNLOCK(ec); 494 memset(mchash, 0, sizeof(mchash)); /* correct ??? */ 495 /* accept all multicast frame */ 496 rxmode |= MOS_CTL_ALLMULTI; 497 goto update; 498 } 499 h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN); 500 /* 3(31:29) and 3(28:26) sampling to have uint8_t[8] */ 501 mchash[h >> 29] |= 1 << ((h >> 26) % 8); 502 ETHER_NEXT_MULTI(step, enm); 503 } 504 ETHER_UNLOCK(ec); 505 /* MOS receive filter is always on */ 506 update: 507 /* 508 * The datasheet claims broadcast frames were always accepted 509 * regardless of filter settings. But the hardware seems to 510 * filter broadcast frames, so pass them explicitly. 511 */ 512 mchash[7] |= 0x80; 513 mos_write_mcast(un, mchash); 514 mos_reg_write_1(un, MOS_CTL, rxmode); 515 } 516 517 static void 518 mos_reset(struct usbnet *un) 519 { 520 u_int8_t ctl; 521 522 if (usbnet_isdying(un)) 523 return; 524 525 ctl = mos_reg_read_1(un, MOS_CTL); 526 ctl &= ~(MOS_CTL_RX_PROMISC | MOS_CTL_ALLMULTI | MOS_CTL_TX_ENB | 527 MOS_CTL_RX_ENB); 528 /* Disable RX, TX, promiscuous and allmulticast mode */ 529 mos_reg_write_1(un, MOS_CTL, ctl); 530 531 /* Reset frame drop counter register to zero */ 532 mos_reg_write_1(un, MOS_FRAME_DROP_CNT, 0); 533 534 /* Wait a little while for the chip to get its brains in order. */ 535 DELAY(1000); 536 } 537 538 void 539 mos_chip_init(struct usbnet *un) 540 { 541 int i; 542 543 /* 544 * Rev.C devices have a pause threshold register which needs to be set 545 * at startup. 546 */ 547 if (mos_reg_read_1(un, MOS_PAUSE_TRHD) != -1) { 548 for (i = 0; i < MOS_PAUSE_REWRITES; i++) 549 mos_reg_write_1(un, MOS_PAUSE_TRHD, 0); 550 } 551 } 552 553 /* 554 * Probe for a MCS7x30 chip. 555 */ 556 static int 557 mos_match(device_t parent, cfdata_t match, void *aux) 558 { 559 struct usb_attach_arg *uaa = aux; 560 561 return (mos_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ? 562 UMATCH_VENDOR_PRODUCT : UMATCH_NONE); 563 } 564 565 /* 566 * Attach the interface. 567 */ 568 static void 569 mos_attach(device_t parent, device_t self, void *aux) 570 { 571 USBNET_MII_DECL_DEFAULT(unm); 572 struct usbnet * un = device_private(self); 573 struct usb_attach_arg *uaa = aux; 574 struct usbd_device *dev = uaa->uaa_device; 575 usbd_status err; 576 usb_interface_descriptor_t *id; 577 usb_endpoint_descriptor_t *ed; 578 char *devinfop; 579 int i; 580 581 aprint_naive("\n"); 582 aprint_normal("\n"); 583 devinfop = usbd_devinfo_alloc(dev, 0); 584 aprint_normal_dev(self, "%s\n", devinfop); 585 usbd_devinfo_free(devinfop); 586 587 un->un_dev = self; 588 un->un_udev = dev; 589 un->un_sc = un; 590 un->un_ops = &mos_ops; 591 un->un_rx_xfer_flags = USBD_SHORT_XFER_OK; 592 un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER; 593 un->un_rx_list_cnt = MOS_RX_LIST_CNT; 594 un->un_tx_list_cnt = MOS_TX_LIST_CNT; 595 un->un_rx_bufsz = un->un_tx_bufsz = MOS_BUFSZ; 596 597 err = usbd_set_config_no(dev, MOS_CONFIG_NO, 1); 598 if (err) { 599 aprint_error_dev(self, "failed to set configuration" 600 ", err=%s\n", usbd_errstr(err)); 601 return; 602 } 603 604 err = usbd_device2interface_handle(dev, MOS_IFACE_IDX, &un->un_iface); 605 if (err) { 606 aprint_error_dev(self, "failed getting interface handle" 607 ", err=%s\n", usbd_errstr(err)); 608 return; 609 } 610 611 un->un_flags = mos_lookup(uaa->uaa_vendor, uaa->uaa_product)->mos_flags; 612 613 id = usbd_get_interface_descriptor(un->un_iface); 614 615 /* Find endpoints. */ 616 for (i = 0; i < id->bNumEndpoints; i++) { 617 ed = usbd_interface2endpoint_descriptor(un->un_iface, i); 618 if (!ed) { 619 aprint_error_dev(self, "couldn't get ep %d\n", i); 620 return; 621 } 622 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 623 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 624 un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress; 625 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 626 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 627 un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress; 628 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 629 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 630 un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress; 631 } 632 } 633 634 if (un->un_flags & MCS7730) 635 aprint_normal_dev(self, "MCS7730\n"); 636 else if (un->un_flags & MCS7830) 637 aprint_normal_dev(self, "MCS7830\n"); 638 else if (un->un_flags & MCS7832) 639 aprint_normal_dev(self, "MCS7832\n"); 640 641 /* Set these up now for register access. */ 642 usbnet_attach(un); 643 644 mos_chip_init(un); 645 646 /* 647 * Read MAC address, inform the world. 648 */ 649 err = mos_readmac(un); 650 if (err) { 651 aprint_error_dev(self, "couldn't read MAC address\n"); 652 return; 653 } 654 655 struct ethercom *ec = usbnet_ec(un); 656 ec->ec_capabilities = ETHERCAP_VLAN_MTU; 657 658 usbnet_attach_ifp(un, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 659 0, &unm); 660 } 661 662 /* 663 * A frame has been uploaded: pass the resulting mbuf chain up to 664 * the higher level protocols. 665 */ 666 void 667 mos_uno_rx_loop(struct usbnet * un, struct usbnet_chain *c, uint32_t total_len) 668 { 669 struct ifnet *ifp = usbnet_ifp(un); 670 uint8_t *buf = c->unc_buf; 671 u_int8_t rxstat; 672 u_int16_t pktlen = 0; 673 674 DPRINTFN(5,("%s: %s: enter len %u\n", 675 device_xname(un->un_dev), __func__, total_len)); 676 677 if (total_len <= 1) 678 return; 679 680 /* evaluate status byte at the end */ 681 pktlen = total_len - 1; 682 if (pktlen > un->un_rx_bufsz) { 683 if_statinc(ifp, if_ierrors); 684 return; 685 } 686 rxstat = buf[pktlen] & MOS_RXSTS_MASK; 687 688 if (rxstat != MOS_RXSTS_VALID) { 689 DPRINTF(("%s: erroneous frame received: ", 690 device_xname(un->un_dev))); 691 if (rxstat & MOS_RXSTS_SHORT_FRAME) 692 DPRINTF(("frame size less than 64 bytes\n")); 693 if (rxstat & MOS_RXSTS_LARGE_FRAME) 694 DPRINTF(("frame size larger than 1532 bytes\n")); 695 if (rxstat & MOS_RXSTS_CRC_ERROR) 696 DPRINTF(("CRC error\n")); 697 if (rxstat & MOS_RXSTS_ALIGN_ERROR) 698 DPRINTF(("alignment error\n")); 699 if_statinc(ifp, if_ierrors); 700 return; 701 } 702 703 if (pktlen < sizeof(struct ether_header) ) { 704 if_statinc(ifp, if_ierrors); 705 return; 706 } 707 708 usbnet_enqueue(un, c->unc_buf, pktlen, 0, 0, 0); 709 } 710 711 static unsigned 712 mos_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) 713 { 714 int length; 715 716 if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz) 717 return 0; 718 719 m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf); 720 length = m->m_pkthdr.len; 721 722 DPRINTFN(5,("%s: %s: len %u\n", 723 device_xname(un->un_dev), __func__, length)); 724 725 return length; 726 } 727 728 static int 729 mos_uno_init(struct ifnet *ifp) 730 { 731 struct usbnet * const un = ifp->if_softc; 732 u_int8_t rxmode; 733 unsigned char ipgs[2]; 734 735 /* Reset the ethernet interface. */ 736 mos_reset(un); 737 738 /* Write MAC address. */ 739 mos_writemac(un); 740 741 /* Read and set transmitter IPG values */ 742 ipgs[0] = mos_reg_read_1(un, MOS_IPG0); 743 ipgs[1] = mos_reg_read_1(un, MOS_IPG1); 744 mos_reg_write_1(un, MOS_IPG0, ipgs[0]); 745 mos_reg_write_1(un, MOS_IPG1, ipgs[1]); 746 747 /* Enable receiver and transmitter, bridge controls speed/duplex mode */ 748 rxmode = mos_reg_read_1(un, MOS_CTL); 749 rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB; 750 rxmode &= ~(MOS_CTL_SLEEP); 751 mos_reg_write_1(un, MOS_CTL, rxmode); 752 753 return 0; 754 } 755 756 void 757 mos_uno_stop(struct ifnet *ifp, int disable) 758 { 759 struct usbnet * const un = ifp->if_softc; 760 761 mos_reset(un); 762 } 763