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