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