1 /* $OpenBSD: if_url.c,v 1.54 2008/11/28 02:44:18 brad 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 ifp->if_capabilities = IFCAP_VLAN_MTU; 286 287 /* 288 * Do ifmedia setup. 289 */ 290 mii = &sc->sc_mii; 291 mii->mii_ifp = ifp; 292 mii->mii_readreg = url_int_miibus_readreg; 293 mii->mii_writereg = url_int_miibus_writereg; 294 #if 0 295 if (sc->sc_flags & URL_EXT_PHY) { 296 mii->mii_readreg = url_ext_miibus_readreg; 297 mii->mii_writereg = url_ext_miibus_writereg; 298 } 299 #endif 300 mii->mii_statchg = url_miibus_statchg; 301 mii->mii_flags = MIIF_AUTOTSLEEP; 302 ifmedia_init(&mii->mii_media, 0, 303 url_ifmedia_change, url_ifmedia_status); 304 mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); 305 if (LIST_FIRST(&mii->mii_phys) == NULL) { 306 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); 307 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); 308 } else 309 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 310 311 /* attach the interface */ 312 if_attach(ifp); 313 ether_ifattach(ifp); 314 315 timeout_set(&sc->sc_stat_ch, url_tick, sc); 316 sc->sc_attached = 1; 317 splx(s); 318 319 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, &sc->sc_dev); 320 321 return; 322 323 bad: 324 sc->sc_dying = 1; 325 } 326 327 /* detach */ 328 int 329 url_detach(struct device *self, int flags) 330 { 331 struct url_softc *sc = (struct url_softc *)self; 332 struct ifnet *ifp = GET_IFP(sc); 333 int s; 334 335 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 336 337 /* Detached before attached finished */ 338 if (!sc->sc_attached) 339 return (0); 340 341 timeout_del(&sc->sc_stat_ch); 342 343 /* Remove any pending tasks */ 344 usb_rem_task(sc->sc_udev, &sc->sc_tick_task); 345 usb_rem_task(sc->sc_udev, &sc->sc_stop_task); 346 347 s = splusb(); 348 349 if (--sc->sc_refcnt >= 0) { 350 /* Wait for processes to go away */ 351 usb_detach_wait(&sc->sc_dev); 352 } 353 354 if (ifp->if_flags & IFF_RUNNING) 355 url_stop(GET_IFP(sc), 1); 356 357 mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); 358 ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY); 359 ether_ifdetach(ifp); 360 if_detach(ifp); 361 362 #ifdef DIAGNOSTIC 363 if (sc->sc_pipe_tx != NULL) 364 printf("%s: detach has active tx endpoint.\n", 365 sc->sc_dev.dv_xname); 366 if (sc->sc_pipe_rx != NULL) 367 printf("%s: detach has active rx endpoint.\n", 368 sc->sc_dev.dv_xname); 369 if (sc->sc_pipe_intr != NULL) 370 printf("%s: detach has active intr endpoint.\n", 371 sc->sc_dev.dv_xname); 372 #endif 373 374 sc->sc_attached = 0; 375 376 splx(s); 377 378 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 379 &sc->sc_dev); 380 381 return (0); 382 } 383 384 /* read/write memory */ 385 int 386 url_mem(struct url_softc *sc, int cmd, int offset, void *buf, int len) 387 { 388 usb_device_request_t req; 389 usbd_status err; 390 391 if (sc == NULL) 392 return (0); 393 394 DPRINTFN(0x200, 395 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 396 397 if (sc->sc_dying) 398 return (0); 399 400 if (cmd == URL_CMD_READMEM) 401 req.bmRequestType = UT_READ_VENDOR_DEVICE; 402 else 403 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 404 req.bRequest = URL_REQ_MEM; 405 USETW(req.wValue, offset); 406 USETW(req.wIndex, 0x0000); 407 USETW(req.wLength, len); 408 409 sc->sc_refcnt++; 410 err = usbd_do_request(sc->sc_udev, &req, buf); 411 if (--sc->sc_refcnt < 0) 412 usb_detach_wakeup(&sc->sc_dev); 413 if (err) { 414 DPRINTF(("%s: url_mem(): %s failed. off=%04x, err=%d\n", 415 sc->sc_dev.dv_xname, 416 cmd == URL_CMD_READMEM ? "read" : "write", 417 offset, err)); 418 } 419 420 return (err); 421 } 422 423 /* read 1byte from register */ 424 int 425 url_csr_read_1(struct url_softc *sc, int reg) 426 { 427 u_int8_t val = 0; 428 429 DPRINTFN(0x100, 430 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 431 432 if (sc->sc_dying) 433 return (0); 434 435 return (url_mem(sc, URL_CMD_READMEM, reg, &val, 1) ? 0 : val); 436 } 437 438 /* read 2bytes from register */ 439 int 440 url_csr_read_2(struct url_softc *sc, int reg) 441 { 442 uWord val; 443 444 DPRINTFN(0x100, 445 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 446 447 if (sc->sc_dying) 448 return (0); 449 450 USETW(val, 0); 451 return (url_mem(sc, URL_CMD_READMEM, reg, &val, 2) ? 0 : UGETW(val)); 452 } 453 454 /* write 1byte to register */ 455 int 456 url_csr_write_1(struct url_softc *sc, int reg, int aval) 457 { 458 u_int8_t val = aval; 459 460 DPRINTFN(0x100, 461 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 462 463 if (sc->sc_dying) 464 return (0); 465 466 return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 1) ? -1 : 0); 467 } 468 469 /* write 2bytes to register */ 470 int 471 url_csr_write_2(struct url_softc *sc, int reg, int aval) 472 { 473 uWord val; 474 475 DPRINTFN(0x100, 476 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 477 478 USETW(val, aval); 479 480 if (sc->sc_dying) 481 return (0); 482 483 return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 2) ? -1 : 0); 484 } 485 486 /* write 4bytes to register */ 487 int 488 url_csr_write_4(struct url_softc *sc, int reg, int aval) 489 { 490 uDWord val; 491 492 DPRINTFN(0x100, 493 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 494 495 USETDW(val, aval); 496 497 if (sc->sc_dying) 498 return (0); 499 500 return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 4) ? -1 : 0); 501 } 502 503 int 504 url_init(struct ifnet *ifp) 505 { 506 struct url_softc *sc = ifp->if_softc; 507 struct mii_data *mii = GET_MII(sc); 508 u_char *eaddr; 509 int i, s; 510 511 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 512 513 if (sc->sc_dying) 514 return (EIO); 515 516 s = splnet(); 517 518 /* Cancel pending I/O and free all TX/RX buffers */ 519 url_stop(ifp, 1); 520 521 eaddr = sc->sc_ac.ac_enaddr; 522 for (i = 0; i < ETHER_ADDR_LEN; i++) 523 url_csr_write_1(sc, URL_IDR0 + i, eaddr[i]); 524 525 /* Init transmission control register */ 526 URL_CLRBIT(sc, URL_TCR, 527 URL_TCR_TXRR1 | URL_TCR_TXRR0 | 528 URL_TCR_IFG1 | URL_TCR_IFG0 | 529 URL_TCR_NOCRC); 530 531 /* Init receive control register */ 532 URL_SETBIT2(sc, URL_RCR, URL_RCR_TAIL | URL_RCR_AD); 533 if (ifp->if_flags & IFF_BROADCAST) 534 URL_SETBIT2(sc, URL_RCR, URL_RCR_AB); 535 else 536 URL_CLRBIT2(sc, URL_RCR, URL_RCR_AB); 537 538 /* If we want promiscuous mode, accept all physical frames. */ 539 if (ifp->if_flags & IFF_PROMISC) 540 URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); 541 else 542 URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); 543 544 545 /* Initialize transmit ring */ 546 if (url_tx_list_init(sc) == ENOBUFS) { 547 printf("%s: tx list init failed\n", sc->sc_dev.dv_xname); 548 splx(s); 549 return (EIO); 550 } 551 552 /* Initialize receive ring */ 553 if (url_rx_list_init(sc) == ENOBUFS) { 554 printf("%s: rx list init failed\n", sc->sc_dev.dv_xname); 555 splx(s); 556 return (EIO); 557 } 558 559 /* Load the multicast filter */ 560 url_setmulti(sc); 561 562 /* Enable RX and TX */ 563 URL_SETBIT(sc, URL_CR, URL_CR_TE | URL_CR_RE); 564 565 mii_mediachg(mii); 566 567 if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) { 568 if (url_openpipes(sc)) { 569 splx(s); 570 return (EIO); 571 } 572 } 573 574 ifp->if_flags |= IFF_RUNNING; 575 ifp->if_flags &= ~IFF_OACTIVE; 576 577 splx(s); 578 579 timeout_add_sec(&sc->sc_stat_ch, 1); 580 581 return (0); 582 } 583 584 void 585 url_reset(struct url_softc *sc) 586 { 587 int i; 588 589 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 590 591 if (sc->sc_dying) 592 return; 593 594 URL_SETBIT(sc, URL_CR, URL_CR_SOFT_RST); 595 596 for (i = 0; i < URL_TX_TIMEOUT; i++) { 597 if (!(url_csr_read_1(sc, URL_CR) & URL_CR_SOFT_RST)) 598 break; 599 delay(10); /* XXX */ 600 } 601 602 delay(10000); /* XXX */ 603 } 604 605 int 606 url_activate(struct device *self, enum devact act) 607 { 608 struct url_softc *sc = (struct url_softc *)self; 609 610 DPRINTF(("%s: %s: enter, act=%d\n", sc->sc_dev.dv_xname, 611 __func__, act)); 612 613 switch (act) { 614 case DVACT_ACTIVATE: 615 break; 616 617 case DVACT_DEACTIVATE: 618 sc->sc_dying = 1; 619 break; 620 } 621 622 return (0); 623 } 624 625 #define url_calchash(addr) (ether_crc32_be((addr), ETHER_ADDR_LEN) >> 26) 626 627 628 void 629 url_setmulti(struct url_softc *sc) 630 { 631 struct ifnet *ifp; 632 struct ether_multi *enm; 633 struct ether_multistep step; 634 u_int32_t hashes[2] = { 0, 0 }; 635 int h = 0; 636 int mcnt = 0; 637 638 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 639 640 if (sc->sc_dying) 641 return; 642 643 ifp = GET_IFP(sc); 644 645 if (ifp->if_flags & IFF_PROMISC) { 646 URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); 647 return; 648 } else if (ifp->if_flags & IFF_ALLMULTI) { 649 allmulti: 650 ifp->if_flags |= IFF_ALLMULTI; 651 URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM); 652 URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAP); 653 return; 654 } 655 656 /* first, zot all the existing hash bits */ 657 url_csr_write_4(sc, URL_MAR0, 0); 658 url_csr_write_4(sc, URL_MAR4, 0); 659 660 /* now program new ones */ 661 ETHER_FIRST_MULTI(step, &sc->sc_ac, enm); 662 while (enm != NULL) { 663 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 664 ETHER_ADDR_LEN) != 0) 665 goto allmulti; 666 667 h = url_calchash(enm->enm_addrlo); 668 if (h < 32) 669 hashes[0] |= (1 << h); 670 else 671 hashes[1] |= (1 << (h -32)); 672 mcnt++; 673 ETHER_NEXT_MULTI(step, enm); 674 } 675 676 ifp->if_flags &= ~IFF_ALLMULTI; 677 678 URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); 679 680 if (mcnt){ 681 URL_SETBIT2(sc, URL_RCR, URL_RCR_AM); 682 } else { 683 URL_CLRBIT2(sc, URL_RCR, URL_RCR_AM); 684 } 685 url_csr_write_4(sc, URL_MAR0, hashes[0]); 686 url_csr_write_4(sc, URL_MAR4, hashes[1]); 687 } 688 689 int 690 url_openpipes(struct url_softc *sc) 691 { 692 struct url_chain *c; 693 usbd_status err; 694 int i; 695 int error = 0; 696 697 if (sc->sc_dying) 698 return (EIO); 699 700 sc->sc_refcnt++; 701 702 /* Open RX pipe */ 703 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no, 704 USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx); 705 if (err) { 706 printf("%s: open rx pipe failed: %s\n", 707 sc->sc_dev.dv_xname, usbd_errstr(err)); 708 error = EIO; 709 goto done; 710 } 711 712 /* Open TX pipe */ 713 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no, 714 USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx); 715 if (err) { 716 printf("%s: open tx pipe failed: %s\n", 717 sc->sc_dev.dv_xname, usbd_errstr(err)); 718 error = EIO; 719 goto done; 720 } 721 722 #if 0 723 /* XXX: interrupt endpoint is not yet supported */ 724 /* Open Interrupt pipe */ 725 err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no, 726 USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc, 727 &sc->sc_cdata.url_ibuf, URL_INTR_PKGLEN, 728 url_intr, URL_INTR_INTERVAL); 729 if (err) { 730 printf("%s: open intr pipe failed: %s\n", 731 sc->sc_dev.dv_xname, usbd_errstr(err)); 732 error = EIO; 733 goto done; 734 } 735 #endif 736 737 738 /* Start up the receive pipe. */ 739 for (i = 0; i < URL_RX_LIST_CNT; i++) { 740 c = &sc->sc_cdata.url_rx_chain[i]; 741 usbd_setup_xfer(c->url_xfer, sc->sc_pipe_rx, 742 c, c->url_buf, URL_BUFSZ, 743 USBD_SHORT_XFER_OK | USBD_NO_COPY, 744 USBD_NO_TIMEOUT, url_rxeof); 745 (void)usbd_transfer(c->url_xfer); 746 DPRINTF(("%s: %s: start read\n", sc->sc_dev.dv_xname, 747 __func__)); 748 } 749 750 done: 751 if (--sc->sc_refcnt < 0) 752 usb_detach_wakeup(&sc->sc_dev); 753 754 return (error); 755 } 756 757 int 758 url_newbuf(struct url_softc *sc, struct url_chain *c, struct mbuf *m) 759 { 760 struct mbuf *m_new = NULL; 761 762 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 763 764 if (m == NULL) { 765 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 766 if (m_new == NULL) { 767 printf("%s: no memory for rx list " 768 "-- packet dropped!\n", sc->sc_dev.dv_xname); 769 return (ENOBUFS); 770 } 771 MCLGET(m_new, M_DONTWAIT); 772 if (!(m_new->m_flags & M_EXT)) { 773 printf("%s: no memory for rx list " 774 "-- packet dropped!\n", sc->sc_dev.dv_xname); 775 m_freem(m_new); 776 return (ENOBUFS); 777 } 778 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 779 } else { 780 m_new = m; 781 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 782 m_new->m_data = m_new->m_ext.ext_buf; 783 } 784 785 m_adj(m_new, ETHER_ALIGN); 786 c->url_mbuf = m_new; 787 788 return (0); 789 } 790 791 792 int 793 url_rx_list_init(struct url_softc *sc) 794 { 795 struct url_cdata *cd; 796 struct url_chain *c; 797 int i; 798 799 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 800 801 cd = &sc->sc_cdata; 802 for (i = 0; i < URL_RX_LIST_CNT; i++) { 803 c = &cd->url_rx_chain[i]; 804 c->url_sc = sc; 805 c->url_idx = i; 806 if (url_newbuf(sc, c, NULL) == ENOBUFS) 807 return (ENOBUFS); 808 if (c->url_xfer == NULL) { 809 c->url_xfer = usbd_alloc_xfer(sc->sc_udev); 810 if (c->url_xfer == NULL) 811 return (ENOBUFS); 812 c->url_buf = usbd_alloc_buffer(c->url_xfer, URL_BUFSZ); 813 if (c->url_buf == NULL) { 814 usbd_free_xfer(c->url_xfer); 815 return (ENOBUFS); 816 } 817 } 818 } 819 820 return (0); 821 } 822 823 int 824 url_tx_list_init(struct url_softc *sc) 825 { 826 struct url_cdata *cd; 827 struct url_chain *c; 828 int i; 829 830 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 831 832 cd = &sc->sc_cdata; 833 for (i = 0; i < URL_TX_LIST_CNT; i++) { 834 c = &cd->url_tx_chain[i]; 835 c->url_sc = sc; 836 c->url_idx = i; 837 c->url_mbuf = NULL; 838 if (c->url_xfer == NULL) { 839 c->url_xfer = usbd_alloc_xfer(sc->sc_udev); 840 if (c->url_xfer == NULL) 841 return (ENOBUFS); 842 c->url_buf = usbd_alloc_buffer(c->url_xfer, URL_BUFSZ); 843 if (c->url_buf == NULL) { 844 usbd_free_xfer(c->url_xfer); 845 return (ENOBUFS); 846 } 847 } 848 } 849 850 return (0); 851 } 852 853 void 854 url_start(struct ifnet *ifp) 855 { 856 struct url_softc *sc = ifp->if_softc; 857 struct mbuf *m_head = NULL; 858 859 DPRINTF(("%s: %s: enter, link=%d\n", sc->sc_dev.dv_xname, 860 __func__, sc->sc_link)); 861 862 if (sc->sc_dying) 863 return; 864 865 if (!sc->sc_link) 866 return; 867 868 if (ifp->if_flags & IFF_OACTIVE) 869 return; 870 871 IFQ_POLL(&ifp->if_snd, m_head); 872 if (m_head == NULL) 873 return; 874 875 if (url_send(sc, m_head, 0)) { 876 ifp->if_flags |= IFF_OACTIVE; 877 return; 878 } 879 880 IFQ_DEQUEUE(&ifp->if_snd, m_head); 881 882 #if NBPFILTER > 0 883 if (ifp->if_bpf) 884 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); 885 #endif 886 887 ifp->if_flags |= IFF_OACTIVE; 888 889 /* Set a timeout in case the chip goes out to lunch. */ 890 ifp->if_timer = 5; 891 } 892 893 int 894 url_send(struct url_softc *sc, struct mbuf *m, int idx) 895 { 896 int total_len; 897 struct url_chain *c; 898 usbd_status err; 899 900 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 901 902 c = &sc->sc_cdata.url_tx_chain[idx]; 903 904 /* Copy the mbuf data into a contiguous buffer */ 905 m_copydata(m, 0, m->m_pkthdr.len, c->url_buf); 906 c->url_mbuf = m; 907 total_len = m->m_pkthdr.len; 908 909 if (total_len < URL_MIN_FRAME_LEN) { 910 bzero(c->url_buf + total_len, URL_MIN_FRAME_LEN - total_len); 911 total_len = URL_MIN_FRAME_LEN; 912 } 913 usbd_setup_xfer(c->url_xfer, sc->sc_pipe_tx, c, c->url_buf, total_len, 914 USBD_FORCE_SHORT_XFER | USBD_NO_COPY, 915 URL_TX_TIMEOUT, url_txeof); 916 917 /* Transmit */ 918 sc->sc_refcnt++; 919 err = usbd_transfer(c->url_xfer); 920 if (--sc->sc_refcnt < 0) 921 usb_detach_wakeup(&sc->sc_dev); 922 if (err != USBD_IN_PROGRESS) { 923 printf("%s: url_send error=%s\n", sc->sc_dev.dv_xname, 924 usbd_errstr(err)); 925 /* Stop the interface */ 926 usb_add_task(sc->sc_udev, &sc->sc_stop_task); 927 return (EIO); 928 } 929 930 DPRINTF(("%s: %s: send %d bytes\n", sc->sc_dev.dv_xname, 931 __func__, total_len)); 932 933 sc->sc_cdata.url_tx_cnt++; 934 935 return (0); 936 } 937 938 void 939 url_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 940 { 941 struct url_chain *c = priv; 942 struct url_softc *sc = c->url_sc; 943 struct ifnet *ifp = GET_IFP(sc); 944 int s; 945 946 if (sc->sc_dying) 947 return; 948 949 s = splnet(); 950 951 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 952 953 ifp->if_timer = 0; 954 ifp->if_flags &= ~IFF_OACTIVE; 955 956 if (status != USBD_NORMAL_COMPLETION) { 957 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 958 splx(s); 959 return; 960 } 961 ifp->if_oerrors++; 962 printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname, 963 usbd_errstr(status)); 964 if (status == USBD_STALLED) { 965 sc->sc_refcnt++; 966 usbd_clear_endpoint_stall_async(sc->sc_pipe_tx); 967 if (--sc->sc_refcnt < 0) 968 usb_detach_wakeup(&sc->sc_dev); 969 } 970 splx(s); 971 return; 972 } 973 974 ifp->if_opackets++; 975 976 m_freem(c->url_mbuf); 977 c->url_mbuf = NULL; 978 979 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 980 url_start(ifp); 981 982 splx(s); 983 } 984 985 void 986 url_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 987 { 988 struct url_chain *c = priv; 989 struct url_softc *sc = c->url_sc; 990 struct ifnet *ifp = GET_IFP(sc); 991 struct mbuf *m; 992 u_int32_t total_len; 993 url_rxhdr_t rxhdr; 994 int s; 995 996 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 997 998 if (sc->sc_dying) 999 return; 1000 1001 if (status != USBD_NORMAL_COMPLETION) { 1002 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 1003 return; 1004 sc->sc_rx_errs++; 1005 if (usbd_ratecheck(&sc->sc_rx_notice)) { 1006 printf("%s: %u usb errors on rx: %s\n", 1007 sc->sc_dev.dv_xname, sc->sc_rx_errs, 1008 usbd_errstr(status)); 1009 sc->sc_rx_errs = 0; 1010 } 1011 if (status == USBD_STALLED) { 1012 sc->sc_refcnt++; 1013 usbd_clear_endpoint_stall_async(sc->sc_pipe_rx); 1014 if (--sc->sc_refcnt < 0) 1015 usb_detach_wakeup(&sc->sc_dev); 1016 } 1017 goto done; 1018 } 1019 1020 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 1021 1022 memcpy(mtod(c->url_mbuf, char *), c->url_buf, total_len); 1023 1024 if (total_len <= ETHER_CRC_LEN) { 1025 ifp->if_ierrors++; 1026 goto done; 1027 } 1028 1029 memcpy(&rxhdr, c->url_buf + total_len - ETHER_CRC_LEN, sizeof(rxhdr)); 1030 1031 DPRINTF(("%s: RX Status: %dbytes%s%s%s%s packets\n", 1032 sc->sc_dev.dv_xname, 1033 UGETW(rxhdr) & URL_RXHDR_BYTEC_MASK, 1034 UGETW(rxhdr) & URL_RXHDR_VALID_MASK ? ", Valid" : "", 1035 UGETW(rxhdr) & URL_RXHDR_RUNTPKT_MASK ? ", Runt" : "", 1036 UGETW(rxhdr) & URL_RXHDR_PHYPKT_MASK ? ", Physical match" : "", 1037 UGETW(rxhdr) & URL_RXHDR_MCASTPKT_MASK ? ", Multicast" : "")); 1038 1039 if ((UGETW(rxhdr) & URL_RXHDR_VALID_MASK) == 0) { 1040 ifp->if_ierrors++; 1041 goto done; 1042 } 1043 1044 ifp->if_ipackets++; 1045 total_len -= ETHER_CRC_LEN; 1046 1047 m = c->url_mbuf; 1048 m->m_pkthdr.len = m->m_len = total_len; 1049 m->m_pkthdr.rcvif = ifp; 1050 1051 s = splnet(); 1052 1053 if (url_newbuf(sc, c, NULL) == ENOBUFS) { 1054 ifp->if_ierrors++; 1055 goto done1; 1056 } 1057 1058 #if NBPFILTER > 0 1059 if (ifp->if_bpf) 1060 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 1061 #endif 1062 1063 DPRINTF(("%s: %s: deliver %d\n", sc->sc_dev.dv_xname, 1064 __func__, m->m_len)); 1065 ether_input_mbuf(ifp, m); 1066 1067 done1: 1068 splx(s); 1069 1070 done: 1071 /* Setup new transfer */ 1072 usbd_setup_xfer(xfer, sc->sc_pipe_rx, c, c->url_buf, URL_BUFSZ, 1073 USBD_SHORT_XFER_OK | USBD_NO_COPY, 1074 USBD_NO_TIMEOUT, url_rxeof); 1075 sc->sc_refcnt++; 1076 usbd_transfer(xfer); 1077 if (--sc->sc_refcnt < 0) 1078 usb_detach_wakeup(&sc->sc_dev); 1079 1080 DPRINTF(("%s: %s: start rx\n", sc->sc_dev.dv_xname, __func__)); 1081 } 1082 1083 #if 0 1084 void url_intr() 1085 { 1086 } 1087 #endif 1088 1089 int 1090 url_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1091 { 1092 struct url_softc *sc = ifp->if_softc; 1093 struct ifaddr *ifa = (struct ifaddr *)data; 1094 struct ifreq *ifr = (struct ifreq *)data; 1095 struct mii_data *mii; 1096 int s, error = 0; 1097 1098 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1099 1100 if (sc->sc_dying) 1101 return (EIO); 1102 1103 s = splnet(); 1104 1105 switch (cmd) { 1106 case SIOCSIFADDR: 1107 ifp->if_flags |= IFF_UP; 1108 url_init(ifp); 1109 1110 switch (ifa->ifa_addr->sa_family) { 1111 #ifdef INET 1112 case AF_INET: 1113 arp_ifinit(&sc->sc_ac, ifa); 1114 break; 1115 #endif /* INET */ 1116 } 1117 break; 1118 1119 case SIOCSIFFLAGS: 1120 if (ifp->if_flags & IFF_UP) { 1121 if (ifp->if_flags & IFF_RUNNING && 1122 ifp->if_flags & IFF_PROMISC) { 1123 URL_SETBIT2(sc, URL_RCR, 1124 URL_RCR_AAM|URL_RCR_AAP); 1125 } else if (ifp->if_flags & IFF_RUNNING && 1126 !(ifp->if_flags & IFF_PROMISC)) { 1127 URL_CLRBIT2(sc, URL_RCR, 1128 URL_RCR_AAM|URL_RCR_AAP); 1129 } else if (!(ifp->if_flags & IFF_RUNNING)) 1130 url_init(ifp); 1131 } else { 1132 if (ifp->if_flags & IFF_RUNNING) 1133 url_stop(ifp, 1); 1134 } 1135 error = 0; 1136 break; 1137 1138 case SIOCGIFMEDIA: 1139 case SIOCSIFMEDIA: 1140 mii = GET_MII(sc); 1141 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1142 break; 1143 1144 default: 1145 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); 1146 } 1147 1148 if (error == ENETRESET) { 1149 if (ifp->if_flags & IFF_RUNNING) 1150 url_setmulti(sc); 1151 error = 0; 1152 } 1153 1154 splx(s); 1155 return (error); 1156 } 1157 1158 void 1159 url_watchdog(struct ifnet *ifp) 1160 { 1161 struct url_softc *sc = ifp->if_softc; 1162 struct url_chain *c; 1163 usbd_status stat; 1164 int s; 1165 1166 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1167 1168 ifp->if_oerrors++; 1169 printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname); 1170 1171 s = splusb(); 1172 c = &sc->sc_cdata.url_tx_chain[0]; 1173 usbd_get_xfer_status(c->url_xfer, NULL, NULL, NULL, &stat); 1174 url_txeof(c->url_xfer, c, stat); 1175 1176 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 1177 url_start(ifp); 1178 splx(s); 1179 } 1180 1181 void 1182 url_stop_task(struct url_softc *sc) 1183 { 1184 url_stop(GET_IFP(sc), 1); 1185 } 1186 1187 /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ 1188 void 1189 url_stop(struct ifnet *ifp, int disable) 1190 { 1191 struct url_softc *sc = ifp->if_softc; 1192 usbd_status err; 1193 int i; 1194 1195 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1196 1197 ifp->if_timer = 0; 1198 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 1199 1200 url_reset(sc); 1201 1202 timeout_del(&sc->sc_stat_ch); 1203 1204 /* Stop transfers */ 1205 /* RX endpoint */ 1206 if (sc->sc_pipe_rx != NULL) { 1207 err = usbd_abort_pipe(sc->sc_pipe_rx); 1208 if (err) 1209 printf("%s: abort rx pipe failed: %s\n", 1210 sc->sc_dev.dv_xname, usbd_errstr(err)); 1211 err = usbd_close_pipe(sc->sc_pipe_rx); 1212 if (err) 1213 printf("%s: close rx pipe failed: %s\n", 1214 sc->sc_dev.dv_xname, usbd_errstr(err)); 1215 sc->sc_pipe_rx = NULL; 1216 } 1217 1218 /* TX endpoint */ 1219 if (sc->sc_pipe_tx != NULL) { 1220 err = usbd_abort_pipe(sc->sc_pipe_tx); 1221 if (err) 1222 printf("%s: abort tx pipe failed: %s\n", 1223 sc->sc_dev.dv_xname, usbd_errstr(err)); 1224 err = usbd_close_pipe(sc->sc_pipe_tx); 1225 if (err) 1226 printf("%s: close tx pipe failed: %s\n", 1227 sc->sc_dev.dv_xname, usbd_errstr(err)); 1228 sc->sc_pipe_tx = NULL; 1229 } 1230 1231 #if 0 1232 /* XXX: Interrupt endpoint is not yet supported!! */ 1233 /* Interrupt endpoint */ 1234 if (sc->sc_pipe_intr != NULL) { 1235 err = usbd_abort_pipe(sc->sc_pipe_intr); 1236 if (err) 1237 printf("%s: abort intr pipe failed: %s\n", 1238 sc->sc_dev.dv_xname, usbd_errstr(err)); 1239 err = usbd_close_pipe(sc->sc_pipe_intr); 1240 if (err) 1241 printf("%s: close intr pipe failed: %s\n", 1242 sc->sc_dev.dv_xname, usbd_errstr(err)); 1243 sc->sc_pipe_intr = NULL; 1244 } 1245 #endif 1246 1247 /* Free RX resources. */ 1248 for (i = 0; i < URL_RX_LIST_CNT; i++) { 1249 if (sc->sc_cdata.url_rx_chain[i].url_mbuf != NULL) { 1250 m_freem(sc->sc_cdata.url_rx_chain[i].url_mbuf); 1251 sc->sc_cdata.url_rx_chain[i].url_mbuf = NULL; 1252 } 1253 if (sc->sc_cdata.url_rx_chain[i].url_xfer != NULL) { 1254 usbd_free_xfer(sc->sc_cdata.url_rx_chain[i].url_xfer); 1255 sc->sc_cdata.url_rx_chain[i].url_xfer = NULL; 1256 } 1257 } 1258 1259 /* Free TX resources. */ 1260 for (i = 0; i < URL_TX_LIST_CNT; i++) { 1261 if (sc->sc_cdata.url_tx_chain[i].url_mbuf != NULL) { 1262 m_freem(sc->sc_cdata.url_tx_chain[i].url_mbuf); 1263 sc->sc_cdata.url_tx_chain[i].url_mbuf = NULL; 1264 } 1265 if (sc->sc_cdata.url_tx_chain[i].url_xfer != NULL) { 1266 usbd_free_xfer(sc->sc_cdata.url_tx_chain[i].url_xfer); 1267 sc->sc_cdata.url_tx_chain[i].url_xfer = NULL; 1268 } 1269 } 1270 1271 sc->sc_link = 0; 1272 } 1273 1274 /* Set media options */ 1275 int 1276 url_ifmedia_change(struct ifnet *ifp) 1277 { 1278 struct url_softc *sc = ifp->if_softc; 1279 struct mii_data *mii = GET_MII(sc); 1280 1281 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1282 1283 if (sc->sc_dying) 1284 return (0); 1285 1286 sc->sc_link = 0; 1287 if (mii->mii_instance) { 1288 struct mii_softc *miisc; 1289 for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL; 1290 miisc = LIST_NEXT(miisc, mii_list)) 1291 mii_phy_reset(miisc); 1292 } 1293 1294 return (mii_mediachg(mii)); 1295 } 1296 1297 /* Report current media status. */ 1298 void 1299 url_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr) 1300 { 1301 struct url_softc *sc = ifp->if_softc; 1302 struct mii_data *mii = GET_MII(sc); 1303 1304 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1305 1306 if (sc->sc_dying) 1307 return; 1308 1309 if ((ifp->if_flags & IFF_RUNNING) == 0) { 1310 ifmr->ifm_active = IFM_ETHER | IFM_NONE; 1311 ifmr->ifm_status = 0; 1312 return; 1313 } 1314 1315 mii_pollstat(mii); 1316 ifmr->ifm_active = mii->mii_media_active; 1317 ifmr->ifm_status = mii->mii_media_status; 1318 } 1319 1320 void 1321 url_tick(void *xsc) 1322 { 1323 struct url_softc *sc = xsc; 1324 1325 if (sc == NULL) 1326 return; 1327 1328 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname, 1329 __func__)); 1330 1331 if (sc->sc_dying) 1332 return; 1333 1334 /* Perform periodic stuff in process context */ 1335 usb_add_task(sc->sc_udev, &sc->sc_tick_task); 1336 } 1337 1338 void 1339 url_tick_task(void *xsc) 1340 { 1341 struct url_softc *sc = xsc; 1342 struct ifnet *ifp; 1343 struct mii_data *mii; 1344 int s; 1345 1346 if (sc == NULL) 1347 return; 1348 1349 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname, 1350 __func__)); 1351 1352 if (sc->sc_dying) 1353 return; 1354 1355 ifp = GET_IFP(sc); 1356 mii = GET_MII(sc); 1357 1358 if (mii == NULL) 1359 return; 1360 1361 s = splnet(); 1362 1363 mii_tick(mii); 1364 if (!sc->sc_link && mii->mii_media_status & IFM_ACTIVE && 1365 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 1366 DPRINTF(("%s: %s: got link\n", 1367 sc->sc_dev.dv_xname, __func__)); 1368 sc->sc_link++; 1369 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 1370 url_start(ifp); 1371 } 1372 1373 timeout_add_sec(&sc->sc_stat_ch, 1); 1374 1375 splx(s); 1376 } 1377 1378 /* Get exclusive access to the MII registers */ 1379 void 1380 url_lock_mii(struct url_softc *sc) 1381 { 1382 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname, 1383 __func__)); 1384 1385 sc->sc_refcnt++; 1386 rw_enter_write(&sc->sc_mii_lock); 1387 } 1388 1389 void 1390 url_unlock_mii(struct url_softc *sc) 1391 { 1392 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname, 1393 __func__)); 1394 1395 rw_exit_write(&sc->sc_mii_lock); 1396 if (--sc->sc_refcnt < 0) 1397 usb_detach_wakeup(&sc->sc_dev); 1398 } 1399 1400 int 1401 url_int_miibus_readreg(struct device *dev, int phy, int reg) 1402 { 1403 struct url_softc *sc; 1404 u_int16_t val; 1405 1406 if (dev == NULL) 1407 return (0); 1408 1409 sc = (void *)dev; 1410 1411 DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n", 1412 sc->sc_dev.dv_xname, __func__, phy, reg)); 1413 1414 if (sc->sc_dying) { 1415 #ifdef DIAGNOSTIC 1416 printf("%s: %s: dying\n", sc->sc_dev.dv_xname, 1417 __func__); 1418 #endif 1419 return (0); 1420 } 1421 1422 /* XXX: one PHY only for the RTL8150 internal PHY */ 1423 if (phy != 0) { 1424 DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", 1425 sc->sc_dev.dv_xname, __func__, phy)); 1426 return (0); 1427 } 1428 1429 url_lock_mii(sc); 1430 1431 switch (reg) { 1432 case MII_BMCR: /* Control Register */ 1433 reg = URL_BMCR; 1434 break; 1435 case MII_BMSR: /* Status Register */ 1436 reg = URL_BMSR; 1437 break; 1438 case MII_PHYIDR1: 1439 case MII_PHYIDR2: 1440 val = 0; 1441 goto R_DONE; 1442 break; 1443 case MII_ANAR: /* Autonegotiation advertisement */ 1444 reg = URL_ANAR; 1445 break; 1446 case MII_ANLPAR: /* Autonegotiation link partner abilities */ 1447 reg = URL_ANLP; 1448 break; 1449 case URLPHY_MSR: /* Media Status Register */ 1450 reg = URL_MSR; 1451 break; 1452 default: 1453 printf("%s: %s: bad register %04x\n", 1454 sc->sc_dev.dv_xname, __func__, reg); 1455 val = 0; 1456 goto R_DONE; 1457 break; 1458 } 1459 1460 if (reg == URL_MSR) 1461 val = url_csr_read_1(sc, reg); 1462 else 1463 val = url_csr_read_2(sc, reg); 1464 1465 R_DONE: 1466 DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04x\n", 1467 sc->sc_dev.dv_xname, __func__, phy, reg, val)); 1468 1469 url_unlock_mii(sc); 1470 return (val); 1471 } 1472 1473 void 1474 url_int_miibus_writereg(struct device *dev, int phy, int reg, int data) 1475 { 1476 struct url_softc *sc; 1477 1478 if (dev == NULL) 1479 return; 1480 1481 sc = (void *)dev; 1482 1483 DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n", 1484 sc->sc_dev.dv_xname, __func__, phy, reg, data)); 1485 1486 if (sc->sc_dying) { 1487 #ifdef DIAGNOSTIC 1488 printf("%s: %s: dying\n", sc->sc_dev.dv_xname, 1489 __func__); 1490 #endif 1491 return; 1492 } 1493 1494 /* XXX: one PHY only for the RTL8150 internal PHY */ 1495 if (phy != 0) { 1496 DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", 1497 sc->sc_dev.dv_xname, __func__, phy)); 1498 return; 1499 } 1500 1501 url_lock_mii(sc); 1502 1503 switch (reg) { 1504 case MII_BMCR: /* Control Register */ 1505 reg = URL_BMCR; 1506 break; 1507 case MII_BMSR: /* Status Register */ 1508 reg = URL_BMSR; 1509 break; 1510 case MII_PHYIDR1: 1511 case MII_PHYIDR2: 1512 goto W_DONE; 1513 break; 1514 case MII_ANAR: /* Autonegotiation advertisement */ 1515 reg = URL_ANAR; 1516 break; 1517 case MII_ANLPAR: /* Autonegotiation link partner abilities */ 1518 reg = URL_ANLP; 1519 break; 1520 case URLPHY_MSR: /* Media Status Register */ 1521 reg = URL_MSR; 1522 break; 1523 default: 1524 printf("%s: %s: bad register %04x\n", 1525 sc->sc_dev.dv_xname, __func__, reg); 1526 goto W_DONE; 1527 break; 1528 } 1529 1530 if (reg == URL_MSR) 1531 url_csr_write_1(sc, reg, data); 1532 else 1533 url_csr_write_2(sc, reg, data); 1534 W_DONE: 1535 1536 url_unlock_mii(sc); 1537 return; 1538 } 1539 1540 void 1541 url_miibus_statchg(struct device *dev) 1542 { 1543 #ifdef URL_DEBUG 1544 struct url_softc *sc; 1545 1546 if (dev == NULL) 1547 return; 1548 1549 sc = (void *)dev; 1550 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 1551 #endif 1552 /* Nothing to do */ 1553 } 1554 1555 #if 0 1556 /* 1557 * external PHYs support, but not test. 1558 */ 1559 int 1560 url_ext_miibus_redreg(struct device *dev, int phy, int reg) 1561 { 1562 struct url_softc *sc = (void *)dev; 1563 u_int16_t val; 1564 1565 DPRINTF(("%s: %s: enter, phy=%d reg=0x%04x\n", 1566 sc->sc_dev.dv_xname, __func__, phy, reg)); 1567 1568 if (sc->sc_dying) { 1569 #ifdef DIAGNOSTIC 1570 printf("%s: %s: dying\n", sc->sc_dev.dv_xname, 1571 __func__); 1572 #endif 1573 return (0); 1574 } 1575 1576 url_lock_mii(sc); 1577 1578 url_csr_write_1(sc, URL_PHYADD, phy & URL_PHYADD_MASK); 1579 /* 1580 * RTL8150L will initiate a MII management data transaction 1581 * if PHYCNT_OWN bit is set 1 by software. After transaction, 1582 * this bit is auto cleared by TRL8150L. 1583 */ 1584 url_csr_write_1(sc, URL_PHYCNT, 1585 (reg | URL_PHYCNT_PHYOWN) & ~URL_PHYCNT_RWCR); 1586 for (i = 0; i < URL_TIMEOUT; i++) { 1587 if ((url_csr_read_1(sc, URL_PHYCNT) & URL_PHYCNT_PHYOWN) == 0) 1588 break; 1589 } 1590 if (i == URL_TIMEOUT) { 1591 printf("%s: MII read timed out\n", sc->sc_dev.dv_xname); 1592 } 1593 1594 val = url_csr_read_2(sc, URL_PHYDAT); 1595 1596 DPRINTF(("%s: %s: phy=%d reg=0x%04x => 0x%04x\n", 1597 sc->sc_dev.dv_xname, __func__, phy, reg, val)); 1598 1599 url_unlock_mii(sc); 1600 return (val); 1601 } 1602 1603 void 1604 url_ext_miibus_writereg(struct device *dev, int phy, int reg, int data) 1605 { 1606 struct url_softc *sc = (void *)dev; 1607 1608 DPRINTF(("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n", 1609 sc->sc_dev.dv_xname, __func__, phy, reg, data)); 1610 1611 if (sc->sc_dying) { 1612 #ifdef DIAGNOSTIC 1613 printf("%s: %s: dying\n", sc->sc_dev.dv_xname, 1614 __func__); 1615 #endif 1616 return; 1617 } 1618 1619 url_lock_mii(sc); 1620 1621 url_csr_write_2(sc, URL_PHYDAT, data); 1622 url_csr_write_1(sc, URL_PHYADD, phy); 1623 url_csr_write_1(sc, URL_PHYCNT, reg | URL_PHYCNT_RWCR); /* Write */ 1624 1625 for (i=0; i < URL_TIMEOUT; i++) { 1626 if (url_csr_read_1(sc, URL_PHYCNT) & URL_PHYCNT_PHYOWN) 1627 break; 1628 } 1629 1630 if (i == URL_TIMEOUT) { 1631 printf("%s: MII write timed out\n", 1632 sc->sc_dev.dv_xname); 1633 } 1634 1635 url_unlock_mii(sc); 1636 return; 1637 } 1638 #endif 1639 1640