The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/if_url.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 69e595721d5b67e743b312db3c98fdb7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.