root/dev/usb/if_url.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. url_match
  2. url_attach
  3. url_detach
  4. url_mem
  5. url_csr_read_1
  6. url_csr_read_2
  7. url_csr_write_1
  8. url_csr_write_2
  9. url_csr_write_4
  10. url_init
  11. url_reset
  12. url_activate
  13. url_setmulti
  14. url_openpipes
  15. url_newbuf
  16. url_rx_list_init
  17. url_tx_list_init
  18. url_start
  19. url_send
  20. url_txeof
  21. url_rxeof
  22. url_intr
  23. url_ioctl
  24. url_watchdog
  25. url_stop_task
  26. url_stop
  27. url_ifmedia_change
  28. url_ifmedia_status
  29. url_tick
  30. url_tick_task
  31. url_lock_mii
  32. url_unlock_mii
  33. url_int_miibus_readreg
  34. url_int_miibus_writereg
  35. url_miibus_statchg
  36. url_ext_miibus_redreg
  37. url_ext_miibus_writereg

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

/* [<][>][^][v][top][bottom][index][help] */