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