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