1 /* $OpenBSD: if_url.c,v 1.51 2008/09/10 14:01:23 blambert Exp $ */ 2 /* $NetBSD: if_url.c,v 1.6 2002/09/29 10:19:21 martin Exp $ */ 3 /* 4 * Copyright (c) 2001, 2002 5 * Shingo WATANABE <nabe@nabechan.org>. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the author nor the names of any co-contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 */ 32 33 /* 34 * The RTL8150L(Realtek USB to fast ethernet controller) spec can be found at 35 * ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/8150v14.pdf 36 * ftp://152.104.125.40/lancard/data_sheet/8150/8150v14.pdf 37 */ 38 39 /* 40 * TODO: 41 * Interrupt Endpoint support 42 * External PHYs 43 * powerhook() support? 44 */ 45 46 #include "bpfilter.h" 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/rwlock.h> 51 #include <sys/mbuf.h> 52 #include <sys/kernel.h> 53 #include <sys/proc.h> 54 #include <sys/socket.h> 55 56 #include <sys/device.h> 57 58 #include <net/if.h> 59 #include <net/if_arp.h> 60 #include <net/if_dl.h> 61 #include <net/if_media.h> 62 63 #if NBPFILTER > 0 64 #include <net/bpf.h> 65 #endif 66 67 #ifdef INET 68 #include <netinet/in.h> 69 #include <netinet/in_systm.h> 70 #include <netinet/in_var.h> 71 #include <netinet/ip.h> 72 #include <netinet/if_ether.h> 73 #endif 74 75 #include <dev/mii/mii.h> 76 #include <dev/mii/miivar.h> 77 #include <dev/mii/urlphyreg.h> 78 79 #include <dev/usb/usb.h> 80 #include <dev/usb/usbdi.h> 81 #include <dev/usb/usbdi_util.h> 82 #include <dev/usb/usbdevs.h> 83 84 #include <dev/usb/if_urlreg.h> 85 86 87 /* Function declarations */ 88 int url_match(struct device *, void *, void *); 89 void url_attach(struct device *, struct device *, void *); 90 int url_detach(struct device *, int); 91 int url_activate(struct device *, enum devact); 92 93 struct cfdriver url_cd = { 94 NULL, "url", DV_IFNET 95 }; 96 97 const struct cfattach url_ca = { 98 sizeof(struct url_softc), 99 url_match, 100 url_attach, 101 url_detach, 102 url_activate, 103 }; 104 105 int url_openpipes(struct url_softc *); 106 int url_rx_list_init(struct url_softc *); 107 int url_tx_list_init(struct url_softc *); 108 int url_newbuf(struct url_softc *, struct url_chain *, struct mbuf *); 109 void url_start(struct ifnet *); 110 int url_send(struct url_softc *, struct mbuf *, int); 111 void url_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 112 void url_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 113 void url_tick(void *); 114 void url_tick_task(void *); 115 int url_ioctl(struct ifnet *, u_long, caddr_t); 116 void url_stop_task(struct url_softc *); 117 void url_stop(struct ifnet *, int); 118 void url_watchdog(struct ifnet *); 119 int url_ifmedia_change(struct ifnet *); 120 void url_ifmedia_status(struct ifnet *, struct ifmediareq *); 121 void url_lock_mii(struct url_softc *); 122 void url_unlock_mii(struct url_softc *); 123 int url_int_miibus_readreg(struct device *, int, int); 124 void url_int_miibus_writereg(struct device *, int, int, int); 125 void url_miibus_statchg(struct device *); 126 int url_init(struct ifnet *); 127 void url_setmulti(struct url_softc *); 128 void url_reset(struct url_softc *); 129 130 int url_csr_read_1(struct url_softc *, int); 131 int url_csr_read_2(struct url_softc *, int); 132 int url_csr_write_1(struct url_softc *, int, int); 133 int url_csr_write_2(struct url_softc *, int, int); 134 int url_csr_write_4(struct url_softc *, int, int); 135 int url_mem(struct url_softc *, int, int, void *, int); 136 137 /* Macros */ 138 #ifdef URL_DEBUG 139 #define DPRINTF(x) do { if (urldebug) printf x; } while (0) 140 #define DPRINTFN(n,x) do { if (urldebug >= (n)) printf x; } while (0) 141 int urldebug = 0; 142 #else 143 #define DPRINTF(x) 144 #define DPRINTFN(n,x) 145 #endif 146 147 #define URL_SETBIT(sc, reg, x) \ 148 url_csr_write_1(sc, reg, url_csr_read_1(sc, reg) | (x)) 149 150 #define URL_SETBIT2(sc, reg, x) \ 151 url_csr_write_2(sc, reg, url_csr_read_2(sc, reg) | (x)) 152 153 #define URL_CLRBIT(sc, reg, x) \ 154 url_csr_write_1(sc, reg, url_csr_read_1(sc, reg) & ~(x)) 155 156 #define URL_CLRBIT2(sc, reg, x) \ 157 url_csr_write_2(sc, reg, url_csr_read_2(sc, reg) & ~(x)) 158 159 static const struct url_type { 160 struct usb_devno url_dev; 161 u_int16_t url_flags; 162 #define URL_EXT_PHY 0x0001 163 } url_devs [] = { 164 {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_LCS8138TX}, 0}, 165 {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RTL8151}, 0}, 166 {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX }, 0}, 167 {{ USB_VENDOR_MICRONET, USB_PRODUCT_MICRONET_SP128AR}, 0}, 168 {{ USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01}, 0}, 169 {{ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8150}, 0}, 170 {{ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8151}, 0}, 171 {{ USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_PRESTIGE}, 0} 172 }; 173 #define url_lookup(v, p) ((struct url_type *)usb_lookup(url_devs, v, p)) 174 175 176 /* Probe */ 177 int 178 url_match(struct device *parent, void *match, void *aux) 179 { 180 struct usb_attach_arg *uaa = aux; 181 182 if (uaa->iface != NULL) 183 return (UMATCH_NONE); 184 185 return (url_lookup(uaa->vendor, uaa->product) != NULL ? 186 UMATCH_VENDOR_PRODUCT : UMATCH_NONE); 187 } 188 /* Attach */ 189 void 190 url_attach(struct device *parent, struct device *self, void *aux) 191 { 192 struct url_softc *sc = (struct url_softc *)self; 193 struct usb_attach_arg *uaa = aux; 194 usbd_device_handle dev = uaa->device; 195 usbd_interface_handle iface; 196 usbd_status err; 197 usb_interface_descriptor_t *id; 198 usb_endpoint_descriptor_t *ed; 199 char *devname = sc->sc_dev.dv_xname; 200 struct ifnet *ifp; 201 struct mii_data *mii; 202 u_char eaddr[ETHER_ADDR_LEN]; 203 int i, s; 204 205 /* Move the device into the configured state. */ 206 err = usbd_set_config_no(dev, URL_CONFIG_NO, 1); 207 if (err) { 208 printf("%s: setting config no failed\n", devname); 209 goto bad; 210 } 211 212 usb_init_task(&sc->sc_tick_task, url_tick_task, sc); 213 rw_init(&sc->sc_mii_lock, "urlmii"); 214 usb_init_task(&sc->sc_stop_task, (void (*)(void *)) url_stop_task, sc); 215 216 /* get control interface */ 217 err = usbd_device2interface_handle(dev, URL_IFACE_INDEX, &iface); 218 if (err) { 219 printf("%s: failed to get interface, err=%s\n", devname, 220 usbd_errstr(err)); 221 goto bad; 222 } 223 224 sc->sc_udev = dev; 225 sc->sc_ctl_iface = iface; 226 sc->sc_flags = url_lookup(uaa->vendor, uaa->product)->url_flags; 227 228 /* get interface descriptor */ 229 id = usbd_get_interface_descriptor(sc->sc_ctl_iface); 230 231 /* find endpoints */ 232 sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1; 233 for (i = 0; i < id->bNumEndpoints; i++) { 234 ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i); 235 if (ed == NULL) { 236 printf("%s: couldn't get endpoint %d\n", devname, i); 237 goto bad; 238 } 239 if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && 240 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) 241 sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */ 242 else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && 243 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) 244 sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */ 245 else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT && 246 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) 247 sc->sc_intrin_no = ed->bEndpointAddress; /* Status */ 248 } 249 250 if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 || 251 sc->sc_intrin_no == -1) { 252 printf("%s: missing endpoint\n", devname); 253 goto bad; 254 } 255 256 s = splnet(); 257 258 /* reset the adapter */ 259 url_reset(sc); 260 261 /* Get Ethernet Address */ 262 err = url_mem(sc, URL_CMD_READMEM, URL_IDR0, (void *)eaddr, 263 ETHER_ADDR_LEN); 264 if (err) { 265 printf("%s: read MAC address failed\n", devname); 266 splx(s); 267 goto bad; 268 } 269 270 /* Print Ethernet Address */ 271 printf("%s: address %s\n", devname, ether_sprintf(eaddr)); 272 273 bcopy(eaddr, (char *)&sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN); 274 /* initialize interface information */ 275 ifp = GET_IFP(sc); 276 ifp->if_softc = sc; 277 strlcpy(ifp->if_xname, devname, IFNAMSIZ); 278 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 279 ifp->if_start = url_start; 280 ifp->if_ioctl = url_ioctl; 281 ifp->if_watchdog = url_watchdog; 282 283 IFQ_SET_READY(&ifp->if_snd); 284 285 /* 286 * Do ifmedia setup. 287 */ 288 mii = &sc->sc_mii; 289 mii->mii_ifp = ifp; 290 mii->mii_readreg = url_int_miibus_readreg; 291 mii->mii_writereg = url_int_miibus_writereg; 292 #if 0 293 if (sc->sc_flags & URL_EXT_PHY) { 294 mii->mii_readreg = url_ext_miibus_readreg; 295 mii->mii_writereg = url_ext_miibus_writereg; 296 } 297 #endif 298 mii->mii_statchg = url_miibus_statchg; 299 mii->mii_flags = MIIF_AUTOTSLEEP; 300 ifmedia_init(&mii->mii_media, 0, 301 url_ifmedia_change, url_ifmedia_status); 302 mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); 303 if (LIST_FIRST(&mii->mii_phys) == NULL) { 304 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); 305 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); 306 } else 307 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 308 309 /* attach the interface */ 310 if_attach(ifp); 311 ether_ifattach(ifp); 312 313 timeout_set(&sc->sc_stat_ch, url_tick, sc); 314 sc->sc_attached = 1; 315 splx(s); 316 317 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, &sc->sc_dev); 318 319 return; 320 321 bad: 322 sc->sc_dying = 1; 323 } 324 325 /* detach */ 326 int 327 url_detach(struct device *self, int flags) 328 { 329 struct url_softc *sc = (struct url_softc *)self; 330 struct ifnet *ifp = GET_IFP(sc); 331 int s; 332 333 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 334 335 /* Detached before attached finished */ 336 if (!sc->sc_attached) 337 return (0); 338 339 timeout_del(&sc->sc_stat_ch); 340 341 /* Remove any pending tasks */ 342 usb_rem_task(sc->sc_udev, &sc->sc_tick_task); 343 usb_rem_task(sc->sc_udev, &sc->sc_stop_task); 344 345 s = splusb(); 346 347 if (--sc->sc_refcnt >= 0) { 348 /* Wait for processes to go away */ 349 usb_detach_wait(&sc->sc_dev); 350 } 351 352 if (ifp->if_flags & IFF_RUNNING) 353 url_stop(GET_IFP(sc), 1); 354 355 mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); 356 ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY); 357 ether_ifdetach(ifp); 358 if_detach(ifp); 359 360 #ifdef DIAGNOSTIC 361 if (sc->sc_pipe_tx != NULL) 362 printf("%s: detach has active tx endpoint.\n", 363 sc->sc_dev.dv_xname); 364 if (sc->sc_pipe_rx != NULL) 365 printf("%s: detach has active rx endpoint.\n", 366 sc->sc_dev.dv_xname); 367 if (sc->sc_pipe_intr != NULL) 368 printf("%s: detach has active intr endpoint.\n", 369 sc->sc_dev.dv_xname); 370 #endif 371 372 sc->sc_attached = 0; 373 374 splx(s); 375 376 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 377 &sc->sc_dev); 378 379 return (0); 380 } 381 382 /* read/write memory */ 383 int 384 url_mem(struct url_softc *sc, int cmd, int offset, void *buf, int len) 385 { 386 usb_device_request_t req; 387 usbd_status err; 388 389 if (sc == NULL) 390 return (0); 391 392 DPRINTFN(0x200, 393 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 394 395 if (sc->sc_dying) 396 return (0); 397 398 if (cmd == URL_CMD_READMEM) 399 req.bmRequestType = UT_READ_VENDOR_DEVICE; 400 else 401 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 402 req.bRequest = URL_REQ_MEM; 403 USETW(req.wValue, offset); 404 USETW(req.wIndex, 0x0000); 405 USETW(req.wLength, len); 406 407 sc->sc_refcnt++; 408 err = usbd_do_request(sc->sc_udev, &req, buf); 409 if (--sc->sc_refcnt < 0) 410 usb_detach_wakeup(&sc->sc_dev); 411 if (err) { 412 DPRINTF(("%s: url_mem(): %s failed. off=%04x, err=%d\n", 413 sc->sc_dev.dv_xname, 414 cmd == URL_CMD_READMEM ? "read" : "write", 415 offset, err)); 416 } 417 418 return (err); 419 } 420 421 /* read 1byte from register */ 422 int 423 url_csr_read_1(struct url_softc *sc, int reg) 424 { 425 u_int8_t val = 0; 426 427 DPRINTFN(0x100, 428 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 429 430 if (sc->sc_dying) 431 return (0); 432 433 return (url_mem(sc, URL_CMD_READMEM, reg, &val, 1) ? 0 : val); 434 } 435 436 /* read 2bytes from register */ 437 int 438 url_csr_read_2(struct url_softc *sc, int reg) 439 { 440 uWord val; 441 442 DPRINTFN(0x100, 443 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 444 445 if (sc->sc_dying) 446 return (0); 447 448 USETW(val, 0); 449 return (url_mem(sc, URL_CMD_READMEM, reg, &val, 2) ? 0 : UGETW(val)); 450 } 451 452 /* write 1byte to register */ 453 int 454 url_csr_write_1(struct url_softc *sc, int reg, int aval) 455 { 456 u_int8_t val = aval; 457 458 DPRINTFN(0x100, 459 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 460 461 if (sc->sc_dying) 462 return (0); 463 464 return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 1) ? -1 : 0); 465 } 466 467 /* write 2bytes to register */ 468 int 469 url_csr_write_2(struct url_softc *sc, int reg, int aval) 470 { 471 uWord val; 472 473 DPRINTFN(0x100, 474 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 475 476 USETW(val, aval); 477 478 if (sc->sc_dying) 479 return (0); 480 481 return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 2) ? -1 : 0); 482 } 483 484 /* write 4bytes to register */ 485 int 486 url_csr_write_4(struct url_softc *sc, int reg, int aval) 487 { 488 uDWord val; 489 490 DPRINTFN(0x100, 491 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 492 493 USETDW(val, aval); 494 495 if (sc->sc_dying) 496 return (0); 497 498 return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 4) ? -1 : 0); 499 } 500 501 int 502 url_init(struct ifnet *ifp) 503 { 504 struct url_softc *sc = ifp->if_softc; 505 struct mii_data *mii = GET_MII(sc); 506 u_char *eaddr; 507 int i, s; 508 509 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 510 511 if (sc->sc_dying) 512 return (EIO); 513 514 s = splnet(); 515 516 /* Cancel pending I/O and free all TX/RX buffers */ 517 url_stop(ifp, 1); 518 519 eaddr = sc->sc_ac.ac_enaddr; 520 for (i = 0; i < ETHER_ADDR_LEN; i++) 521 url_csr_write_1(sc, URL_IDR0 + i, eaddr[i]); 522 523 /* Init transmission control register */ 524 URL_CLRBIT(sc, URL_TCR, 525 URL_TCR_TXRR1 | URL_TCR_TXRR0 | 526 URL_TCR_IFG1 | URL_TCR_IFG0 | 527 URL_TCR_NOCRC); 528 529 /* Init receive control register */ 530 URL_SETBIT2(sc, URL_RCR, URL_RCR_TAIL | URL_RCR_AD); 531 if (ifp->if_flags & IFF_BROADCAST) 532 URL_SETBIT2(sc, URL_RCR, URL_RCR_AB); 533 else 534 URL_CLRBIT2(sc, URL_RCR, URL_RCR_AB); 535 536 /* If we want promiscuous mode, accept all physical frames. */ 537 if (ifp->if_flags & IFF_PROMISC) 538 URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); 539 else 540 URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); 541 542 543 /* Initialize transmit ring */ 544 if (url_tx_list_init(sc) == ENOBUFS) { 545 printf("%s: tx list init failed\n", sc->sc_dev.dv_xname); 546 splx(s); 547 return (EIO); 548 } 549 550 /* Initialize receive ring */ 551 if (url_rx_list_init(sc) == ENOBUFS) { 552 printf("%s: rx list init failed\n", sc->sc_dev.dv_xname); 553 splx(s); 554 return (EIO); 555 } 556 557 /* Load the multicast filter */ 558 url_setmulti(sc); 559 560 /* Enable RX and TX */ 561 URL_SETBIT(sc, URL_CR, URL_CR_TE | URL_CR_RE); 562 563 mii_mediachg(mii); 564 565 if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) { 566 if (url_openpipes(sc)) { 567 splx(s); 568 return (EIO); 569 } 570 } 571 572 ifp->if_flags |= IFF_RUNNING; 573 ifp->if_flags &= ~IFF_OACTIVE; 574 575 splx(s); 576 577 timeout_add_sec(&sc->sc_stat_ch, 1); 578 579 return (0); 580 } 581 582 void 583 url_reset(struct url_softc *sc) 584 { 585 int i; 586 587 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 588 589 if (sc->sc_dying) 590 return; 591 592 URL_SETBIT(sc, URL_CR, URL_CR_SOFT_RST); 593 594 for (i = 0; i < URL_TX_TIMEOUT; i++) { 595 if (!(url_csr_read_1(sc, URL_CR) & URL_CR_SOFT_RST)) 596 break; 597 delay(10); /* XXX */ 598 } 599 600 delay(10000); /* XXX */ 601 } 602 603 int 604 url_activate(struct device *self, enum devact act) 605 { 606 struct url_softc *sc = (struct url_softc *)self; 607 608 DPRINTF(("%s: %s: enter, act=%d\n", sc->sc_dev.dv_xname, 609 __func__, act)); 610 611 switch (act) { 612 case DVACT_ACTIVATE: 613 break; 614 615 case DVACT_DEACTIVATE: 616 sc->sc_dying = 1; 617 break; 618 } 619 620 return (0); 621 } 622 623 #define url_calchash(addr) (ether_crc32_be((addr), ETHER_ADDR_LEN) >> 26) 624 625 626 void 627 url_setmulti(struct url_softc *sc) 628 { 629 struct ifnet *ifp; 630 struct ether_multi *enm; 631 struct ether_multistep step; 632 u_int32_t hashes[2] = { 0, 0 }; 633 int h = 0; 634 int mcnt = 0; 635 636 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 637 638 if (sc->sc_dying) 639 return; 640 641 ifp = GET_IFP(sc); 642 643 if (ifp->if_flags & IFF_PROMISC) { 644 URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); 645 return; 646 } else if (ifp->if_flags & IFF_ALLMULTI) { 647 allmulti: 648 ifp->if_flags |= IFF_ALLMULTI; 649 URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM); 650 URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAP); 651 return; 652 } 653 654 /* first, zot all the existing hash bits */ 655 url_csr_write_4(sc, URL_MAR0, 0); 656 url_csr_write_4(sc, URL_MAR4, 0); 657 658 /* now program new ones */ 659 ETHER_FIRST_MULTI(step, &sc->sc_ac, enm); 660 while (enm != NULL) { 661 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 662 ETHER_ADDR_LEN) != 0) 663 goto allmulti; 664 665 h = url_calchash(enm->enm_addrlo); 666 if (h < 32) 667 hashes[0] |= (1 << h); 668 else 669 hashes[1] |= (1 << (h -32)); 670 mcnt++; 671 ETHER_NEXT_MULTI(step, enm); 672 } 673 674 ifp->if_flags &= ~IFF_ALLMULTI; 675 676 URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); 677 678 if (mcnt){ 679 URL_SETBIT2(sc, URL_RCR, URL_RCR_AM); 680 } else { 681 URL_CLRBIT2(sc, URL_RCR, URL_RCR_AM); 682 } 683 url_csr_write_4(sc, URL_MAR0, hashes[0]); 684 url_csr_write_4(sc, URL_MAR4, hashes[1]); 685 } 686 687 int 688 url_openpipes(struct url_softc *sc) 689 { 690 struct url_chain *c; 691 usbd_status err; 692 int i; 693 int error = 0; 694 695 if (sc->sc_dying) 696 return (EIO); 697 698 sc->sc_refcnt++; 699 700 /* Open RX pipe */ 701 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no, 702 USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx); 703 if (err) { 704 printf("%s: open rx pipe failed: %s\n", 705 sc->sc_dev.dv_xname, usbd_errstr(err)); 706 error = EIO; 707 goto done; 708 } 709 710 /* Open TX pipe */ 711 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no, 712 USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx); 713 if (err) { 714 printf("%s: open tx pipe failed: %s\n", 715 sc->sc_dev.dv_xname, usbd_errstr(err)); 716 error = EIO; 717 goto done; 718 } 719 720 #if 0 721 /* XXX: interrupt endpoint is not yet supported */ 722 /* Open Interrupt pipe */ 723 err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no, 724 USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc, 725 &sc->sc_cdata.url_ibuf, URL_INTR_PKGLEN, 726 url_intr, URL_INTR_INTERVAL); 727 if (err) { 728 printf("%s: open intr pipe failed: %s\n", 729 sc->sc_dev.dv_xname, usbd_errstr(err)); 730 error = EIO; 731 goto done; 732 } 733 #endif 734 735 736 /* Start up the receive pipe. */ 737 for (i = 0; i < URL_RX_LIST_CNT; i++) { 738 c = &sc->sc_cdata.url_rx_chain[i]; 739 usbd_setup_xfer(c->url_xfer, sc->sc_pipe_rx, 740 c, c->url_buf, URL_BUFSZ, 741 USBD_SHORT_XFER_OK | USBD_NO_COPY, 742 USBD_NO_TIMEOUT, url_rxeof); 743 (void)usbd_transfer(c->url_xfer); 744 DPRINTF(("%s: %s: start read\n", sc->sc_dev.dv_xname, 745 __func__)); 746 } 747 748 done: 749 if (--sc->sc_refcnt < 0) 750 usb_detach_wakeup(&sc->sc_dev); 751 752 return (error); 753 } 754 755 int 756 url_newbuf(struct url_softc *sc, struct url_chain *c, struct mbuf *m) 757 { 758 struct mbuf *m_new = NULL; 759 760 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 761 762 if (m == NULL) { 763 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 764 if (m_new == NULL) { 765 printf("%s: no memory for rx list " 766 "-- packet dropped!\n", sc->sc_dev.dv_xname); 767 return (ENOBUFS); 768 } 769 MCLGET(m_new, M_DONTWAIT); 770 if (!(m_new->m_flags & M_EXT)) { 771 printf("%s: no memory for rx list " 772 "-- packet dropped!\n", sc->sc_dev.dv_xname); 773 m_freem(m_new); 774 return (ENOBUFS); 775 } 776 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 777 } else { 778 m_new = m; 779 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 780 m_new->m_data = m_new->m_ext.ext_buf; 781 } 782 783 m_adj(m_new, ETHER_ALIGN); 784 c->url_mbuf = m_new; 785 786 return (0); 787 } 788 789 790 int 791 url_rx_list_init(struct url_softc *sc) 792 { 793 struct url_cdata *cd; 794 struct url_chain *c; 795 int i; 796 797 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 798 799 cd = &sc->sc_cdata; 800 for (i = 0; i < URL_RX_LIST_CNT; i++) { 801 c = &cd->url_rx_chain[i]; 802 c->url_sc = sc; 803 c->url_idx = i; 804 if (url_newbuf(sc, c, NULL) == ENOBUFS) 805 return (ENOBUFS); 806 if (c->url_xfer == NULL) { 807 c->url_xfer = usbd_alloc_xfer(sc->sc_udev); 808 if (c->url_xfer == NULL) 809 return (ENOBUFS); 810 c->url_buf = usbd_alloc_buffer(c->url_xfer, URL_BUFSZ); 811 if (c->url_buf == NULL) { 812 usbd_free_xfer(c->url_xfer); 813 return (ENOBUFS); 814 } 815 } 816 } 817 818 return (0); 819 } 820 821 int 822 url_tx_list_init(struct url_softc *sc) 823 { 824 struct url_cdata *cd; 825 struct url_chain *c; 826 int i; 827 828 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 829 830 cd = &sc->sc_cdata; 831 for (i = 0; i < URL_TX_LIST_CNT; i++) { 832 c = &cd->url_tx_chain[i]; 833 c->url_sc = sc; 834 c->url_idx = i; 835 c->url_mbuf = NULL; 836 if (c->url_xfer == NULL) { 837 c->url_xfer = usbd_alloc_xfer(sc->sc_udev); 838 if (c->url_xfer == NULL) 839 return (ENOBUFS); 840 c->url_buf = usbd_alloc_buffer(c->url_xfer, URL_BUFSZ); 841 if (c->url_buf == NULL) { 842 usbd_free_xfer(c->url_xfer); 843 return (ENOBUFS); 844 } 845 } 846 } 847 848 return (0); 849 } 850 851 void 852 url_start(struct ifnet *ifp) 853 { 854 struct url_softc *sc = ifp->if_softc; 855 struct mbuf *m_head = NULL; 856 857 DPRINTF(("%s: %s: enter, link=%d\n", sc->sc_dev.dv_xname, 858 __func__, sc->sc_link)); 859 860 if (sc->sc_dying) 861 return; 862 863 if (!sc->sc_link) 864 return; 865 866 if (ifp->if_flags & IFF_OACTIVE) 867 return; 868 869 IFQ_POLL(&ifp->if_snd, m_head); 870 if (m_head == NULL) 871 return; 872 873 if (url_send(sc, m_head, 0)) { 874 ifp->if_flags |= IFF_OACTIVE; 875 return; 876 } 877 878 IFQ_DEQUEUE(&ifp->if_snd, m_head); 879 880 #if NBPFILTER > 0 881 if (ifp->if_bpf) 882 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); 883 #endif 884 885 ifp->if_flags |= IFF_OACTIVE; 886 887 /* Set a timeout in case the chip goes out to lunch. */ 888 ifp->if_timer = 5; 889 } 890 891 int 892 url_send(struct url_softc *sc, struct mbuf *m, int idx) 893 { 894 int total_len; 895 struct url_chain *c; 896 usbd_status err; 897 898 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 899 900 c = &sc->sc_cdata.url_tx_chain[idx]; 901 902 /* Copy the mbuf data into a contiguous buffer */ 903 m_copydata(m, 0, m->m_pkthdr.len, c->url_buf); 904 c->url_mbuf = m; 905 total_len = m->m_pkthdr.len; 906 907 if (total_len < URL_MIN_FRAME_LEN) { 908 bzero(c->url_buf + total_len, URL_MIN_FRAME_LEN - total_len); 909 total_len = URL_MIN_FRAME_LEN; 910 } 911 usbd_setup_xfer(c->url_xfer, sc->sc_pipe_tx, c, c->url_buf, total_len, 912 USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 913 URL_TX_TIMEOUT, url_txeof); 914 915 /* Transmit */ 916 sc->sc_refcnt++; 917 err = usbd_transfer(c->url_xfer); 918 if (--sc->sc_refcnt < 0) 919 usb_detach_wakeup(&sc->sc_dev); 920 if (err != USBD_IN_PROGRESS) { 921 printf("%s: url_send error=%s\n", sc->sc_dev.dv_xname, 922 usbd_errstr(err)); 923 /* Stop the interface */ 924 usb_add_task(sc->sc_udev, &sc->sc_stop_task); 925 return (EIO); 926 } 927 928 DPRINTF(("%s: %s: send %d bytes\n", sc->sc_dev.dv_xname, 929 __func__, total_len)); 930 931 sc->sc_cdata.url_tx_cnt++; 932 933 return (0); 934 } 935 936 void 937 url_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 938 { 939 struct url_chain *c = priv; 940 struct url_softc *sc = c->url_sc; 941 struct ifnet *ifp = GET_IFP(sc); 942 int s; 943 944 if (sc->sc_dying) 945 return; 946 947 s = splnet(); 948 949 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 950 951 ifp->if_timer = 0; 952 ifp->if_flags &= ~IFF_OACTIVE; 953 954 if (status != USBD_NORMAL_COMPLETION) { 955 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 956 splx(s); 957 return; 958 } 959 ifp->if_oerrors++; 960 printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname, 961 usbd_errstr(status)); 962 if (status == USBD_STALLED) { 963 sc->sc_refcnt++; 964 usbd_clear_endpoint_stall_async(sc->sc_pipe_tx); 965 if (--sc->sc_refcnt < 0) 966 usb_detach_wakeup(&sc->sc_dev); 967 } 968 splx(s); 969 return; 970 } 971 972 ifp->if_opackets++; 973 974 m_freem(c->url_mbuf); 975 c->url_mbuf = NULL; 976 977 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 978 url_start(ifp); 979 980 splx(s); 981 } 982 983 void 984 url_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 985 { 986 struct url_chain *c = priv; 987 struct url_softc *sc = c->url_sc; 988 struct ifnet *ifp = GET_IFP(sc); 989 struct mbuf *m; 990 u_int32_t total_len; 991 url_rxhdr_t rxhdr; 992 int s; 993 994 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 995 996 if (sc->sc_dying) 997 return; 998 999 if (status != USBD_NORMAL_COMPLETION) { 1000 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 1001 return; 1002 sc->sc_rx_errs++; 1003 if (usbd_ratecheck(&sc->sc_rx_notice)) { 1004 printf("%s: %u usb errors on rx: %s\n", 1005 sc->sc_dev.dv_xname, sc->sc_rx_errs, 1006 usbd_errstr(status)); 1007 sc->sc_rx_errs = 0; 1008 } 1009 if (status == USBD_STALLED) { 1010 sc->sc_refcnt++; 1011 usbd_clear_endpoint_stall_async(sc->sc_pipe_rx); 1012 if (--sc->sc_refcnt < 0) 1013 usb_detach_wakeup(&sc->sc_dev); 1014 } 1015 goto done; 1016 } 1017 1018 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 1019 1020 memcpy(mtod(c->url_mbuf, char *), c->url_buf, total_len); 1021 1022 if (total_len <= ETHER_CRC_LEN) { 1023 ifp->if_ierrors++; 1024 goto done; 1025 } 1026 1027 memcpy(&rxhdr, c->url_buf + total_len - ETHER_CRC_LEN, sizeof(rxhdr)); 1028 1029 DPRINTF(("%s: RX Status: %dbytes%s%s%s%s packets\n", 1030 sc->sc_dev.dv_xname, 1031 UGETW(rxhdr) & URL_RXHDR_BYTEC_MASK, 1032 UGETW(rxhdr) & URL_RXHDR_VALID_MASK ? ", Valid" : "", 1033 UGETW(rxhdr) & URL_RXHDR_RUNTPKT_MASK ? ", Runt" : "", 1034 UGETW(rxhdr) & URL_RXHDR_PHYPKT_MASK ? ", Physical match" : "", 1035 UGETW(rxhdr) & URL_RXHDR_MCASTPKT_MASK ? ", Multicast" : "")); 1036 1037 if ((UGETW(rxhdr) & URL_RXHDR_VALID_MASK) == 0) { 1038 ifp->if_ierrors++; 1039 goto done; 1040 } 1041 1042 ifp->if_ipackets++; 1043 total_len -= ETHER_CRC_LEN; 1044 1045 m = c->url_mbuf; 1046 m->m_pkthdr.len = m->m_len = total_len; 1047 m->m_pkthdr.rcvif = ifp; 1048 1049 s = splnet(); 1050 1051 if (url_newbuf(sc, c, NULL) == ENOBUFS) { 1052 ifp->if_ierrors++; 1053 goto done1; 1054 } 1055 1056 #if NBPFILTER > 0 1057 if (ifp->if_bpf) 1058 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 1059 #endif 1060 1061 DPRINTF(("%s: %s: deliver %d\n", sc->sc_dev.dv_xname, 1062 __func__, m->m_len)); 1063 ether_input_mbuf(ifp, m); 1064 1065 done1: 1066 splx(s); 1067 1068 done: 1069 /* Setup new transfer */ 1070 usbd_setup_xfer(xfer, sc->sc_pipe_rx, c, c->url_buf, URL_BUFSZ, 1071 USBD_SHORT_XFER_OK | USBD_NO_COPY, 1072 USBD_NO_TIMEOUT, url_rxeof); 1073 sc->sc_refcnt++; 1074 usbd_transfer(xfer); 1075 if (--sc->sc_refcnt < 0) 1076 usb_detach_wakeup(&sc->sc_dev); 1077 1078 DPRINTF(("%s: %s: start rx\n", sc->sc_dev.dv_xname, __func__)); 1079 } 1080 1081 #if 0 1082 void url_intr() 1083 { 1084 } 1085 #endif 1086 1087 int 1088 url_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1089 { 1090 struct url_softc *sc = ifp->if_softc; 1091 struct ifaddr *ifa = (struct ifaddr *)data; 1092 struct ifreq *ifr = (struct ifreq *)data; 1093 struct mii_data *mii; 1094 int s, error = 0; 1095 1096 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1097 1098 if (sc->sc_dying) 1099 return (EIO); 1100 1101 s = splnet(); 1102 1103 switch (cmd) { 1104 case SIOCSIFADDR: 1105 ifp->if_flags |= IFF_UP; 1106 url_init(ifp); 1107 1108 switch (ifa->ifa_addr->sa_family) { 1109 #ifdef INET 1110 case AF_INET: 1111 arp_ifinit(&sc->sc_ac, ifa); 1112 break; 1113 #endif /* INET */ 1114 } 1115 break; 1116 1117 case SIOCSIFMTU: 1118 if (ifr->ifr_mtu > ETHERMTU) 1119 error = EINVAL; 1120 else 1121 ifp->if_mtu = ifr->ifr_mtu; 1122 break; 1123 1124 case SIOCSIFFLAGS: 1125 if (ifp->if_flags & IFF_UP) { 1126 if (ifp->if_flags & IFF_RUNNING && 1127 ifp->if_flags & IFF_PROMISC) { 1128 URL_SETBIT2(sc, URL_RCR, 1129 URL_RCR_AAM|URL_RCR_AAP); 1130 } else if (ifp->if_flags & IFF_RUNNING && 1131 !(ifp->if_flags & IFF_PROMISC)) { 1132 URL_CLRBIT2(sc, URL_RCR, 1133 URL_RCR_AAM|URL_RCR_AAP); 1134 } else if (!(ifp->if_flags & IFF_RUNNING)) 1135 url_init(ifp); 1136 } else { 1137 if (ifp->if_flags & IFF_RUNNING) 1138 url_stop(ifp, 1); 1139 } 1140 error = 0; 1141 break; 1142 case SIOCADDMULTI: 1143 case SIOCDELMULTI: 1144 error = (cmd == SIOCADDMULTI) ? 1145 ether_addmulti(ifr, &sc->sc_ac) : 1146 ether_delmulti(ifr, &sc->sc_ac); 1147 1148 if (error == ENETRESET) { 1149 if (ifp->if_flags & IFF_RUNNING) 1150 url_setmulti(sc); 1151 error = 0; 1152 } 1153 break; 1154 case SIOCGIFMEDIA: 1155 case SIOCSIFMEDIA: 1156 mii = GET_MII(sc); 1157 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1158 break; 1159 default: 1160 error = EINVAL; 1161 break; 1162 } 1163 1164 splx(s); 1165 1166 return (error); 1167 } 1168 1169 void 1170 url_watchdog(struct ifnet *ifp) 1171 { 1172 struct url_softc *sc = ifp->if_softc; 1173 struct url_chain *c; 1174 usbd_status stat; 1175 int s; 1176 1177 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1178 1179 ifp->if_oerrors++; 1180 printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname); 1181 1182 s = splusb(); 1183 c = &sc->sc_cdata.url_tx_chain[0]; 1184 usbd_get_xfer_status(c->url_xfer, NULL, NULL, NULL, &stat); 1185 url_txeof(c->url_xfer, c, stat); 1186 1187 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 1188 url_start(ifp); 1189 splx(s); 1190 } 1191 1192 void 1193 url_stop_task(struct url_softc *sc) 1194 { 1195 url_stop(GET_IFP(sc), 1); 1196 } 1197 1198 /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ 1199 void 1200 url_stop(struct ifnet *ifp, int disable) 1201 { 1202 struct url_softc *sc = ifp->if_softc; 1203 usbd_status err; 1204 int i; 1205 1206 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1207 1208 ifp->if_timer = 0; 1209 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 1210 1211 url_reset(sc); 1212 1213 timeout_del(&sc->sc_stat_ch); 1214 1215 /* Stop transfers */ 1216 /* RX endpoint */ 1217 if (sc->sc_pipe_rx != NULL) { 1218 err = usbd_abort_pipe(sc->sc_pipe_rx); 1219 if (err) 1220 printf("%s: abort rx pipe failed: %s\n", 1221 sc->sc_dev.dv_xname, usbd_errstr(err)); 1222 err = usbd_close_pipe(sc->sc_pipe_rx); 1223 if (err) 1224 printf("%s: close rx pipe failed: %s\n", 1225 sc->sc_dev.dv_xname, usbd_errstr(err)); 1226 sc->sc_pipe_rx = NULL; 1227 } 1228 1229 /* TX endpoint */ 1230 if (sc->sc_pipe_tx != NULL) { 1231 err = usbd_abort_pipe(sc->sc_pipe_tx); 1232 if (err) 1233 printf("%s: abort tx pipe failed: %s\n", 1234 sc->sc_dev.dv_xname, usbd_errstr(err)); 1235 err = usbd_close_pipe(sc->sc_pipe_tx); 1236 if (err) 1237 printf("%s: close tx pipe failed: %s\n", 1238 sc->sc_dev.dv_xname, usbd_errstr(err)); 1239 sc->sc_pipe_tx = NULL; 1240 } 1241 1242 #if 0 1243 /* XXX: Interrupt endpoint is not yet supported!! */ 1244 /* Interrupt endpoint */ 1245 if (sc->sc_pipe_intr != NULL) { 1246 err = usbd_abort_pipe(sc->sc_pipe_intr); 1247 if (err) 1248 printf("%s: abort intr pipe failed: %s\n", 1249 sc->sc_dev.dv_xname, usbd_errstr(err)); 1250 err = usbd_close_pipe(sc->sc_pipe_intr); 1251 if (err) 1252 printf("%s: close intr pipe failed: %s\n", 1253 sc->sc_dev.dv_xname, usbd_errstr(err)); 1254 sc->sc_pipe_intr = NULL; 1255 } 1256 #endif 1257 1258 /* Free RX resources. */ 1259 for (i = 0; i < URL_RX_LIST_CNT; i++) { 1260 if (sc->sc_cdata.url_rx_chain[i].url_mbuf != NULL) { 1261 m_freem(sc->sc_cdata.url_rx_chain[i].url_mbuf); 1262 sc->sc_cdata.url_rx_chain[i].url_mbuf = NULL; 1263 } 1264 if (sc->sc_cdata.url_rx_chain[i].url_xfer != NULL) { 1265 usbd_free_xfer(sc->sc_cdata.url_rx_chain[i].url_xfer); 1266 sc->sc_cdata.url_rx_chain[i].url_xfer = NULL; 1267 } 1268 } 1269 1270 /* Free TX resources. */ 1271 for (i = 0; i < URL_TX_LIST_CNT; i++) { 1272 if (sc->sc_cdata.url_tx_chain[i].url_mbuf != NULL) { 1273 m_freem(sc->sc_cdata.url_tx_chain[i].url_mbuf); 1274 sc->sc_cdata.url_tx_chain[i].url_mbuf = NULL; 1275 } 1276 if (sc->sc_cdata.url_tx_chain[i].url_xfer != NULL) { 1277 usbd_free_xfer(sc->sc_cdata.url_tx_chain[i].url_xfer); 1278 sc->sc_cdata.url_tx_chain[i].url_xfer = NULL; 1279 } 1280 } 1281 1282 sc->sc_link = 0; 1283 } 1284 1285 /* Set media options */ 1286 int 1287 url_ifmedia_change(struct ifnet *ifp) 1288 { 1289 struct url_softc *sc = ifp->if_softc; 1290 struct mii_data *mii = GET_MII(sc); 1291 1292 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1293 1294 if (sc->sc_dying) 1295 return (0); 1296 1297 sc->sc_link = 0; 1298 if (mii->mii_instance) { 1299 struct mii_softc *miisc; 1300 for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL; 1301 miisc = LIST_NEXT(miisc, mii_list)) 1302 mii_phy_reset(miisc); 1303 } 1304 1305 return (mii_mediachg(mii)); 1306 } 1307 1308 /* Report current media status. */ 1309 void 1310 url_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr) 1311 { 1312 struct url_softc *sc = ifp->if_softc; 1313 struct mii_data *mii = GET_MII(sc); 1314 1315 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1316 1317 if (sc->sc_dying) 1318 return; 1319 1320 if ((ifp->if_flags & IFF_RUNNING) == 0) { 1321 ifmr->ifm_active = IFM_ETHER | IFM_NONE; 1322 ifmr->ifm_status = 0; 1323 return; 1324 } 1325 1326 mii_pollstat(mii); 1327 ifmr->ifm_active = mii->mii_media_active; 1328 ifmr->ifm_status = mii->mii_media_status; 1329 } 1330 1331 void 1332 url_tick(void *xsc) 1333 { 1334 struct url_softc *sc = xsc; 1335 1336 if (sc == NULL) 1337 return; 1338 1339 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname, 1340 __func__)); 1341 1342 if (sc->sc_dying) 1343 return; 1344 1345 /* Perform periodic stuff in process context */ 1346 usb_add_task(sc->sc_udev, &sc->sc_tick_task); 1347 } 1348 1349 void 1350 url_tick_task(void *xsc) 1351 { 1352 struct url_softc *sc = xsc; 1353 struct ifnet *ifp; 1354 struct mii_data *mii; 1355 int s; 1356 1357 if (sc == NULL) 1358 return; 1359 1360 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname, 1361 __func__)); 1362 1363 if (sc->sc_dying) 1364 return; 1365 1366 ifp = GET_IFP(sc); 1367 mii = GET_MII(sc); 1368 1369 if (mii == NULL) 1370 return; 1371 1372 s = splnet(); 1373 1374 mii_tick(mii); 1375 if (!sc->sc_link && mii->mii_media_status & IFM_ACTIVE && 1376 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 1377 DPRINTF(("%s: %s: got link\n", 1378 sc->sc_dev.dv_xname, __func__)); 1379 sc->sc_link++; 1380 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 1381 url_start(ifp); 1382 } 1383 1384 timeout_add_sec(&sc->sc_stat_ch, 1); 1385 1386 splx(s); 1387 } 1388 1389 /* Get exclusive access to the MII registers */ 1390 void 1391 url_lock_mii(struct url_softc *sc) 1392 { 1393 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname, 1394 __func__)); 1395 1396 sc->sc_refcnt++; 1397 rw_enter_write(&sc->sc_mii_lock); 1398 } 1399 1400 void 1401 url_unlock_mii(struct url_softc *sc) 1402 { 1403 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname, 1404 __func__)); 1405 1406 rw_exit_write(&sc->sc_mii_lock); 1407 if (--sc->sc_refcnt < 0) 1408 usb_detach_wakeup(&sc->sc_dev); 1409 } 1410 1411 int 1412 url_int_miibus_readreg(struct device *dev, int phy, int reg) 1413 { 1414 struct url_softc *sc; 1415 u_int16_t val; 1416 1417 if (dev == NULL) 1418 return (0); 1419 1420 sc = (void *)dev; 1421 1422 DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n", 1423 sc->sc_dev.dv_xname, __func__, phy, reg)); 1424 1425 if (sc->sc_dying) { 1426 #ifdef DIAGNOSTIC 1427 printf("%s: %s: dying\n", sc->sc_dev.dv_xname, 1428 __func__); 1429 #endif 1430 return (0); 1431 } 1432 1433 /* XXX: one PHY only for the RTL8150 internal PHY */ 1434 if (phy != 0) { 1435 DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", 1436 sc->sc_dev.dv_xname, __func__, phy)); 1437 return (0); 1438 } 1439 1440 url_lock_mii(sc); 1441 1442 switch (reg) { 1443 case MII_BMCR: /* Control Register */ 1444 reg = URL_BMCR; 1445 break; 1446 case MII_BMSR: /* Status Register */ 1447 reg = URL_BMSR; 1448 break; 1449 case MII_PHYIDR1: 1450 case MII_PHYIDR2: 1451 val = 0; 1452 goto R_DONE; 1453 break; 1454 case MII_ANAR: /* Autonegotiation advertisement */ 1455 reg = URL_ANAR; 1456 break; 1457 case MII_ANLPAR: /* Autonegotiation link partner abilities */ 1458 reg = URL_ANLP; 1459 break; 1460 case URLPHY_MSR: /* Media Status Register */ 1461 reg = URL_MSR; 1462 break; 1463 default: 1464 printf("%s: %s: bad register %04x\n", 1465 sc->sc_dev.dv_xname, __func__, reg); 1466 val = 0; 1467 goto R_DONE; 1468 break; 1469 } 1470 1471 if (reg == URL_MSR) 1472 val = url_csr_read_1(sc, reg); 1473 else 1474 val = url_csr_read_2(sc, reg); 1475 1476 R_DONE: 1477 DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04x\n", 1478 sc->sc_dev.dv_xname, __func__, phy, reg, val)); 1479 1480 url_unlock_mii(sc); 1481 return (val); 1482 } 1483 1484 void 1485 url_int_miibus_writereg(struct device *dev, int phy, int reg, int data) 1486 { 1487 struct url_softc *sc; 1488 1489 if (dev == NULL) 1490 return; 1491 1492 sc = (void *)dev; 1493 1494 DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n", 1495 sc->sc_dev.dv_xname, __func__, phy, reg, data)); 1496 1497 if (sc->sc_dying) { 1498 #ifdef DIAGNOSTIC 1499 printf("%s: %s: dying\n", sc->sc_dev.dv_xname, 1500 __func__); 1501 #endif 1502 return; 1503 } 1504 1505 /* XXX: one PHY only for the RTL8150 internal PHY */ 1506 if (phy != 0) { 1507 DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", 1508 sc->sc_dev.dv_xname, __func__, phy)); 1509 return; 1510 } 1511 1512 url_lock_mii(sc); 1513 1514 switch (reg) { 1515 case MII_BMCR: /* Control Register */ 1516 reg = URL_BMCR; 1517 break; 1518 case MII_BMSR: /* Status Register */ 1519 reg = URL_BMSR; 1520 break; 1521 case MII_PHYIDR1: 1522 case MII_PHYIDR2: 1523 goto W_DONE; 1524 break; 1525 case MII_ANAR: /* Autonegotiation advertisement */ 1526 reg = URL_ANAR; 1527 break; 1528 case MII_ANLPAR: /* Autonegotiation link partner abilities */ 1529 reg = URL_ANLP; 1530 break; 1531 case URLPHY_MSR: /* Media Status Register */ 1532 reg = URL_MSR; 1533 break; 1534 default: 1535 printf("%s: %s: bad register %04x\n", 1536 sc->sc_dev.dv_xname, __func__, reg); 1537 goto W_DONE; 1538 break; 1539 } 1540 1541 if (reg == URL_MSR) 1542 url_csr_write_1(sc, reg, data); 1543 else 1544 url_csr_write_2(sc, reg, data); 1545 W_DONE: 1546 1547 url_unlock_mii(sc); 1548 return; 1549 } 1550 1551 void 1552 url_miibus_statchg(struct device *dev) 1553 { 1554 #ifdef URL_DEBUG 1555 struct url_softc *sc; 1556 1557 if (dev == NULL) 1558 return; 1559 1560 sc = (void *)dev; 1561 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1562 #endif 1563 /* Nothing to do */ 1564 } 1565 1566 #if 0 1567 /* 1568 * external PHYs support, but not test. 1569 */ 1570 int 1571 url_ext_miibus_redreg(struct device *dev, int phy, int reg) 1572 { 1573 struct url_softc *sc = (void *)dev; 1574 u_int16_t val; 1575 1576 DPRINTF(("%s: %s: enter, phy=%d reg=0x%04x\n", 1577 sc->sc_dev.dv_xname, __func__, phy, reg)); 1578 1579 if (sc->sc_dying) { 1580 #ifdef DIAGNOSTIC 1581 printf("%s: %s: dying\n", sc->sc_dev.dv_xname, 1582 __func__); 1583 #endif 1584 return (0); 1585 } 1586 1587 url_lock_mii(sc); 1588 1589 url_csr_write_1(sc, URL_PHYADD, phy & URL_PHYADD_MASK); 1590 /* 1591 * RTL8150L will initiate a MII management data transaction 1592 * if PHYCNT_OWN bit is set 1 by software. After transaction, 1593 * this bit is auto cleared by TRL8150L. 1594 */ 1595 url_csr_write_1(sc, URL_PHYCNT, 1596 (reg | URL_PHYCNT_PHYOWN) & ~URL_PHYCNT_RWCR); 1597 for (i = 0; i < URL_TIMEOUT; i++) { 1598 if ((url_csr_read_1(sc, URL_PHYCNT) & URL_PHYCNT_PHYOWN) == 0) 1599 break; 1600 } 1601 if (i == URL_TIMEOUT) { 1602 printf("%s: MII read timed out\n", sc->sc_dev.dv_xname); 1603 } 1604 1605 val = url_csr_read_2(sc, URL_PHYDAT); 1606 1607 DPRINTF(("%s: %s: phy=%d reg=0x%04x => 0x%04x\n", 1608 sc->sc_dev.dv_xname, __func__, phy, reg, val)); 1609 1610 url_unlock_mii(sc); 1611 return (val); 1612 } 1613 1614 void 1615 url_ext_miibus_writereg(struct device *dev, int phy, int reg, int data) 1616 { 1617 struct url_softc *sc = (void *)dev; 1618 1619 DPRINTF(("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n", 1620 sc->sc_dev.dv_xname, __func__, phy, reg, data)); 1621 1622 if (sc->sc_dying) { 1623 #ifdef DIAGNOSTIC 1624 printf("%s: %s: dying\n", sc->sc_dev.dv_xname, 1625 __func__); 1626 #endif 1627 return; 1628 } 1629 1630 url_lock_mii(sc); 1631 1632 url_csr_write_2(sc, URL_PHYDAT, data); 1633 url_csr_write_1(sc, URL_PHYADD, phy); 1634 url_csr_write_1(sc, URL_PHYCNT, reg | URL_PHYCNT_RWCR); /* Write */ 1635 1636 for (i=0; i < URL_TIMEOUT; i++) { 1637 if (url_csr_read_1(sc, URL_PHYCNT) & URL_PHYCNT_PHYOWN) 1638 break; 1639 } 1640 1641 if (i == URL_TIMEOUT) { 1642 printf("%s: MII write timed out\n", 1643 sc->sc_dev.dv_xname); 1644 } 1645 1646 url_unlock_mii(sc); 1647 return; 1648 } 1649 #endif 1650 1651