1 /* $OpenBSD: if_mos.c,v 1.7 2009/10/13 19:33:17 pirofti Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Johann Christian Rode <jcrode@gmx.net> 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) 2005, 2006, 2007 Jonathan Gray <jsg@openbsd.org> 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) 1997, 1998, 1999, 2000-2003 37 * Bill Paul <wpaul@windriver.com>. All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. All advertising materials mentioning features or use of this software 48 * must display the following acknowledgement: 49 * This product includes software developed by Bill Paul. 50 * 4. Neither the name of the author nor the names of any co-contributors 51 * may be used to endorse or promote products derived from this software 52 * without specific prior written permission. 53 * 54 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 64 * THE POSSIBILITY OF SUCH DAMAGE. 65 */ 66 67 #include <sys/cdefs.h> 68 69 /* 70 * Moschip MCS7730/MCS7830 USB to Ethernet controller 71 * The datasheet is available at the following URL: 72 * http://www.moschip.com/data/products/MCS7830/Data%20Sheet_7830.pdf 73 */ 74 75 #include "bpfilter.h" 76 77 #include <sys/param.h> 78 #include <sys/systm.h> 79 #include <sys/sockio.h> 80 #include <sys/rwlock.h> 81 #include <sys/mbuf.h> 82 #include <sys/kernel.h> 83 #include <sys/proc.h> 84 #include <sys/socket.h> 85 86 #include <sys/device.h> 87 88 #include <machine/bus.h> 89 90 #include <net/if.h> 91 #include <net/if_dl.h> 92 #include <net/if_media.h> 93 94 #if NBPFILTER > 0 95 #include <net/bpf.h> 96 #endif 97 98 #ifdef INET 99 #include <netinet/in.h> 100 #include <netinet/in_systm.h> 101 #include <netinet/in_var.h> 102 #include <netinet/ip.h> 103 #include <netinet/if_ether.h> 104 #endif 105 106 #include <dev/mii/mii.h> 107 #include <dev/mii/miivar.h> 108 109 #include <dev/usb/usb.h> 110 #include <dev/usb/usbdi.h> 111 #include <dev/usb/usbdi_util.h> 112 #include <dev/usb/usbdivar.h> 113 #include <dev/usb/usbdevs.h> 114 115 #include <dev/usb/if_mosreg.h> 116 117 #ifdef MOS_DEBUG 118 #define DPRINTF(x) do { if (mosdebug) printf x; } while (0) 119 #define DPRINTFN(n,x) do { if (mosdebug >= (n)) printf x; } while (0) 120 int mosdebug = 0; 121 #else 122 #define DPRINTF(x) 123 #define DPRINTFN(n,x) 124 #endif 125 126 /* 127 * Various supported device vendors/products. 128 */ 129 const struct mos_type mos_devs[] = { 130 { { USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7730 }, MCS7730 }, 131 { { USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7830 }, MCS7830 }, 132 { { USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN030 }, MCS7830 }, 133 }; 134 #define mos_lookup(v, p) ((struct mos_type *)usb_lookup(mos_devs, v, p)) 135 136 int mos_match(struct device *, void *, void *); 137 void mos_attach(struct device *, struct device *, void *); 138 int mos_detach(struct device *, int); 139 int mos_activate(struct device *, int); 140 141 struct cfdriver mos_cd = { 142 NULL, "mos", DV_IFNET 143 }; 144 145 const struct cfattach mos_ca = { 146 sizeof(struct mos_softc), 147 mos_match, 148 mos_attach, 149 mos_detach, 150 mos_activate, 151 }; 152 153 int mos_tx_list_init(struct mos_softc *); 154 int mos_rx_list_init(struct mos_softc *); 155 struct mbuf *mos_newbuf(void); 156 int mos_encap(struct mos_softc *, struct mbuf *, int); 157 void mos_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 158 void mos_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 159 void mos_tick(void *); 160 void mos_tick_task(void *); 161 void mos_start(struct ifnet *); 162 int mos_ioctl(struct ifnet *, u_long, caddr_t); 163 void mos_init(void *); 164 void mos_chip_init(struct mos_softc *); 165 void mos_stop(struct mos_softc *); 166 void mos_watchdog(struct ifnet *); 167 int mos_miibus_readreg(struct device *, int, int); 168 void mos_miibus_writereg(struct device *, int, int, int); 169 void mos_miibus_statchg(struct device *); 170 int mos_ifmedia_upd(struct ifnet *); 171 void mos_ifmedia_sts(struct ifnet *, struct ifmediareq *); 172 void mos_reset(struct mos_softc *sc); 173 174 int mos_reg_read_1(struct mos_softc *, int); 175 int mos_reg_read_2(struct mos_softc *, int); 176 int mos_reg_write_1(struct mos_softc *, int, int); 177 int mos_reg_write_2(struct mos_softc *, int, int); 178 int mos_readmac(struct mos_softc *, u_char *); 179 int mos_writemac(struct mos_softc *, u_char *); 180 int mos_write_mcast(struct mos_softc *, u_char *); 181 182 void mos_setmulti(struct mos_softc *); 183 void mos_lock_mii(struct mos_softc *); 184 void mos_unlock_mii(struct mos_softc *); 185 186 /* 187 * Get exclusive access to the MII registers 188 */ 189 void 190 mos_lock_mii(struct mos_softc *sc) 191 { 192 sc->mos_refcnt++; 193 rw_enter_write(&sc->mos_mii_lock); 194 } 195 196 void 197 mos_unlock_mii(struct mos_softc *sc) 198 { 199 rw_exit_write(&sc->mos_mii_lock); 200 if (--sc->mos_refcnt < 0) 201 usb_detach_wakeup(&sc->mos_dev); 202 } 203 204 int 205 mos_reg_read_1(struct mos_softc *sc, int reg) 206 { 207 usb_device_request_t req; 208 usbd_status err; 209 uByte val = 0; 210 211 if (sc->mos_dying) 212 return (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, 1); 219 220 err = usbd_do_request(sc->mos_udev, &req, &val); 221 222 if (err) { 223 DPRINTF(("mos_reg_read_1 error, reg: %d\n", reg)); 224 return (-1); 225 } 226 227 return (val); 228 } 229 230 int 231 mos_reg_read_2(struct mos_softc *sc, int reg) 232 { 233 usb_device_request_t req; 234 usbd_status err; 235 uWord val; 236 237 USETW(val,0); 238 239 if (sc->mos_dying) 240 return(0); 241 242 req.bmRequestType = UT_READ_VENDOR_DEVICE; 243 req.bRequest = MOS_UR_READREG; 244 USETW(req.wValue, 0); 245 USETW(req.wIndex, reg); 246 USETW(req.wLength, 2); 247 248 err = usbd_do_request(sc->mos_udev, &req, &val); 249 250 if (err) { 251 DPRINTF(("mos_reg_read_2 error, reg: %d\n", reg)); 252 return (-1); 253 } 254 255 return(UGETW(val)); 256 } 257 258 int 259 mos_reg_write_1(struct mos_softc *sc, int reg, int aval) 260 { 261 usb_device_request_t req; 262 usbd_status err; 263 uByte val; 264 265 val = aval; 266 267 if (sc->mos_dying) 268 return(0); 269 270 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 271 req.bRequest = MOS_UR_WRITEREG; 272 USETW(req.wValue, 0); 273 USETW(req.wIndex, reg); 274 USETW(req.wLength, 1); 275 276 err = usbd_do_request(sc->mos_udev, &req, &val); 277 278 if (err) { 279 DPRINTF(("mos_reg_write_1 error, reg: %d\n", reg)); 280 return (-1); 281 } 282 283 return(0); 284 } 285 286 int 287 mos_reg_write_2(struct mos_softc *sc, int reg, int aval) 288 { 289 usb_device_request_t req; 290 usbd_status err; 291 uWord val; 292 293 USETW(val, aval); 294 295 if (sc->mos_dying) 296 return (0); 297 298 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 299 req.bRequest = MOS_UR_WRITEREG; 300 USETW(req.wValue, 0); 301 USETW(req.wIndex, reg); 302 USETW(req.wLength, 2); 303 304 err = usbd_do_request(sc->mos_udev, &req, &val); 305 306 if (err) { 307 DPRINTF(("mos_reg_write_2 error, reg: %d\n", reg)); 308 return (-1); 309 } 310 311 return (0); 312 } 313 314 int 315 mos_readmac(struct mos_softc *sc, u_char *mac) 316 { 317 usb_device_request_t req; 318 usbd_status err; 319 320 if (sc->mos_dying) 321 return(0); 322 323 req.bmRequestType = UT_READ_VENDOR_DEVICE; 324 req.bRequest = MOS_UR_READREG; 325 USETW(req.wValue, 0); 326 USETW(req.wIndex, MOS_MAC); 327 USETW(req.wLength, ETHER_ADDR_LEN); 328 329 err = usbd_do_request(sc->mos_udev, &req, mac); 330 331 if (err) { 332 DPRINTF(("mos_readmac error")); 333 return (-1); 334 } 335 336 return (0); 337 } 338 339 int 340 mos_writemac(struct mos_softc *sc, u_char *mac) 341 { 342 usb_device_request_t req; 343 usbd_status err; 344 345 if (sc->mos_dying) 346 return(0); 347 348 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 349 req.bRequest = MOS_UR_WRITEREG; 350 USETW(req.wValue, 0); 351 USETW(req.wIndex, MOS_MAC); 352 USETW(req.wLength, ETHER_ADDR_LEN); 353 354 err = usbd_do_request(sc->mos_udev, &req, mac); 355 356 if (err) { 357 DPRINTF(("mos_writemac error")); 358 return (-1); 359 } 360 361 return (0); 362 } 363 364 int 365 mos_write_mcast(struct mos_softc *sc, u_char *hashtbl) 366 { 367 usb_device_request_t req; 368 usbd_status err; 369 370 if (sc->mos_dying) 371 return(0); 372 373 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 374 req.bRequest = MOS_UR_WRITEREG; 375 USETW(req.wValue, 0); 376 USETW(req.wIndex, MOS_MCAST_TABLE); 377 USETW(req.wLength, 8); 378 379 err = usbd_do_request(sc->mos_udev, &req, hashtbl); 380 381 if (err) { 382 DPRINTF(("mos_reg_mcast error\n")); 383 return(-1); 384 } 385 386 return(0); 387 } 388 389 int 390 mos_miibus_readreg(struct device *dev, int phy, int reg) 391 { 392 struct mos_softc *sc = (void *)dev; 393 uWord val; 394 int i,res; 395 396 if (sc->mos_dying) { 397 DPRINTF(("mos: dying\n")); 398 return (0); 399 } 400 401 USETW(val, 0); 402 403 mos_lock_mii(sc); 404 405 mos_reg_write_2(sc, MOS_PHY_DATA, 0); 406 mos_reg_write_1(sc, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) | 407 MOS_PHYCTL_READ); 408 mos_reg_write_1(sc, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) | 409 MOS_PHYSTS_PENDING); 410 411 for (i = 0; i < MOS_TIMEOUT; i++) { 412 if (mos_reg_read_1(sc, MOS_PHY_STS) & MOS_PHYSTS_READY) 413 break; 414 } 415 if (i == MOS_TIMEOUT) { 416 printf("%s: MII read timeout\n", sc->mos_dev.dv_xname); 417 } 418 419 res = mos_reg_read_2(sc, MOS_PHY_DATA); 420 421 mos_unlock_mii(sc); 422 423 return (res); 424 } 425 426 void 427 mos_miibus_writereg(struct device *dev, int phy, int reg, int val) 428 { 429 struct mos_softc *sc = (void *)dev; 430 int i; 431 432 if (sc->mos_dying) 433 return; 434 435 mos_lock_mii(sc); 436 437 mos_reg_write_2(sc, MOS_PHY_DATA, val); 438 mos_reg_write_1(sc, MOS_PHY_CTL, (phy & MOS_PHYCTL_PHYADDR) | 439 MOS_PHYCTL_WRITE); 440 mos_reg_write_1(sc, MOS_PHY_STS, (reg & MOS_PHYSTS_PHYREG) | 441 MOS_PHYSTS_PENDING); 442 443 for (i = 0; i < MOS_TIMEOUT; i++) { 444 if (mos_reg_read_1(sc, MOS_PHY_STS) & MOS_PHYSTS_READY) 445 break; 446 } 447 if (i == MOS_TIMEOUT) { 448 printf("%s: MII write timeout\n", sc->mos_dev.dv_xname); 449 } 450 451 mos_unlock_mii(sc); 452 453 return; 454 } 455 456 void 457 mos_miibus_statchg(struct device *dev) 458 { 459 struct mos_softc *sc = (void *)dev; 460 struct mii_data *mii = GET_MII(sc); 461 int val, err; 462 463 mos_lock_mii(sc); 464 465 /* disable RX, TX prior to changing FDX, SPEEDSEL */ 466 val = mos_reg_read_1(sc, MOS_CTL); 467 val &= ~(MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); 468 mos_reg_write_1(sc, MOS_CTL, val); 469 470 /* reset register which counts dropped frames */ 471 mos_reg_write_1(sc, MOS_FRAME_DROP_CNT, 0); 472 473 if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) 474 val |= MOS_CTL_FDX_ENB; 475 else 476 val &= ~(MOS_CTL_FDX_ENB); 477 478 switch (IFM_SUBTYPE(mii->mii_media_active)) { 479 case IFM_100_TX: 480 val |= MOS_CTL_SPEEDSEL; 481 break; 482 case IFM_10_T: 483 val &= ~(MOS_CTL_SPEEDSEL); 484 break; 485 } 486 487 /* re-enable TX, RX */ 488 val |= (MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); 489 err = mos_reg_write_1(sc, MOS_CTL, val); 490 mos_unlock_mii(sc); 491 492 if (err) { 493 printf("%s: media change failed\n", sc->mos_dev.dv_xname); 494 return; 495 } 496 } 497 498 /* 499 * Set media options. 500 */ 501 int 502 mos_ifmedia_upd(struct ifnet *ifp) 503 { 504 struct mos_softc *sc = ifp->if_softc; 505 struct mii_data *mii = GET_MII(sc); 506 507 sc->mos_link = 0; 508 if (mii->mii_instance) { 509 struct mii_softc *miisc; 510 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 511 mii_phy_reset(miisc); 512 } 513 mii_mediachg(mii); 514 515 return (0); 516 } 517 518 /* 519 * Report current media status. 520 */ 521 void 522 mos_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 523 { 524 struct mos_softc *sc = ifp->if_softc; 525 struct mii_data *mii = GET_MII(sc); 526 527 mii_pollstat(mii); 528 ifmr->ifm_active = mii->mii_media_active; 529 ifmr->ifm_status = mii->mii_media_status; 530 } 531 532 void 533 mos_setmulti(struct mos_softc *sc) 534 { 535 struct ifnet *ifp; 536 struct ether_multi *enm; 537 struct ether_multistep step; 538 u_int32_t h = 0; 539 u_int8_t rxmode; 540 u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 541 542 if (sc->mos_dying) 543 return; 544 545 ifp = GET_IFP(sc); 546 547 rxmode = mos_reg_read_1(sc, MOS_CTL); 548 549 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 550 allmulti: 551 rxmode |= MOS_CTL_ALLMULTI; 552 mos_reg_write_1(sc, MOS_CTL, rxmode); 553 return; 554 } else 555 rxmode &= ~MOS_CTL_ALLMULTI; 556 557 /* now program new ones */ 558 ETHER_FIRST_MULTI(step, &sc->arpcom, enm); 559 while (enm != NULL) { 560 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 561 ETHER_ADDR_LEN) != 0) 562 goto allmulti; 563 564 h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26; 565 hashtbl[h / 8] |= 1 << (h % 8); 566 ETHER_NEXT_MULTI(step, enm); 567 } 568 569 ifp->if_flags &= ~IFF_ALLMULTI; 570 mos_write_mcast(sc, (void *)&hashtbl); 571 mos_reg_write_1(sc, MOS_CTL, rxmode); 572 return; 573 } 574 575 void 576 mos_reset(struct mos_softc *sc) 577 { 578 u_int8_t ctl; 579 if (sc->mos_dying) 580 return; 581 582 ctl = mos_reg_read_1(sc, MOS_CTL); 583 ctl &= ~(MOS_CTL_RX_PROMISC | MOS_CTL_ALLMULTI | MOS_CTL_TX_ENB | 584 MOS_CTL_RX_ENB); 585 /* Disable RX, TX, promiscuous and allmulticast mode */ 586 mos_reg_write_1(sc, MOS_CTL, ctl); 587 588 /* Reset frame drop counter register to zero */ 589 mos_reg_write_1(sc, MOS_FRAME_DROP_CNT, 0); 590 591 /* Wait a little while for the chip to get its brains in order. */ 592 DELAY(1000); 593 return; 594 } 595 596 void 597 mos_chip_init(struct mos_softc *sc) 598 { 599 int i; 600 601 /* 602 * Rev.C devices have a pause threshold register which needs to be set 603 * at startup. 604 */ 605 if (mos_reg_read_1(sc, MOS_PAUSE_TRHD) != -1) { 606 for (i=0;i<MOS_PAUSE_REWRITES;i++) 607 mos_reg_write_1(sc, MOS_PAUSE_TRHD, 0); 608 } 609 610 sc->mos_phyaddrs[0] = 1; sc->mos_phyaddrs[1] = 0xFF; 611 } 612 613 /* 614 * Probe for a MCS7x30 chip. 615 */ 616 int 617 mos_match(struct device *parent, void *match, void *aux) 618 { 619 struct usb_attach_arg *uaa = aux; 620 621 if (!uaa->iface) 622 return(UMATCH_NONE); 623 624 return (mos_lookup(uaa->vendor, uaa->product) != NULL ? 625 UMATCH_VENDOR_PRODUCT : UMATCH_NONE); 626 } 627 628 /* 629 * Attach the interface. Allocate softc structures, do ifmedia 630 * setup and ethernet/BPF attach. 631 */ 632 void 633 mos_attach(struct device *parent, struct device *self, void *aux) 634 { 635 struct mos_softc *sc = (struct mos_softc *)self; 636 struct usb_attach_arg *uaa = aux; 637 struct ifnet *ifp; 638 usbd_device_handle dev = uaa->device; 639 usbd_status err; 640 usb_interface_descriptor_t *id; 641 usb_endpoint_descriptor_t *ed; 642 struct mii_data *mii; 643 u_char eaddr[ETHER_ADDR_LEN]; 644 int i,s; 645 646 sc->mos_unit = self->dv_unit; 647 648 err = usbd_set_config_no(dev, MOS_CONFIG_NO, 1); 649 if (err) { 650 printf("%s: getting interface handle failed\n", 651 sc->mos_dev.dv_xname); 652 return; 653 } 654 655 usb_init_task(&sc->mos_tick_task, mos_tick_task, sc); 656 rw_init(&sc->mos_mii_lock, "mosmii"); 657 usb_init_task(&sc->mos_stop_task, (void (*)(void *))mos_stop, sc); 658 659 err = usbd_device2interface_handle(dev, MOS_IFACE_IDX, &sc->mos_iface); 660 if (err) { 661 printf("%s: getting interface handle failed\n", 662 sc->mos_dev.dv_xname); 663 return; 664 } 665 666 sc->mos_udev = dev; 667 sc->mos_flags = mos_lookup(uaa->vendor, uaa->product)->mos_flags; 668 669 id = usbd_get_interface_descriptor(sc->mos_iface); 670 671 sc->mos_bufsz = MOS_BUFSZ; 672 673 /* Find endpoints. */ 674 for (i = 0; i < id->bNumEndpoints; i++) { 675 ed = usbd_interface2endpoint_descriptor(sc->mos_iface, i); 676 if (!ed) { 677 printf("%s: couldn't get ep %d\n", 678 sc->mos_dev.dv_xname, i); 679 return; 680 } 681 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 682 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 683 sc->mos_ed[MOS_ENDPT_RX] = ed->bEndpointAddress; 684 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 685 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 686 sc->mos_ed[MOS_ENDPT_TX] = ed->bEndpointAddress; 687 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 688 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 689 sc->mos_ed[MOS_ENDPT_INTR] = ed->bEndpointAddress; 690 } 691 } 692 693 s = splnet(); 694 695 printf("%s:", sc->mos_dev.dv_xname); 696 697 if (sc->mos_flags & MCS7730) { 698 printf(" MCS7730"); 699 } else if (sc->mos_flags & MCS7830) { 700 printf(" MCS7830"); 701 } 702 703 mos_chip_init(sc); 704 705 /* 706 * Read MAC address, inform the world. 707 */ 708 err = mos_readmac(sc, (void*)&eaddr); 709 if (err) { 710 printf("%s: couldn't get MAC address\n", 711 sc->mos_dev.dv_xname); 712 return; 713 } 714 bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 715 printf(", address %s\n", ether_sprintf(eaddr)); 716 717 /* Initialize interface info.*/ 718 ifp = GET_IFP(sc); 719 ifp->if_softc = sc; 720 ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST; 721 ifp->if_ioctl = mos_ioctl; 722 ifp->if_start = mos_start; 723 ifp->if_watchdog = mos_watchdog; 724 strlcpy(ifp->if_xname, sc->mos_dev.dv_xname, IFNAMSIZ); 725 726 IFQ_SET_READY(&ifp->if_snd); 727 728 ifp->if_capabilities = IFCAP_VLAN_MTU; 729 730 /* Initialize MII/media info. */ 731 mii = GET_MII(sc); 732 mii->mii_ifp = ifp; 733 mii->mii_readreg = mos_miibus_readreg; 734 mii->mii_writereg = mos_miibus_writereg; 735 mii->mii_statchg = mos_miibus_statchg; 736 mii->mii_flags = MIIF_AUTOTSLEEP; 737 738 ifmedia_init(&mii->mii_media, 0, mos_ifmedia_upd, mos_ifmedia_sts); 739 mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); 740 741 if (LIST_FIRST(&mii->mii_phys) == NULL) { 742 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); 743 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); 744 } else 745 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 746 747 /* Attach the interface. */ 748 if_attach(ifp); 749 ether_ifattach(ifp); 750 751 timeout_set(&sc->mos_stat_ch, mos_tick, sc); 752 753 sc->mos_attached = 1; 754 splx(s); 755 756 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->mos_udev, 757 &sc->mos_dev); 758 } 759 760 int 761 mos_detach(struct device *self, int flags) 762 { 763 struct mos_softc *sc = (struct mos_softc *)self; 764 struct ifnet *ifp = GET_IFP(sc); 765 int s; 766 767 DPRINTFN(2,("%s: %s: enter\n", sc->mos_dev.dv_xname, __func__)); 768 769 if (!sc->mos_attached) 770 return (0); 771 772 timeout_del(&sc->mos_stat_ch); 773 774 sc->mos_dying = 1; 775 776 if (sc->mos_ep[MOS_ENDPT_TX] != NULL) 777 usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_TX]); 778 if (sc->mos_ep[MOS_ENDPT_RX] != NULL) 779 usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_RX]); 780 if (sc->mos_ep[MOS_ENDPT_INTR] != NULL) 781 usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_INTR]); 782 783 /* 784 * Remove any pending tasks. They cannot be executing because they run 785 * in the same thread as detach. 786 */ 787 usb_rem_task(sc->mos_udev, &sc->mos_tick_task); 788 usb_rem_task(sc->mos_udev, &sc->mos_stop_task); 789 s = splusb(); 790 791 if (--sc->mos_refcnt >= 0) { 792 /* Wait for processes to go away */ 793 usb_detach_wait(&sc->mos_dev); 794 } 795 796 if (ifp->if_flags & IFF_RUNNING) 797 mos_stop(sc); 798 799 mii_detach(&sc->mos_mii, MII_PHY_ANY, MII_OFFSET_ANY); 800 ifmedia_delete_instance(&sc->mos_mii.mii_media, IFM_INST_ANY); 801 ether_ifdetach(ifp); 802 if_detach(ifp); 803 804 #ifdef DIAGNOSTIC 805 if (sc->mos_ep[MOS_ENDPT_TX] != NULL || 806 sc->mos_ep[MOS_ENDPT_RX] != NULL || 807 sc->mos_ep[MOS_ENDPT_INTR] != NULL) 808 printf("%s: detach has active endpoints\n", 809 sc->mos_dev.dv_xname); 810 #endif 811 812 sc->mos_attached = 0; 813 814 if (--sc->mos_refcnt >= 0) { 815 /* Wait for processes to go away. */ 816 usb_detach_wait(&sc->mos_dev); 817 } 818 splx(s); 819 820 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->mos_udev, 821 &sc->mos_dev); 822 823 return (0); 824 } 825 826 827 int 828 mos_activate(struct device *self, int act) 829 { 830 struct mos_softc *sc = (struct mos_softc *)self; 831 832 DPRINTFN(2,("%s: %s: enter\n", sc->mos_dev.dv_xname, __func__)); 833 834 switch (act) { 835 case DVACT_ACTIVATE: 836 break; 837 838 case DVACT_DEACTIVATE: 839 sc->mos_dying = 1; 840 break; 841 } 842 return (0); 843 } 844 845 struct mbuf * 846 mos_newbuf(void) 847 { 848 struct mbuf *m; 849 850 MGETHDR(m, M_DONTWAIT, MT_DATA); 851 if (m == NULL) 852 return (NULL); 853 854 MCLGET(m, M_DONTWAIT); 855 if (!(m->m_flags & M_EXT)) { 856 m_freem(m); 857 return (NULL); 858 } 859 860 m->m_len = m->m_pkthdr.len = MCLBYTES; 861 m_adj(m, ETHER_ALIGN); 862 863 return (m); 864 } 865 866 int 867 mos_rx_list_init(struct mos_softc *sc) 868 { 869 struct mos_cdata *cd; 870 struct mos_chain *c; 871 int i; 872 873 DPRINTF(("%s: %s: enter\n", sc->mos_dev.dv_xname, __func__)); 874 875 cd = &sc->mos_cdata; 876 for (i = 0; i < MOS_RX_LIST_CNT; i++) { 877 c = &cd->mos_rx_chain[i]; 878 c->mos_sc = sc; 879 c->mos_idx = i; 880 c->mos_mbuf = NULL; 881 if (c->mos_xfer == NULL) { 882 c->mos_xfer = usbd_alloc_xfer(sc->mos_udev); 883 if (c->mos_xfer == NULL) 884 return (ENOBUFS); 885 c->mos_buf = usbd_alloc_buffer(c->mos_xfer, 886 sc->mos_bufsz); 887 if (c->mos_buf == NULL) { 888 usbd_free_xfer(c->mos_xfer); 889 return (ENOBUFS); 890 } 891 } 892 } 893 894 return (0); 895 } 896 897 int 898 mos_tx_list_init(struct mos_softc *sc) 899 { 900 struct mos_cdata *cd; 901 struct mos_chain *c; 902 int i; 903 904 DPRINTF(("%s: %s: enter\n", sc->mos_dev.dv_xname, __func__)); 905 906 cd = &sc->mos_cdata; 907 for (i = 0; i < MOS_TX_LIST_CNT; i++) { 908 c = &cd->mos_tx_chain[i]; 909 c->mos_sc = sc; 910 c->mos_idx = i; 911 c->mos_mbuf = NULL; 912 if (c->mos_xfer == NULL) { 913 c->mos_xfer = usbd_alloc_xfer(sc->mos_udev); 914 if (c->mos_xfer == NULL) 915 return (ENOBUFS); 916 c->mos_buf = usbd_alloc_buffer(c->mos_xfer, 917 sc->mos_bufsz); 918 if (c->mos_buf == NULL) { 919 usbd_free_xfer(c->mos_xfer); 920 return (ENOBUFS); 921 } 922 } 923 } 924 925 return (0); 926 } 927 928 /* 929 * A frame has been uploaded: pass the resulting mbuf chain up to 930 * the higher level protocols. 931 */ 932 void 933 mos_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 934 { 935 struct mos_chain *c = (struct mos_chain *)priv; 936 struct mos_softc *sc = c->mos_sc; 937 struct ifnet *ifp = GET_IFP(sc); 938 u_char *buf = c->mos_buf; 939 u_int8_t rxstat; 940 u_int32_t total_len; 941 u_int16_t pktlen = 0; 942 struct mbuf *m; 943 int s; 944 945 DPRINTFN(10,("%s: %s: enter\n", sc->mos_dev.dv_xname,__func__)); 946 947 if (sc->mos_dying) 948 return; 949 950 if (!(ifp->if_flags & IFF_RUNNING)) 951 return; 952 953 if (status != USBD_NORMAL_COMPLETION) { 954 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 955 return; 956 if (usbd_ratecheck(&sc->mos_rx_notice)) { 957 printf("%s: usb errors on rx: %s\n", 958 sc->mos_dev.dv_xname, usbd_errstr(status)); 959 } 960 if (status == USBD_STALLED) 961 usbd_clear_endpoint_stall_async(sc->mos_ep[MOS_ENDPT_RX]); 962 goto done; 963 } 964 965 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 966 967 if (total_len <= 1) 968 goto done; 969 970 /* evaluate status byte at the end */ 971 pktlen = total_len - 1; 972 rxstat = buf[pktlen] & MOS_RXSTS_MASK; 973 974 if (rxstat != MOS_RXSTS_VALID) { 975 DPRINTF(("%s: erroneous frame received: ", 976 sc->mos_dev.dv_xname)); 977 if (rxstat & MOS_RXSTS_SHORT_FRAME) 978 DPRINTF(("frame size less than 64 bytes\n")); 979 if (rxstat & MOS_RXSTS_LARGE_FRAME) 980 DPRINTF(("frame size larger than 1532 bytes\n")); 981 if (rxstat & MOS_RXSTS_CRC_ERROR) 982 DPRINTF(("CRC error\n")); 983 if (rxstat & MOS_RXSTS_ALIGN_ERROR) 984 DPRINTF(("alignment error\n")); 985 ifp->if_ierrors++; 986 goto done; 987 } 988 989 if ( pktlen < sizeof(struct ether_header) ) { 990 ifp->if_ierrors++; 991 goto done; 992 } 993 994 m = mos_newbuf(); 995 if (m == NULL) { 996 ifp->if_ierrors++; 997 goto done; 998 } 999 1000 ifp->if_ipackets++; 1001 m->m_pkthdr.rcvif = ifp; 1002 m->m_pkthdr.len = m->m_len = pktlen; 1003 1004 memcpy(mtod(m, char *), buf, pktlen); 1005 1006 /* push the packet up */ 1007 s = splnet(); 1008 #if NBPFILTER > 0 1009 if (ifp->if_bpf) 1010 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 1011 #endif 1012 1013 ether_input_mbuf(ifp, m); 1014 1015 splx(s); 1016 1017 done: 1018 memset(c->mos_buf, 0, sc->mos_bufsz); 1019 1020 /* Setup new transfer. */ 1021 usbd_setup_xfer(xfer, sc->mos_ep[MOS_ENDPT_RX], 1022 c, c->mos_buf, sc->mos_bufsz, 1023 USBD_SHORT_XFER_OK | USBD_NO_COPY, 1024 USBD_NO_TIMEOUT, mos_rxeof); 1025 usbd_transfer(xfer); 1026 1027 DPRINTFN(10,("%s: %s: start rx\n", sc->mos_dev.dv_xname, __func__)); 1028 1029 return; 1030 } 1031 1032 /* 1033 * A frame was downloaded to the chip. It's safe for us to clean up 1034 * the list buffers. 1035 */ 1036 1037 void 1038 mos_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 1039 { 1040 struct mos_softc *sc; 1041 struct mos_chain *c; 1042 struct ifnet *ifp; 1043 int s; 1044 1045 c = priv; 1046 sc = c->mos_sc; 1047 ifp = &sc->arpcom.ac_if; 1048 1049 if (sc->mos_dying) 1050 return; 1051 1052 s = splnet(); 1053 1054 if (status != USBD_NORMAL_COMPLETION) { 1055 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 1056 splx(s); 1057 return; 1058 } 1059 ifp->if_oerrors++; 1060 printf("%s: usb error on tx: %s\n", sc->mos_dev.dv_xname, 1061 usbd_errstr(status)); 1062 if (status == USBD_STALLED) 1063 usbd_clear_endpoint_stall_async(sc->mos_ep[MOS_ENDPT_TX]); 1064 splx(s); 1065 return; 1066 } 1067 1068 ifp->if_timer = 0; 1069 ifp->if_flags &= ~IFF_OACTIVE; 1070 1071 m_freem(c->mos_mbuf); 1072 c->mos_mbuf = NULL; 1073 1074 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 1075 mos_start(ifp); 1076 1077 ifp->if_opackets++; 1078 splx(s); 1079 return; 1080 } 1081 1082 void 1083 mos_tick(void *xsc) 1084 { 1085 struct mos_softc *sc = xsc; 1086 1087 if (sc == NULL) 1088 return; 1089 1090 DPRINTFN(0xff, ("%s: %s: enter\n", sc->mos_dev.dv_xname, 1091 __func__)); 1092 1093 if (sc->mos_dying) 1094 return; 1095 1096 /* Perform periodic stuff in process context */ 1097 usb_add_task(sc->mos_udev, &sc->mos_tick_task); 1098 1099 } 1100 1101 void 1102 mos_tick_task(void *xsc) 1103 { 1104 int s; 1105 struct mos_softc *sc; 1106 struct ifnet *ifp; 1107 struct mii_data *mii; 1108 1109 sc = xsc; 1110 1111 if (sc == NULL) 1112 return; 1113 1114 if (sc->mos_dying) 1115 return; 1116 1117 ifp = GET_IFP(sc); 1118 mii = GET_MII(sc); 1119 if (mii == NULL) 1120 return; 1121 1122 s = splnet(); 1123 1124 mii_tick(mii); 1125 if (!sc->mos_link && mii->mii_media_status & IFM_ACTIVE && 1126 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 1127 DPRINTF(("%s: %s: got link\n", 1128 sc->mos_dev.dv_xname, __func__)); 1129 sc->mos_link++; 1130 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 1131 mos_start(ifp); 1132 } 1133 1134 timeout_add_sec(&sc->mos_stat_ch, 1); 1135 1136 splx(s); 1137 } 1138 1139 int 1140 mos_encap(struct mos_softc *sc, struct mbuf *m, int idx) 1141 { 1142 struct mos_chain *c; 1143 usbd_status err; 1144 int length; 1145 1146 c = &sc->mos_cdata.mos_tx_chain[idx]; 1147 1148 m_copydata(m, 0, m->m_pkthdr.len, c->mos_buf); 1149 length = m->m_pkthdr.len; 1150 1151 c->mos_mbuf = m; 1152 1153 usbd_setup_xfer(c->mos_xfer, sc->mos_ep[MOS_ENDPT_TX], 1154 c, c->mos_buf, length, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 1155 10000, mos_txeof); 1156 1157 /* Transmit */ 1158 err = usbd_transfer(c->mos_xfer); 1159 if (err != USBD_IN_PROGRESS) { 1160 mos_stop(sc); 1161 return(EIO); 1162 } 1163 1164 sc->mos_cdata.mos_tx_cnt++; 1165 1166 return(0); 1167 } 1168 1169 void 1170 mos_start(struct ifnet *ifp) 1171 { 1172 struct mos_softc *sc; 1173 struct mbuf *m_head = NULL; 1174 1175 sc = ifp->if_softc; 1176 1177 if (!sc->mos_link) 1178 return; 1179 1180 if (ifp->if_flags & IFF_OACTIVE) 1181 return; 1182 1183 IFQ_POLL(&ifp->if_snd, m_head); 1184 if (m_head == NULL) 1185 return; 1186 1187 if (mos_encap(sc, m_head, 0)) { 1188 ifp->if_flags |= IFF_OACTIVE; 1189 return; 1190 } 1191 IFQ_DEQUEUE(&ifp->if_snd, m_head); 1192 1193 /* 1194 * If there's a BPF listener, bounce a copy of this frame 1195 * to him. 1196 */ 1197 #if NBPFILTER > 0 1198 if (ifp->if_bpf) 1199 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); 1200 #endif 1201 1202 ifp->if_flags |= IFF_OACTIVE; 1203 1204 /* 1205 * Set a timeout in case the chip goes out to lunch. 1206 */ 1207 ifp->if_timer = 5; 1208 1209 return; 1210 } 1211 1212 void 1213 mos_init(void *xsc) 1214 { 1215 struct mos_softc *sc = xsc; 1216 struct ifnet *ifp = &sc->arpcom.ac_if; 1217 struct mos_chain *c; 1218 usbd_status err; 1219 u_int8_t rxmode; 1220 int i, s; 1221 1222 s = splnet(); 1223 1224 /* 1225 * Cancel pending I/O and free all RX/TX buffers. 1226 */ 1227 mos_reset(sc); 1228 1229 /* 1230 * Write MAC address 1231 */ 1232 mos_writemac(sc, sc->arpcom.ac_enaddr); 1233 1234 /* Init RX ring. */ 1235 if (mos_rx_list_init(sc) == ENOBUFS) { 1236 printf("%s: rx list init failed\n", sc->mos_dev.dv_xname); 1237 splx(s); 1238 return; 1239 } 1240 1241 /* Init TX ring. */ 1242 if (mos_tx_list_init(sc) == ENOBUFS) { 1243 printf("%s: tx list init failed\n", sc->mos_dev.dv_xname); 1244 splx(s); 1245 return; 1246 } 1247 1248 /* Read and set transmitter IPG values */ 1249 sc->mos_ipgs[0] = mos_reg_read_1(sc, MOS_IPG0); 1250 sc->mos_ipgs[1] = mos_reg_read_1(sc, MOS_IPG1); 1251 mos_reg_write_1(sc, MOS_IPG0, sc->mos_ipgs[0]); 1252 mos_reg_write_1(sc, MOS_IPG1, sc->mos_ipgs[1]); 1253 1254 /* Enable receiver and transmitter, bridge controls speed/duplex mode */ 1255 rxmode = mos_reg_read_1(sc, MOS_CTL); 1256 rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB; 1257 rxmode &= ~(MOS_CTL_SLEEP); 1258 1259 /* If we want promiscuous mode, set the allframes bit. */ 1260 if (ifp->if_flags & IFF_PROMISC) 1261 rxmode |= MOS_CTL_RX_PROMISC; 1262 1263 /* XXX: broadcast mode? */ 1264 1265 mos_reg_write_1(sc, MOS_CTL, rxmode); 1266 1267 /* Load the multicast filter. */ 1268 mos_setmulti(sc); 1269 1270 mii_mediachg(GET_MII(sc)); 1271 1272 /* Open RX and TX pipes. */ 1273 err = usbd_open_pipe(sc->mos_iface, sc->mos_ed[MOS_ENDPT_RX], 1274 USBD_EXCLUSIVE_USE, &sc->mos_ep[MOS_ENDPT_RX]); 1275 if (err) { 1276 printf("%s: open rx pipe failed: %s\n", 1277 sc->mos_dev.dv_xname, usbd_errstr(err)); 1278 splx(s); 1279 return; 1280 } 1281 1282 err = usbd_open_pipe(sc->mos_iface, sc->mos_ed[MOS_ENDPT_TX], 1283 USBD_EXCLUSIVE_USE, &sc->mos_ep[MOS_ENDPT_TX]); 1284 if (err) { 1285 printf("%s: open tx pipe failed: %s\n", 1286 sc->mos_dev.dv_xname, usbd_errstr(err)); 1287 splx(s); 1288 return; 1289 } 1290 1291 /* Start up the receive pipe. */ 1292 for (i = 0; i < MOS_RX_LIST_CNT; i++) { 1293 c = &sc->mos_cdata.mos_rx_chain[i]; 1294 usbd_setup_xfer(c->mos_xfer, sc->mos_ep[MOS_ENDPT_RX], 1295 c, c->mos_buf, sc->mos_bufsz, 1296 USBD_SHORT_XFER_OK | USBD_NO_COPY, 1297 USBD_NO_TIMEOUT, mos_rxeof); 1298 usbd_transfer(c->mos_xfer); 1299 } 1300 1301 ifp->if_flags |= IFF_RUNNING; 1302 ifp->if_flags &= ~IFF_OACTIVE; 1303 1304 splx(s); 1305 1306 timeout_add_sec(&sc->mos_stat_ch, 1); 1307 return; 1308 } 1309 1310 int 1311 mos_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1312 { 1313 struct mos_softc *sc = ifp->if_softc; 1314 struct ifreq *ifr = (struct ifreq *)data; 1315 struct ifaddr *ifa = (struct ifaddr *)data; 1316 struct mii_data *mii; 1317 u_int8_t rxmode; 1318 int s, error = 0; 1319 1320 s = splnet(); 1321 1322 switch(cmd) { 1323 case SIOCSIFADDR: 1324 ifp->if_flags |= IFF_UP; 1325 if (!(ifp->if_flags & IFF_RUNNING)) 1326 mos_init(sc); 1327 #ifdef INET 1328 if (ifa->ifa_addr->sa_family == AF_INET) 1329 arp_ifinit(&sc->arpcom, ifa); 1330 #endif 1331 break; 1332 1333 case SIOCSIFMTU: 1334 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu) 1335 error = EINVAL; 1336 else if (ifp->if_mtu != ifr->ifr_mtu) 1337 ifp->if_mtu = ifr->ifr_mtu; 1338 break; 1339 1340 case SIOCSIFFLAGS: 1341 if (ifp->if_flags & IFF_UP) { 1342 if (ifp->if_flags & IFF_RUNNING && 1343 ifp->if_flags & IFF_PROMISC && 1344 !(sc->mos_if_flags & IFF_PROMISC)) { 1345 rxmode = mos_reg_read_1(sc, MOS_CTL); 1346 rxmode |= MOS_CTL_RX_PROMISC; 1347 mos_reg_write_1(sc, MOS_CTL, rxmode); 1348 mos_setmulti(sc); 1349 } else if (ifp->if_flags & IFF_RUNNING && 1350 !(ifp->if_flags & IFF_PROMISC) && 1351 !(sc->mos_if_flags & IFF_PROMISC)) { 1352 rxmode = mos_reg_read_1(sc, MOS_CTL); 1353 rxmode |= MOS_CTL_RX_PROMISC; 1354 mos_reg_write_1(sc, MOS_CTL, rxmode); 1355 mos_setmulti(sc); 1356 } else if (!(ifp->if_flags & IFF_RUNNING)) 1357 mos_init(sc); 1358 } else { 1359 if (ifp->if_flags & IFF_RUNNING) 1360 mos_stop(sc); 1361 } 1362 sc->mos_if_flags = ifp->if_flags; 1363 break; 1364 case SIOCADDMULTI: 1365 case SIOCDELMULTI: 1366 error = (cmd == SIOCADDMULTI) ? 1367 ether_addmulti(ifr, &sc->arpcom) : 1368 ether_delmulti(ifr, &sc->arpcom); 1369 1370 if (error == ENETRESET) { 1371 /* 1372 * Multicast list has changed; set the hardware 1373 * filter accordingly. 1374 */ 1375 if (ifp->if_flags & IFF_RUNNING) 1376 mos_setmulti(sc); 1377 error = 0; 1378 } 1379 break; 1380 case SIOCGIFMEDIA: 1381 case SIOCSIFMEDIA: 1382 mii = GET_MII(sc); 1383 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1384 break; 1385 1386 default: 1387 error = ether_ioctl(ifp, &sc->arpcom, cmd, data); 1388 } 1389 1390 splx(s); 1391 return(error); 1392 } 1393 1394 void 1395 mos_watchdog(struct ifnet *ifp) 1396 { 1397 struct mos_softc *sc; 1398 struct mos_chain *c; 1399 usbd_status stat; 1400 int s; 1401 1402 sc = ifp->if_softc; 1403 1404 ifp->if_oerrors++; 1405 printf("%s: watchdog timeout\n", sc->mos_dev.dv_xname); 1406 1407 s = splusb(); 1408 c = &sc->mos_cdata.mos_tx_chain[0]; 1409 usbd_get_xfer_status(c->mos_xfer, NULL, NULL, NULL, &stat); 1410 mos_txeof(c->mos_xfer, c, stat); 1411 1412 if (!IFQ_IS_EMPTY(&ifp->if_snd)) 1413 mos_start(ifp); 1414 splx(s); 1415 } 1416 1417 1418 /* 1419 * Stop the adapter and free any mbufs allocated to the 1420 * RX and TX lists. 1421 */ 1422 void 1423 mos_stop(struct mos_softc *sc) 1424 { 1425 usbd_status err; 1426 struct ifnet *ifp; 1427 int i; 1428 1429 mos_reset(sc); 1430 1431 ifp = &sc->arpcom.ac_if; 1432 ifp->if_timer = 0; 1433 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 1434 1435 timeout_del(&sc->mos_stat_ch); 1436 1437 /* Stop transfers. */ 1438 if (sc->mos_ep[MOS_ENDPT_RX] != NULL) { 1439 err = usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_RX]); 1440 if (err) { 1441 printf("%s: abort rx pipe failed: %s\n", 1442 sc->mos_dev.dv_xname, usbd_errstr(err)); 1443 } 1444 err = usbd_close_pipe(sc->mos_ep[MOS_ENDPT_RX]); 1445 if (err) { 1446 printf("%s: close rx pipe failed: %s\n", 1447 sc->mos_dev.dv_xname, usbd_errstr(err)); 1448 } 1449 sc->mos_ep[MOS_ENDPT_RX] = NULL; 1450 } 1451 1452 if (sc->mos_ep[MOS_ENDPT_TX] != NULL) { 1453 err = usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_TX]); 1454 if (err) { 1455 printf("%s: abort tx pipe failed: %s\n", 1456 sc->mos_dev.dv_xname, usbd_errstr(err)); 1457 } 1458 err = usbd_close_pipe(sc->mos_ep[MOS_ENDPT_TX]); 1459 if (err) { 1460 printf("%s: close tx pipe failed: %s\n", 1461 sc->mos_dev.dv_xname, usbd_errstr(err)); 1462 } 1463 sc->mos_ep[MOS_ENDPT_TX] = NULL; 1464 } 1465 1466 if (sc->mos_ep[MOS_ENDPT_INTR] != NULL) { 1467 err = usbd_abort_pipe(sc->mos_ep[MOS_ENDPT_INTR]); 1468 if (err) { 1469 printf("%s: abort intr pipe failed: %s\n", 1470 sc->mos_dev.dv_xname, usbd_errstr(err)); 1471 } 1472 err = usbd_close_pipe(sc->mos_ep[MOS_ENDPT_INTR]); 1473 if (err) { 1474 printf("%s: close intr pipe failed: %s\n", 1475 sc->mos_dev.dv_xname, usbd_errstr(err)); 1476 } 1477 sc->mos_ep[MOS_ENDPT_INTR] = NULL; 1478 } 1479 1480 /* Free RX resources. */ 1481 for (i = 0; i < MOS_RX_LIST_CNT; i++) { 1482 if (sc->mos_cdata.mos_rx_chain[i].mos_mbuf != NULL) { 1483 m_freem(sc->mos_cdata.mos_rx_chain[i].mos_mbuf); 1484 sc->mos_cdata.mos_rx_chain[i].mos_mbuf = NULL; 1485 } 1486 if (sc->mos_cdata.mos_rx_chain[i].mos_xfer != NULL) { 1487 usbd_free_xfer(sc->mos_cdata.mos_rx_chain[i].mos_xfer); 1488 sc->mos_cdata.mos_rx_chain[i].mos_xfer = NULL; 1489 } 1490 } 1491 1492 /* Free TX resources. */ 1493 for (i = 0; i < MOS_TX_LIST_CNT; i++) { 1494 if (sc->mos_cdata.mos_tx_chain[i].mos_mbuf != NULL) { 1495 m_freem(sc->mos_cdata.mos_tx_chain[i].mos_mbuf); 1496 sc->mos_cdata.mos_tx_chain[i].mos_mbuf = NULL; 1497 } 1498 if (sc->mos_cdata.mos_tx_chain[i].mos_xfer != NULL) { 1499 usbd_free_xfer(sc->mos_cdata.mos_tx_chain[i].mos_xfer); 1500 sc->mos_cdata.mos_tx_chain[i].mos_xfer = NULL; 1501 } 1502 } 1503 1504 sc->mos_link = 0; 1505 } 1506 1507