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