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