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

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

Version: -  FREEBSD  -  FREEBSD8  -  FREEBSD7  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  OPENSOLARIS  -  minix-3-1-1  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

    1 /*      $NetBSD: if_udav.c,v 1.2 2003/09/04 15:17:38 tsutsui Exp $      */
    2 /*      $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $   */
    3 /*      $FreeBSD: src/sys/dev/usb/if_udav.c,v 1.14.2.4 2006/03/17 21:30:56 glebius Exp $        */
    4 /*-
    5  * Copyright (c) 2003
    6  *     Shingo WATANABE <nabe@nabechan.org>.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  */
   33 
   34 /*
   35  * DM9601(DAVICOM USB to Ethernet MAC Controller with Integrated 10/100 PHY)
   36  * The spec can be found at the following url.
   37  *   http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf
   38  */
   39 
   40 /*
   41  * TODO:
   42  *      Interrupt Endpoint support
   43  *      External PHYs
   44  *      powerhook() support?
   45  */
   46 
   47 #include <sys/cdefs.h>
   48 __FBSDID("$FreeBSD: src/sys/dev/usb/if_udav.c,v 1.14.2.4 2006/03/17 21:30:56 glebius Exp $");
   49 
   50 #include "opt_inet.h"
   51 #if defined(__NetBSD__)
   52 #include "opt_ns.h"
   53 #endif
   54 #if defined(__NetBSD__)
   55 #include "bpfilter.h"
   56 #endif
   57 #if defined(__FreeBSD__)
   58 #define NBPFILTER       1
   59 #endif
   60 #if defined(__NetBSD__)
   61 #include "rnd.h"
   62 #endif
   63 
   64 #include <sys/param.h>
   65 #include <sys/systm.h>
   66 #include <sys/lock.h>
   67 #include <sys/mbuf.h>
   68 #include <sys/kernel.h>
   69 #include <sys/module.h>
   70 #include <sys/socket.h>
   71 #if defined(__FreeBSD__)
   72 #include <sys/types.h>
   73 #include <sys/lockmgr.h>
   74 #include <sys/sockio.h>
   75 #endif
   76 
   77 #if defined(__NetBSD__)
   78 #include <sys/device.h>
   79 #endif
   80 
   81 #if NRND > 0
   82 #include <sys/rnd.h>
   83 #endif
   84 
   85 #include <net/if.h>
   86 #include <net/if_arp.h>
   87 #include <net/if_dl.h>
   88 #include <net/if_media.h>
   89 #include <net/ethernet.h>
   90 #include <net/if_types.h>
   91 
   92 #if NBPFILTER > 0
   93 #include <net/bpf.h>
   94 #endif
   95 #if defined(__NetBSD__)
   96 #ifndef BPF_MTAP
   97 #define BPF_MTAP(_ifp, _m)      do {                    \
   98         if ((_ifp)->if_bpf)) {                          \
   99                 bpf_mtap((_ifp)->if_bpf, (_m)) ;        \
  100         }                                               \
  101 } while (0)
  102 #endif
  103 #endif
  104 
  105 #if defined(__NetBSD__)
  106 #include <net/if_ether.h>
  107 #ifdef INET
  108 #include <netinet/in.h>
  109 #include <netinet/if_inarp.h>
  110 #endif /* INET */
  111 #elif defined(__FreeBSD__) /* defined(__NetBSD__) */
  112 #include <netinet/in.h>
  113 #include <netinet/if_ether.h>
  114 #endif /* defined(__FreeBSD__) */
  115 
  116 #if defined(__NetBSD__)
  117 #ifdef NS
  118 #include <netns/ns.h>
  119 #include <netns/ns_if.h>
  120 #endif
  121 #endif /* defined (__NetBSD__) */
  122 
  123 #include <sys/bus.h>
  124 #include <machine/bus.h>
  125 #if __FreeBSD_version < 500000
  126 #include <machine/clock.h>
  127 #endif
  128 
  129 #include <dev/mii/mii.h>
  130 #include <dev/mii/miivar.h>
  131 
  132 #include <dev/usb/usb.h>
  133 #include <dev/usb/usbdi.h>
  134 #include <dev/usb/usbdi_util.h>
  135 #include "usbdevs.h"
  136 #include <dev/usb/usbdivar.h>
  137 #include <dev/usb/usb_ethersubr.h>
  138 
  139 #include <dev/usb/if_udavreg.h>
  140 
  141 #if defined(__FreeBSD__)
  142 MODULE_DEPEND(udav, usb, 1, 1, 1);
  143 MODULE_DEPEND(udav, ether, 1, 1, 1);
  144 MODULE_DEPEND(udav, miibus, 1, 1, 1);
  145 #endif
  146 
  147 /* "controller miibus0" required.  See GENERIC if you get errors here. */
  148 #include "miibus_if.h"
  149 
  150 #if !defined(__FreeBSD__)
  151 /* Function declarations */
  152 USB_DECLARE_DRIVER(udav);
  153 #endif
  154 
  155 #if defined(__FreeBSD__)
  156 Static int udav_match(device_ptr_t);
  157 Static int udav_attach(device_ptr_t);
  158 Static int udav_detach(device_ptr_t);
  159 Static void udav_shutdown(device_ptr_t);
  160 #endif
  161 
  162 Static int udav_openpipes(struct udav_softc *);
  163 Static void udav_start(struct ifnet *);
  164 Static int udav_send(struct udav_softc *, struct mbuf *, int);
  165 Static void udav_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
  166 #if defined(__FreeBSD__)
  167 Static void udav_rxstart(struct ifnet *ifp);
  168 #endif
  169 Static void udav_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
  170 Static void udav_tick(void *);
  171 Static void udav_tick_task(void *);
  172 Static int udav_ioctl(struct ifnet *, u_long, caddr_t);
  173 Static void udav_stop_task(struct udav_softc *);
  174 Static void udav_stop(struct ifnet *, int);
  175 Static void udav_watchdog(struct ifnet *);
  176 Static int udav_ifmedia_change(struct ifnet *);
  177 Static void udav_ifmedia_status(struct ifnet *, struct ifmediareq *);
  178 Static void udav_lock_mii(struct udav_softc *);
  179 Static void udav_unlock_mii(struct udav_softc *);
  180 Static int udav_miibus_readreg(device_ptr_t, int, int);
  181 Static void udav_miibus_writereg(device_ptr_t, int, int, int);
  182 Static void udav_miibus_statchg(device_ptr_t);
  183 #if defined(__NetBSD__)
  184 Static int udav_init(struct ifnet *);
  185 #elif defined(__FreeBSD__)
  186 Static void udav_init(void *);
  187 #endif
  188 Static void udav_setmulti(struct udav_softc *);
  189 Static void udav_reset(struct udav_softc *);
  190 
  191 Static int udav_csr_read(struct udav_softc *, int, void *, int);
  192 Static int udav_csr_write(struct udav_softc *, int, void *, int);
  193 Static int udav_csr_read1(struct udav_softc *, int);
  194 Static int udav_csr_write1(struct udav_softc *, int, unsigned char);
  195 
  196 #if 0
  197 Static int udav_mem_read(struct udav_softc *, int, void *, int);
  198 Static int udav_mem_write(struct udav_softc *, int, void *, int);
  199 Static int udav_mem_write1(struct udav_softc *, int, unsigned char);
  200 #endif
  201 
  202 #if defined(__FreeBSD__)
  203 Static device_method_t udav_methods[] = {
  204         /* Device interface */
  205         DEVMETHOD(device_probe,         udav_match),
  206         DEVMETHOD(device_attach,        udav_attach),
  207         DEVMETHOD(device_detach,        udav_detach),
  208         DEVMETHOD(device_shutdown,      udav_shutdown),
  209 
  210         /* bus interface */
  211         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  212         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
  213 
  214         /* MII interface */
  215         DEVMETHOD(miibus_readreg,       udav_miibus_readreg),
  216         DEVMETHOD(miibus_writereg,      udav_miibus_writereg),
  217         DEVMETHOD(miibus_statchg,       udav_miibus_statchg),
  218 
  219         { 0, 0 }
  220 };
  221 
  222 Static driver_t udav_driver = {
  223         "udav",
  224         udav_methods,
  225         sizeof(struct udav_softc)
  226 };
  227 
  228 Static devclass_t udav_devclass;
  229 
  230 DRIVER_MODULE(udav, uhub, udav_driver, udav_devclass, usbd_driver_load, 0);
  231 DRIVER_MODULE(miibus, udav, miibus_driver, miibus_devclass, 0, 0);
  232 
  233 #endif /* defined(__FreeBSD__) */
  234 
  235 /* Macros */
  236 #ifdef UDAV_DEBUG
  237 #define DPRINTF(x)      if (udavdebug) logprintf x
  238 #define DPRINTFN(n,x)   if (udavdebug >= (n)) logprintf x
  239 int udavdebug = 0;
  240 #else
  241 #define DPRINTF(x)
  242 #define DPRINTFN(n,x)
  243 #endif
  244 
  245 #define delay(d)        DELAY(d)
  246 
  247 #define UDAV_SETBIT(sc, reg, x) \
  248         udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) | (x))
  249 
  250 #define UDAV_CLRBIT(sc, reg, x) \
  251         udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) & ~(x))
  252 
  253 static const struct udav_type {
  254         struct usb_devno udav_dev;
  255         u_int16_t udav_flags;
  256 #define UDAV_EXT_PHY    0x0001
  257 } udav_devs [] = {
  258         /* Corega USB-TXC */
  259         {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXC }, 0},
  260 #if 0
  261         /* DAVICOM DM9601 Generic? */
  262         /*  XXX: The following ids was obtained from the data sheet. */
  263         {{ 0x0a46, 0x9601 }, 0},
  264 #endif
  265 };
  266 #define udav_lookup(v, p) ((const struct udav_type *)usb_lookup(udav_devs, v, p))
  267 
  268 
  269 /* Probe */
  270 USB_MATCH(udav)
  271 {
  272         USB_MATCH_START(udav, uaa);
  273 
  274         if (uaa->iface != NULL)
  275                 return (UMATCH_NONE);
  276 
  277         return (udav_lookup(uaa->vendor, uaa->product) != NULL ?
  278                 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
  279 }
  280 
  281 /* Attach */
  282 USB_ATTACH(udav)
  283 {
  284         USB_ATTACH_START(udav, sc, uaa);
  285         usbd_device_handle dev = uaa->device;
  286         usbd_interface_handle iface;
  287         usbd_status err;
  288         usb_interface_descriptor_t *id;
  289         usb_endpoint_descriptor_t *ed;
  290         char devinfo[1024];
  291         const char *devname ;
  292         struct ifnet *ifp;
  293 #if defined(__NetBSD__)
  294         struct mii_data *mii;
  295 #endif
  296         u_char eaddr[ETHER_ADDR_LEN];
  297         int i;
  298 #if defined(__NetBSD__)
  299         int s;
  300 #endif
  301 
  302         bzero(sc, sizeof(struct udav_softc));
  303 
  304         usbd_devinfo(dev, 0, devinfo);
  305         USB_ATTACH_SETUP;
  306         devname = USBDEVNAME(sc->sc_dev);
  307         printf("%s: %s\n", devname, devinfo);
  308 
  309         /* Move the device into the configured state. */
  310         err = usbd_set_config_no(dev, UDAV_CONFIG_NO, 1);
  311         if (err) {
  312                 printf("%s: setting config no failed\n", devname);
  313                 goto bad;
  314         }
  315 
  316         usb_init_task(&sc->sc_tick_task, udav_tick_task, sc);
  317         lockinit(&sc->sc_mii_lock, PZERO, "udavmii", 0, 0);
  318         usb_init_task(&sc->sc_stop_task, (void (*)(void *)) udav_stop_task, sc);
  319 
  320         /* get control interface */
  321         err = usbd_device2interface_handle(dev, UDAV_IFACE_INDEX, &iface);
  322         if (err) {
  323                 printf("%s: failed to get interface, err=%s\n", devname,
  324                        usbd_errstr(err));
  325                 goto bad;
  326         }
  327 
  328         sc->sc_udev = dev;
  329         sc->sc_ctl_iface = iface;
  330         sc->sc_flags = udav_lookup(uaa->vendor, uaa->product)->udav_flags;
  331 
  332         /* get interface descriptor */
  333         id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
  334 
  335         /* find endpoints */
  336         sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1;
  337         for (i = 0; i < id->bNumEndpoints; i++) {
  338                 ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i);
  339                 if (ed == NULL) {
  340                         printf("%s: couldn't get endpoint %d\n", devname, i);
  341                         goto bad;
  342                 }
  343                 if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
  344                     UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
  345                         sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */
  346                 else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
  347                          UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
  348                         sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */
  349                 else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT &&
  350                          UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
  351                         sc->sc_intrin_no = ed->bEndpointAddress; /* Status */
  352         }
  353 
  354         if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 ||
  355             sc->sc_intrin_no == -1) {
  356                 printf("%s: missing endpoint\n", devname);
  357                 goto bad;
  358         }
  359 
  360 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
  361         mtx_init(&sc->sc_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK,
  362             MTX_DEF | MTX_RECURSE);
  363 #endif
  364 #if defined(__NetBSD__)
  365         s = splnet();
  366 #elif defined(__FreeBSD__)
  367         UDAV_LOCK(sc);
  368 #endif
  369 
  370         /* reset the adapter */
  371         udav_reset(sc);
  372 
  373         /* Get Ethernet Address */
  374         err = udav_csr_read(sc, UDAV_PAR, (void *)eaddr, ETHER_ADDR_LEN);
  375         if (err) {
  376                 printf("%s: read MAC address failed\n", devname);
  377 #if defined(__NetBSD__)
  378                 splx(s);
  379 #elif defined(__FreeBSD__)
  380                 UDAV_UNLOCK(sc);
  381                 mtx_destroy(&sc->sc_mtx);
  382 #endif
  383                 goto bad;
  384         }
  385 
  386         /* Print Ethernet Address */
  387         printf("%s: Ethernet address %s\n", devname, ether_sprintf(eaddr));
  388 
  389         /* initialize interface infomation */
  390 #if defined(__FreeBSD__)
  391         ifp = GET_IFP(sc) = if_alloc(IFT_ETHER);
  392         if (ifp == NULL) {
  393                 printf("%s: can not if_alloc\n", devname);
  394                 UDAV_UNLOCK(sc);
  395                 mtx_destroy(&sc->sc_mtx);
  396                 goto bad;
  397         }
  398 #else
  399         ifp = GET_IFP(sc);
  400 #endif
  401         ifp->if_softc = sc;
  402         ifp->if_mtu = ETHERMTU;
  403 #if defined(__NetBSD__)
  404         strncpy(ifp->if_xname, devname, IFNAMSIZ);
  405 #elif defined(__FreeBSD__)
  406         if_initname(ifp, "udav",  device_get_unit(self));
  407 #endif
  408         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
  409             IFF_NEEDSGIANT;
  410         ifp->if_start = udav_start;
  411         ifp->if_ioctl = udav_ioctl;
  412         ifp->if_watchdog = udav_watchdog;
  413         ifp->if_init = udav_init;
  414 #if defined(__NetBSD__)
  415         ifp->if_stop = udav_stop;
  416 #endif
  417 #if defined(__FreeBSD__)
  418         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  419 #endif
  420 #if defined(__NetBSD__)
  421         IFQ_SET_READY(&ifp->if_snd);
  422 #endif
  423 
  424 
  425 #if defined(__NetBSD__)
  426         /*
  427          * Do ifmedia setup.
  428          */
  429         mii = &sc->sc_mii;
  430         mii->mii_ifp = ifp;
  431         mii->mii_readreg = udav_miibus_readreg;
  432         mii->mii_writereg = udav_miibus_writereg;
  433         mii->mii_statchg = udav_miibus_statchg;
  434         mii->mii_flags = MIIF_AUTOTSLEEP;
  435         ifmedia_init(&mii->mii_media, 0,
  436                      udav_ifmedia_change, udav_ifmedia_status);
  437         mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
  438         if (LIST_FIRST(&mii->mii_phys) == NULL) {
  439                 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
  440                 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
  441         } else
  442                 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
  443 
  444         /* attach the interface */
  445         if_attach(ifp);
  446         Ether_ifattach(ifp, eaddr);
  447 #elif defined(__FreeBSD__)
  448         if (mii_phy_probe(self, &sc->sc_miibus,
  449             udav_ifmedia_change, udav_ifmedia_status)) {
  450                 printf("%s: MII without any PHY!\n", USBDEVNAME(sc->sc_dev));
  451                 if_free(ifp);
  452                 UDAV_UNLOCK(sc);
  453                 mtx_destroy(&sc->sc_mtx);
  454                 USB_ATTACH_ERROR_RETURN;
  455         }
  456 
  457         sc->sc_qdat.ifp = ifp;
  458         sc->sc_qdat.if_rxstart = udav_rxstart;
  459 
  460         /*
  461          * Call MI attach routine.
  462          */
  463 
  464         ether_ifattach(ifp, eaddr);
  465 #endif
  466 
  467 #if NRND > 0
  468         rnd_attach_source(&sc->rnd_source, devname, RND_TYPE_NET, 0);
  469 #endif
  470 
  471         usb_callout_init(sc->sc_stat_ch);
  472 #if defined(__FreeBSD__)
  473         usb_register_netisr();
  474 #endif
  475         sc->sc_attached = 1;
  476 #if defined(__NetBSD__)
  477         splx(s);
  478 #elif defined(__FreeBSD__)
  479         UDAV_UNLOCK(sc);
  480 #endif
  481 
  482         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, USBDEV(sc->sc_dev));
  483 
  484         USB_ATTACH_SUCCESS_RETURN;
  485 
  486  bad:
  487         sc->sc_dying = 1;
  488         USB_ATTACH_ERROR_RETURN;
  489 }
  490 
  491 /* detach */
  492 USB_DETACH(udav)
  493 {
  494         USB_DETACH_START(udav, sc);
  495         struct ifnet *ifp = GET_IFP(sc);
  496 #if defined(__NetBSD__)
  497         int s;
  498 #endif
  499 
  500         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
  501 
  502         /* Detached before attached finished */
  503         if (!sc->sc_attached)
  504                 return (0);
  505 
  506         UDAV_LOCK(sc);
  507 
  508         usb_uncallout(sc->sc_stat_ch, udav_tick, sc);
  509 
  510         /* Remove any pending tasks */
  511         usb_rem_task(sc->sc_udev, &sc->sc_tick_task);
  512         usb_rem_task(sc->sc_udev, &sc->sc_stop_task);
  513 
  514 #if defined(__NetBSD__)
  515         s = splusb();
  516 #elif defined(__FreeBSD__)
  517         UDAV_LOCK(sc);
  518 #endif
  519 
  520         if (--sc->sc_refcnt >= 0) {
  521                 /* Wait for processes to go away */
  522                 usb_detach_wait(USBDEV(sc->sc_dev));
  523         }
  524 #if defined(__FreeBSD__)
  525         if (ifp->if_drv_flags & IFF_DRV_RUNNING)
  526 #else
  527         if (ifp->if_flags & IFF_RUNNING)
  528 #endif
  529                 udav_stop(GET_IFP(sc), 1);
  530 
  531 #if NRND > 0
  532         rnd_detach_source(&sc->rnd_source);
  533 #endif
  534 #if defined(__NetBSD__)
  535         mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
  536         ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
  537 #endif
  538         ether_ifdetach(ifp);
  539 #if defined(__NetBSD__)
  540         if_detach(ifp);
  541 #endif
  542 #if defined(__FreeBSD__)
  543         if_free(ifp);
  544 #endif
  545 
  546 #ifdef DIAGNOSTIC
  547         if (sc->sc_pipe_tx != NULL)
  548                 printf("%s: detach has active tx endpoint.\n",
  549                        USBDEVNAME(sc->sc_dev));
  550         if (sc->sc_pipe_rx != NULL)
  551                 printf("%s: detach has active rx endpoint.\n",
  552                        USBDEVNAME(sc->sc_dev));
  553         if (sc->sc_pipe_intr != NULL)
  554                 printf("%s: detach has active intr endpoint.\n",
  555                        USBDEVNAME(sc->sc_dev));
  556 #endif
  557         sc->sc_attached = 0;
  558 
  559 #if defined(__NetBSD__)
  560         splx(s);
  561 #elif defined(__FreeBSD__)
  562         UDAV_UNLOCK(sc);
  563 #endif
  564 
  565 #if defined(__FreeBSD__)
  566         mtx_destroy(&sc->sc_mtx);
  567 #endif
  568 
  569         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  570                            USBDEV(sc->sc_dev));
  571         return (0);
  572 }
  573 
  574 #if 0
  575 /* read memory */
  576 Static int
  577 udav_mem_read(struct udav_softc *sc, int offset, void *buf, int len)
  578 {
  579         usb_device_request_t req;
  580         usbd_status err;
  581 
  582         if (sc == NULL)
  583                 return (0);
  584 
  585         DPRINTFN(0x200,
  586                 ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
  587 
  588         if (sc->sc_dying)
  589                 return (0);
  590 
  591         offset &= 0xffff;
  592         len &= 0xff;
  593 
  594         req.bmRequestType = UT_READ_VENDOR_DEVICE;
  595         req.bRequest = UDAV_REQ_MEM_READ;
  596         USETW(req.wValue, 0x0000);
  597         USETW(req.wIndex, offset);
  598         USETW(req.wLength, len);
  599 
  600         sc->sc_refcnt++;
  601         err = usbd_do_request(sc->sc_udev, &req, buf);
  602         if (--sc->sc_refcnt < 0)
  603                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  604         if (err) {
  605                 DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
  606                          USBDEVNAME(sc->sc_dev), __func__, offset, err));
  607         }
  608 
  609         return (err);
  610 }
  611 
  612 /* write memory */
  613 Static int
  614 udav_mem_write(struct udav_softc *sc, int offset, void *buf, int len)
  615 {
  616         usb_device_request_t req;
  617         usbd_status err;
  618 
  619         if (sc == NULL)
  620                 return (0);
  621 
  622         DPRINTFN(0x200,
  623                 ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
  624 
  625         if (sc->sc_dying)
  626                 return (0);
  627 
  628         offset &= 0xffff;
  629         len &= 0xff;
  630 
  631         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  632         req.bRequest = UDAV_REQ_MEM_WRITE;
  633         USETW(req.wValue, 0x0000);
  634         USETW(req.wIndex, offset);
  635         USETW(req.wLength, len);
  636 
  637         sc->sc_refcnt++;
  638         err = usbd_do_request(sc->sc_udev, &req, buf);
  639         if (--sc->sc_refcnt < 0)
  640                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  641         if (err) {
  642                 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
  643                          USBDEVNAME(sc->sc_dev), __func__, offset, err));
  644         }
  645 
  646         return (err);
  647 }
  648 
  649 /* write memory */
  650 Static int
  651 udav_mem_write1(struct udav_softc *sc, int offset, unsigned char ch)
  652 {
  653         usb_device_request_t req;
  654         usbd_status err;
  655 
  656         if (sc == NULL)
  657                 return (0);
  658 
  659         DPRINTFN(0x200,
  660                 ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
  661 
  662         if (sc->sc_dying)
  663                 return (0);
  664 
  665         offset &= 0xffff;
  666 
  667         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  668         req.bRequest = UDAV_REQ_MEM_WRITE1;
  669         USETW(req.wValue, ch);
  670         USETW(req.wIndex, offset);
  671         USETW(req.wLength, 0x0000);
  672 
  673         sc->sc_refcnt++;
  674         err = usbd_do_request(sc->sc_udev, &req, NULL);
  675         if (--sc->sc_refcnt < 0)
  676                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  677         if (err) {
  678                 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
  679                          USBDEVNAME(sc->sc_dev), __func__, offset, err));
  680         }
  681 
  682         return (err);
  683 }
  684 #endif
  685 
  686 /* read register(s) */
  687 Static int
  688 udav_csr_read(struct udav_softc *sc, int offset, void *buf, int len)
  689 {
  690         usb_device_request_t req;
  691         usbd_status err;
  692 
  693         if (sc == NULL)
  694                 return (0);
  695 
  696         DPRINTFN(0x200,
  697                 ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
  698 
  699         if (sc->sc_dying)
  700                 return (0);
  701 
  702         offset &= 0xff;
  703         len &= 0xff;
  704 
  705         req.bmRequestType = UT_READ_VENDOR_DEVICE;
  706         req.bRequest = UDAV_REQ_REG_READ;
  707         USETW(req.wValue, 0x0000);
  708         USETW(req.wIndex, offset);
  709         USETW(req.wLength, len);
  710 
  711         sc->sc_refcnt++;
  712         err = usbd_do_request(sc->sc_udev, &req, buf);
  713         if (--sc->sc_refcnt < 0)
  714                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  715         if (err) {
  716                 DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
  717                          USBDEVNAME(sc->sc_dev), __func__, offset, err));
  718         }
  719 
  720         return (err);
  721 }
  722 
  723 /* write register(s) */
  724 Static int
  725 udav_csr_write(struct udav_softc *sc, int offset, void *buf, int len)
  726 {
  727         usb_device_request_t req;
  728         usbd_status err;
  729 
  730         if (sc == NULL)
  731                 return (0);
  732 
  733         DPRINTFN(0x200,
  734                 ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
  735 
  736         if (sc->sc_dying)
  737                 return (0);
  738 
  739         offset &= 0xff;
  740         len &= 0xff;
  741 
  742         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  743         req.bRequest = UDAV_REQ_REG_WRITE;
  744         USETW(req.wValue, 0x0000);
  745         USETW(req.wIndex, offset);
  746         USETW(req.wLength, len);
  747 
  748         sc->sc_refcnt++;
  749         err = usbd_do_request(sc->sc_udev, &req, buf);
  750         if (--sc->sc_refcnt < 0)
  751                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  752         if (err) {
  753                 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
  754                          USBDEVNAME(sc->sc_dev), __func__, offset, err));
  755         }
  756 
  757         return (err);
  758 }
  759 
  760 Static int
  761 udav_csr_read1(struct udav_softc *sc, int offset)
  762 {
  763         u_int8_t val = 0;
  764         
  765         if (sc == NULL)
  766                 return (0);
  767 
  768         DPRINTFN(0x200,
  769                 ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
  770 
  771         if (sc->sc_dying)
  772                 return (0);
  773 
  774         return (udav_csr_read(sc, offset, &val, 1) ? 0 : val);
  775 }
  776 
  777 /* write a register */
  778 Static int
  779 udav_csr_write1(struct udav_softc *sc, int offset, unsigned char ch)
  780 {
  781         usb_device_request_t req;
  782         usbd_status err;
  783 
  784         if (sc == NULL)
  785                 return (0);
  786 
  787         DPRINTFN(0x200,
  788                 ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
  789 
  790         if (sc->sc_dying)
  791                 return (0);
  792 
  793         offset &= 0xff;
  794 
  795         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  796         req.bRequest = UDAV_REQ_REG_WRITE1;
  797         USETW(req.wValue, ch);
  798         USETW(req.wIndex, offset);
  799         USETW(req.wLength, 0x0000);
  800 
  801         sc->sc_refcnt++;
  802         err = usbd_do_request(sc->sc_udev, &req, NULL);
  803         if (--sc->sc_refcnt < 0)
  804                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  805         if (err) {
  806                 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
  807                          USBDEVNAME(sc->sc_dev), __func__, offset, err));
  808         }
  809 
  810         return (err);
  811 }
  812 
  813 #if defined(__NetBSD__)
  814 Static int
  815 udav_init(struct ifnet *ifp)
  816 #elif defined(__FreeBSD__)
  817 Static void
  818 udav_init(void *xsc)
  819 #endif
  820 {
  821 #if defined(__NetBSD__)
  822         struct udav_softc *sc = ifp->if_softc;
  823 #elif defined(__FreeBSD__)
  824         struct udav_softc *sc = (struct udav_softc *)xsc;
  825         struct ifnet    *ifp = GET_IFP(sc);
  826 #endif
  827         struct mii_data *mii = GET_MII(sc);
  828         u_char *eaddr;
  829 #if defined(__NetBSD__)
  830         int s;
  831 #endif
  832 
  833         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
  834 
  835         if (sc->sc_dying)
  836 #if defined(__NetBSD__)
  837                 return (EIO);
  838 #elif defined(__FreeBSD__)
  839                 return ;
  840 #endif
  841 
  842 #if defined(__NetBSD__)
  843         s = splnet();
  844 #elif defined(__FreeBSD__)
  845         UDAV_LOCK(sc);
  846 #endif
  847 
  848         /* Cancel pending I/O and free all TX/RX buffers */
  849         udav_stop(ifp, 1);
  850 
  851 #if defined(__NetBSD__)
  852         eaddr = LLADDR(ifp->if_sadl);
  853 #elif defined(__FreeBSD__)
  854         eaddr = IFP2ENADDR(ifp);
  855 #endif
  856         udav_csr_write(sc, UDAV_PAR, eaddr, ETHER_ADDR_LEN);
  857 
  858         /* Initialize network control register */
  859         /*  Disable loopback  */
  860         UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_LBK0 | UDAV_NCR_LBK1);
  861 
  862         /* Initialize RX control register */
  863         UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_DIS_LONG | UDAV_RCR_DIS_CRC);
  864 
  865         /* If we want promiscuous mode, accept all physical frames. */
  866         if (ifp->if_flags & IFF_PROMISC)
  867                 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
  868         else
  869                 UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
  870 
  871         /* Initialize transmit ring */
  872         if (usb_ether_tx_list_init(sc, &sc->sc_cdata,
  873             sc->sc_udev) == ENOBUFS) {
  874                 printf("%s: tx list init failed\n", USBDEVNAME(sc->sc_dev));
  875 #if defined(__NetBSD__)
  876                 splx(s);
  877                 return (EIO);
  878 #elif defined(__FreeBSD__)
  879                 UDAV_UNLOCK(sc);
  880                 return ;
  881 #endif
  882 
  883         }
  884 
  885         /* Initialize receive ring */
  886         if (usb_ether_rx_list_init(sc, &sc->sc_cdata,
  887             sc->sc_udev) == ENOBUFS) {
  888                 printf("%s: rx list init failed\n", USBDEVNAME(sc->sc_dev));
  889 #if defined(__NetBSD__)
  890                 splx(s);
  891                 return (EIO);
  892 #elif defined(__FreeBSD__)
  893                 UDAV_UNLOCK(sc);
  894                 return ;
  895 #endif
  896         }
  897 
  898         /* Load the multicast filter */
  899         udav_setmulti(sc);
  900 
  901         /* Enable RX */
  902         UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_RXEN);
  903 
  904         /* clear POWER_DOWN state of internal PHY */
  905         UDAV_SETBIT(sc, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0);
  906         UDAV_CLRBIT(sc, UDAV_GPR, UDAV_GPR_GEPIO0);
  907 
  908         mii_mediachg(mii);
  909 
  910         if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) {
  911                 if (udav_openpipes(sc)) {
  912 #if defined(__NetBSD__)
  913                         splx(s);
  914                         return (EIO);
  915 #elif defined(__FreeBSD__)
  916                         UDAV_UNLOCK(sc);
  917                         return ;
  918 #endif
  919                 }
  920         }
  921 
  922 #if defined(__FreeBSD__)
  923         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  924         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  925 #else
  926         ifp->if_flags |= IFF_RUNNING;
  927         ifp->if_flags &= ~IFF_OACTIVE;
  928 #endif
  929 
  930 #if defined(__NetBSD__)
  931         splx(s);
  932 #elif defined(__FreeBSD__)
  933         UDAV_UNLOCK(sc);
  934 #endif
  935 
  936         usb_callout(sc->sc_stat_ch, hz, udav_tick, sc);
  937 
  938 #if defined(__NetBSD__)
  939         return (0);
  940 #elif defined(__FreeBSD__)
  941         return ;
  942 #endif
  943 }
  944 
  945 Static void
  946 udav_reset(struct udav_softc *sc)
  947 {
  948         int i;
  949 
  950         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
  951 
  952         if (sc->sc_dying)
  953                 return;
  954 
  955         /* Select PHY */
  956 #if 1
  957         /*
  958          * XXX: force select internal phy.
  959          *      external phy routines are not tested.
  960          */
  961         UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
  962 #else
  963         if (sc->sc_flags & UDAV_EXT_PHY) {
  964                 UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
  965         } else {
  966                 UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
  967         }
  968 #endif
  969 
  970         UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_RST);
  971 
  972         for (i = 0; i < UDAV_TX_TIMEOUT; i++) {
  973                 if (!(udav_csr_read1(sc, UDAV_NCR) & UDAV_NCR_RST))
  974                         break;
  975                 delay(10);      /* XXX */
  976         }
  977         delay(10000);           /* XXX */
  978 }
  979 
  980 #if defined(__NetBSD__) || defined(__OpenBSD__)
  981 int
  982 udav_activate(device_ptr_t self, enum devact act)
  983 {
  984         struct udav_softc *sc = (struct udav_softc *)self;
  985 
  986         DPRINTF(("%s: %s: enter, act=%d\n", USBDEVNAME(sc->sc_dev),
  987                  __func__, act));
  988         switch (act) {
  989         case DVACT_ACTIVATE:
  990                 return (EOPNOTSUPP);
  991                 break;
  992 
  993         case DVACT_DEACTIVATE:
  994                 if_deactivate(&sc->sc_ec.ec_if);
  995                 sc->sc_dying = 1;
  996                 break;
  997         }
  998         return (0);
  999 }
 1000 #endif
 1001 
 1002 #define UDAV_BITS       6
 1003 
 1004 #define UDAV_CALCHASH(addr) \
 1005         (ether_crc32_le((addr), ETHER_ADDR_LEN) & ((1 << UDAV_BITS) - 1))
 1006 
 1007 Static void
 1008 udav_setmulti(struct udav_softc *sc)
 1009 {
 1010         struct ifnet *ifp;
 1011 #if defined(__NetBSD__)
 1012         struct ether_multi *enm;
 1013         struct ether_multistep step;
 1014 #elif defined(__FreeBSD__)
 1015         struct ifmultiaddr *ifma;
 1016 #endif
 1017         u_int8_t hashes[8];
 1018         int h = 0;
 1019 
 1020         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
 1021 
 1022         if (sc->sc_dying)
 1023                 return;
 1024 
 1025         ifp = GET_IFP(sc);
 1026 
 1027         if (ifp->if_flags & IFF_PROMISC) {
 1028                 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
 1029                 return;
 1030         } else if (ifp->if_flags & IFF_ALLMULTI) {
 1031 #if defined(__NetBSD__)
 1032         allmulti:
 1033 #endif
 1034                 ifp->if_flags |= IFF_ALLMULTI;
 1035                 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
 1036                 UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_PRMSC);
 1037                 return;
 1038         }
 1039 
 1040         /* first, zot all the existing hash bits */
 1041         memset(hashes, 0x00, sizeof(hashes));
 1042         hashes[7] |= 0x80;      /* broadcast address */
 1043         udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes));
 1044 
 1045         /* now program new ones */
 1046 #if defined(__NetBSD__)
 1047         ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
 1048         while (enm != NULL) {
 1049                 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
 1050                            ETHER_ADDR_LEN) != 0)
 1051                         goto allmulti;
 1052 
 1053                 h = UDAV_CALCHASH(enm->enm_addrlo);
 1054                 hashes[h>>3] |= 1 << (h & 0x7);
 1055                 ETHER_NEXT_MULTI(step, enm);
 1056         }
 1057 #elif defined(__FreeBSD__)
 1058         IF_ADDR_LOCK(ifp);
 1059 #if __FreeBSD_version >= 500000
 1060         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
 1061 #else
 1062         LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
 1063 #endif
 1064         {
 1065                 if (ifma->ifma_addr->sa_family != AF_LINK)
 1066                         continue;
 1067                 h = UDAV_CALCHASH(LLADDR((struct sockaddr_dl *)
 1068                     ifma->ifma_addr));
 1069                 hashes[h>>3] |= 1 << (h & 0x7);
 1070         }
 1071         IF_ADDR_UNLOCK(ifp);
 1072 #endif
 1073 
 1074         /* disable all multicast */
 1075         ifp->if_flags &= ~IFF_ALLMULTI;
 1076         UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
 1077 
 1078         /* write hash value to the register */
 1079         udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes));
 1080 }
 1081 
 1082 Static int
 1083 udav_openpipes(struct udav_softc *sc)
 1084 {
 1085         struct ue_chain *c;
 1086         usbd_status err;
 1087         int i;
 1088         int error = 0;
 1089 
 1090         if (sc->sc_dying)
 1091                 return (EIO);
 1092 
 1093         sc->sc_refcnt++;
 1094 
 1095         /* Open RX pipe */
 1096         err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no,
 1097                              USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx);
 1098         if (err) {
 1099                 printf("%s: open rx pipe failed: %s\n",
 1100                        USBDEVNAME(sc->sc_dev), usbd_errstr(err));
 1101                 error = EIO;
 1102                 goto done;
 1103         }
 1104 
 1105         /* Open TX pipe */
 1106         err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no,
 1107                              USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx);
 1108         if (err) {
 1109                 printf("%s: open tx pipe failed: %s\n",
 1110                        USBDEVNAME(sc->sc_dev), usbd_errstr(err));
 1111                 error = EIO;
 1112                 goto done;
 1113         }
 1114 
 1115 #if 0
 1116         /* XXX: interrupt endpoint is not yet supported */
 1117         /* Open Interrupt pipe */
 1118         err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no,
 1119                                   USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc,
 1120                                   &sc->sc_cdata.ue_ibuf, UDAV_INTR_PKGLEN,
 1121                                   udav_intr, UDAV_INTR_INTERVAL);
 1122         if (err) {
 1123                 printf("%s: open intr pipe failed: %s\n",
 1124                        USBDEVNAME(sc->sc_dev), usbd_errstr(err));
 1125                 error = EIO;
 1126                 goto done;
 1127         }
 1128 #endif
 1129 
 1130 
 1131         /* Start up the receive pipe. */
 1132         for (i = 0; i < UE_RX_LIST_CNT; i++) {
 1133                 c = &sc->sc_cdata.ue_rx_chain[i];
 1134                 usbd_setup_xfer(c->ue_xfer, sc->sc_pipe_rx,
 1135                                 c, c->ue_buf, UE_BUFSZ,
 1136                                 USBD_SHORT_XFER_OK | USBD_NO_COPY,
 1137                                 USBD_NO_TIMEOUT, udav_rxeof);
 1138                 (void)usbd_transfer(c->ue_xfer);
 1139                 DPRINTF(("%s: %s: start read\n", USBDEVNAME(sc->sc_dev),
 1140                          __func__));
 1141         }
 1142 
 1143  done:
 1144         if (--sc->sc_refcnt < 0)
 1145                 usb_detach_wakeup(USBDEV(sc->sc_dev));
 1146 
 1147         return (error);
 1148 }
 1149 
 1150 Static void
 1151 udav_start(struct ifnet *ifp)
 1152 {
 1153         struct udav_softc *sc = ifp->if_softc;
 1154         struct mbuf *m_head = NULL;
 1155 
 1156         DPRINTF(("%s: %s: enter, link=%d\n", USBDEVNAME(sc->sc_dev),
 1157                  __func__, sc->sc_link));
 1158 
 1159         if (sc->sc_dying)
 1160                 return;
 1161 
 1162         if (!sc->sc_link)
 1163                 return;
 1164 
 1165 #if defined(__FreeBSD__)
 1166         if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
 1167 #else
 1168         if (ifp->if_flags & IFF_OACTIVE)
 1169 #endif
 1170                 return;
 1171 #if defined(__NetBSD__)
 1172         IFQ_POLL(&ifp->if_snd, m_head);
 1173 #elif defined(__FreeBSD__)
 1174         IF_DEQUEUE(&ifp->if_snd, m_head);
 1175 #endif
 1176         if (m_head == NULL)
 1177                 return;
 1178 
 1179         if (udav_send(sc, m_head, 0)) {
 1180 #if defined(__FreeBSD__)
 1181                 IF_PREPEND(&ifp->if_snd, m_head);
 1182                 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 1183 #else
 1184                 ifp->if_flags |= IFF_OACTIVE;
 1185 #endif
 1186                 return;
 1187         }
 1188 
 1189 #if defined(__NetBSD__)
 1190         IFQ_DEQUEUE(&ifp->if_snd, m_head);
 1191 #endif
 1192 
 1193 #if NBPFILTER > 0
 1194         BPF_MTAP(ifp, m_head);
 1195 #endif
 1196 
 1197 #if defined(__FreeBSD__)
 1198         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 1199 #else
 1200         ifp->if_flags |= IFF_OACTIVE;
 1201 #endif
 1202 
 1203         /* Set a timeout in case the chip goes out to lunch. */
 1204         ifp->if_timer = 5;
 1205 }
 1206 
 1207 Static int
 1208 udav_send(struct udav_softc *sc, struct mbuf *m, int idx)
 1209 {
 1210         int total_len;
 1211         struct ue_chain *c;
 1212         usbd_status err;
 1213 
 1214         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
 1215 
 1216         c = &sc->sc_cdata.ue_tx_chain[idx];
 1217 
 1218         /* Copy the mbuf data into a contiguous buffer */
 1219         /*  first 2 bytes are packet length */
 1220         m_copydata(m, 0, m->m_pkthdr.len, c->ue_buf + 2);
 1221         c->ue_mbuf = m;
 1222         total_len = m->m_pkthdr.len;
 1223         if (total_len < UDAV_MIN_FRAME_LEN) {
 1224                 memset(c->ue_buf + 2 + total_len, 0,
 1225                     UDAV_MIN_FRAME_LEN - total_len);
 1226                 total_len = UDAV_MIN_FRAME_LEN;
 1227         }
 1228 
 1229         /* Frame length is specified in the first 2bytes of the buffer */
 1230         c->ue_buf[0] = (u_int8_t)total_len;
 1231         c->ue_buf[1] = (u_int8_t)(total_len >> 8);
 1232         total_len += 2;
 1233 
 1234         usbd_setup_xfer(c->ue_xfer, sc->sc_pipe_tx, c, c->ue_buf, total_len,
 1235                         USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
 1236                         UDAV_TX_TIMEOUT, udav_txeof);
 1237 
 1238         /* Transmit */
 1239         sc->sc_refcnt++;
 1240         err = usbd_transfer(c->ue_xfer);
 1241         if (--sc->sc_refcnt < 0)
 1242                 usb_detach_wakeup(USBDEV(sc->sc_dev));
 1243         if (err != USBD_IN_PROGRESS) {
 1244                 printf("%s: udav_send error=%s\n", USBDEVNAME(sc->sc_dev),
 1245                        usbd_errstr(err));
 1246                 /* Stop the interface */
 1247                 usb_add_task(sc->sc_udev, &sc->sc_stop_task);
 1248                 return (EIO);
 1249         }
 1250 
 1251         DPRINTF(("%s: %s: send %d bytes\n", USBDEVNAME(sc->sc_dev),
 1252                  __func__, total_len));
 1253 
 1254         sc->sc_cdata.ue_tx_cnt++;
 1255 
 1256         return (0);
 1257 }
 1258 
 1259 Static void
 1260 udav_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
 1261 {
 1262         struct ue_chain *c = priv;
 1263         struct udav_softc *sc = c->ue_sc;
 1264         struct ifnet *ifp = GET_IFP(sc);
 1265 #if defined(__NetBSD__)
 1266         int s;
 1267 #endif
 1268 
 1269         if (sc->sc_dying)
 1270                 return;
 1271 
 1272 #if defined(__NetBSD__)
 1273         s = splnet();
 1274 #elif defined(__FreeBSD__)
 1275         UDAV_LOCK(sc);
 1276 #endif
 1277 
 1278         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
 1279 
 1280         ifp->if_timer = 0;
 1281 #if defined(__FreeBSD__)
 1282         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 1283 #else
 1284         ifp->if_flags &= ~IFF_OACTIVE;
 1285 #endif
 1286 
 1287         if (status != USBD_NORMAL_COMPLETION) {
 1288                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
 1289 #if defined(__NetBSD__)
 1290                         splx(s);
 1291 #elif defined(__FreeBSD__)
 1292                         UDAV_UNLOCK(sc);
 1293 #endif
 1294                         return;
 1295                 }
 1296                 ifp->if_oerrors++;
 1297                 printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->sc_dev),
 1298                        usbd_errstr(status));
 1299                 if (status == USBD_STALLED) {
 1300                         sc->sc_refcnt++;
 1301                         usbd_clear_endpoint_stall(sc->sc_pipe_tx);
 1302                         if (--sc->sc_refcnt < 0)
 1303                                 usb_detach_wakeup(USBDEV(sc->sc_dev));
 1304                 }
 1305 #if defined(__NetBSD__)
 1306                 splx(s);
 1307 #elif defined(__FreeBSD__)
 1308                 UDAV_UNLOCK(sc);
 1309 #endif
 1310                 return;
 1311         }
 1312 
 1313         ifp->if_opackets++;
 1314 
 1315         m_freem(c->ue_mbuf);
 1316         c->ue_mbuf = NULL;
 1317 
 1318 #if defined(__NetBSD__)
 1319         if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
 1320 #elif defined(__FreeBSD__)
 1321         if ( ifp->if_snd.ifq_head != NULL )
 1322 #endif
 1323                 udav_start(ifp);
 1324 
 1325 #if defined(__NetBSD__)
 1326         splx(s);
 1327 #elif defined(__FreeBSD__)
 1328         UDAV_UNLOCK(sc);
 1329 #endif
 1330 }
 1331 
 1332 Static void
 1333 udav_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
 1334 {
 1335         struct ue_chain *c = priv;
 1336         struct udav_softc *sc = c->ue_sc;
 1337         struct ifnet *ifp = GET_IFP(sc);
 1338         struct mbuf *m;
 1339         u_int32_t total_len;
 1340         u_int8_t *pktstat;
 1341 #if defined(__NetBSD__)
 1342         int s;
 1343 #endif
 1344 
 1345         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
 1346 
 1347         if (sc->sc_dying)
 1348                 return;
 1349 
 1350         if (status != USBD_NORMAL_COMPLETION) {
 1351                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
 1352                         return;
 1353                 sc->sc_rx_errs++;
 1354                 if (usbd_ratecheck(&sc->sc_rx_notice)) {
 1355                         printf("%s: %u usb errors on rx: %s\n",
 1356                                USBDEVNAME(sc->sc_dev), sc->sc_rx_errs,
 1357                                usbd_errstr(status));
 1358                         sc->sc_rx_errs = 0;
 1359                 }
 1360                 if (status == USBD_STALLED) {
 1361                         sc->sc_refcnt++;
 1362                         usbd_clear_endpoint_stall(sc->sc_pipe_rx);
 1363                         if (--sc->sc_refcnt < 0)
 1364                                 usb_detach_wakeup(USBDEV(sc->sc_dev));
 1365                 }
 1366                 goto done;
 1367         }
 1368 
 1369         usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
 1370 
 1371         /* copy data to mbuf */
 1372         m = c->ue_mbuf;
 1373         memcpy(mtod(m, char *), c->ue_buf, total_len);
 1374 
 1375         /* first byte in received data */
 1376         pktstat = mtod(m, u_int8_t *);
 1377         m_adj(m, sizeof(u_int8_t));
 1378         DPRINTF(("%s: RX Status: 0x%02x\n", USBDEVNAME(sc->sc_dev), *pktstat));
 1379 
 1380         total_len = UGETW(mtod(m, u_int8_t *));
 1381         m_adj(m, sizeof(u_int16_t));
 1382 
 1383         if (*pktstat & UDAV_RSR_LCS) {
 1384                 ifp->if_collisions++;
 1385                 goto done;
 1386         }
 1387 
 1388         if (total_len < sizeof(struct ether_header) ||
 1389             *pktstat & UDAV_RSR_ERR) {
 1390                 ifp->if_ierrors++;
 1391                 goto done;
 1392         }
 1393 
 1394         ifp->if_ipackets++;
 1395         total_len -= ETHER_CRC_LEN;
 1396 
 1397         m->m_pkthdr.len = m->m_len = total_len;
 1398 #if defined(__NetBSD__)
 1399         m->m_pkthdr.rcvif = ifp;
 1400 #elif defined(__FreeBSD__)
 1401         m->m_pkthdr.rcvif = (struct ifnet *)&sc->sc_qdat;
 1402 #endif
 1403 
 1404 #if defined(__NetBSD__)
 1405         s = splnet();
 1406 #elif defined(__FreeBSD__)
 1407         UDAV_LOCK(sc);
 1408 #endif
 1409 
 1410 #if defined(__NetBSD__)
 1411         c->ue_mbuf = usb_ether_newbuf();
 1412         if (c->ue_mbuf == NULL) {
 1413                 printf("%s: no memory for rx list "
 1414                     "-- packet dropped!\n", USBDEVNAME(sc->sc_dev));
 1415                 ifp->if_ierrors++;
 1416                 goto done1;
 1417         }
 1418 #endif
 1419 
 1420 #if NBPFILTER > 0
 1421         BPF_MTAP(ifp, m);
 1422 #endif
 1423 
 1424         DPRINTF(("%s: %s: deliver %d\n", USBDEVNAME(sc->sc_dev),
 1425                  __func__, m->m_len));
 1426 #if defined(__NetBSD__)
 1427         IF_INPUT(ifp, m);
 1428 #endif
 1429 #if defined(__FreeBSD__)
 1430         usb_ether_input(m);
 1431         UDAV_UNLOCK(sc);
 1432         return ;
 1433 #endif
 1434 
 1435 #if defined(__NetBSD__)
 1436  done1:
 1437         splx(s);
 1438 #elif defined(__FreeBSD__)
 1439         UDAV_UNLOCK(sc);
 1440 #endif
 1441  done:
 1442         /* Setup new transfer */
 1443         usbd_setup_xfer(xfer, sc->sc_pipe_rx, c, c->ue_buf, UE_BUFSZ,
 1444                         USBD_SHORT_XFER_OK | USBD_NO_COPY,
 1445                         USBD_NO_TIMEOUT, udav_rxeof);
 1446         sc->sc_refcnt++;
 1447         usbd_transfer(xfer);
 1448         if (--sc->sc_refcnt < 0)
 1449                 usb_detach_wakeup(USBDEV(sc->sc_dev));
 1450 
 1451         DPRINTF(("%s: %s: start rx\n", USBDEVNAME(sc->sc_dev), __func__));
 1452 }
 1453 
 1454 #if 0
 1455 Static void udav_intr()
 1456 {
 1457 }
 1458 #endif
 1459 
 1460 Static int
 1461 udav_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 1462 {
 1463         struct udav_softc *sc = ifp->if_softc;
 1464         struct ifreq *ifr = (struct ifreq *)data;
 1465         struct mii_data *mii;
 1466 #if defined(__NetBSD__)
 1467         int s;
 1468 #endif
 1469         int error = 0;
 1470 
 1471         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
 1472 
 1473         if (sc->sc_dying)
 1474                 return (EIO);
 1475 
 1476 #if defined(__NetBSD__)
 1477         s = splnet();
 1478 #elif defined(__FreeBSD__)
 1479         UDAV_LOCK(sc);
 1480 #endif
 1481 
 1482         switch (cmd) {
 1483 #if defined(__FreeBSD__)
 1484         case SIOCSIFFLAGS:
 1485                 if (ifp->if_flags & IFF_UP) {
 1486                         if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
 1487                             ifp->if_flags & IFF_PROMISC) {
 1488                                 UDAV_SETBIT(sc, UDAV_RCR,
 1489                                             UDAV_RCR_ALL|UDAV_RCR_PRMSC);
 1490                         } else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
 1491                                    !(ifp->if_flags & IFF_PROMISC)) {
 1492                                 if (ifp->if_flags & IFF_ALLMULTI)
 1493                                         UDAV_CLRBIT(sc, UDAV_RCR,
 1494                                                     UDAV_RCR_PRMSC);
 1495                                 else
 1496                                         UDAV_CLRBIT(sc, UDAV_RCR,
 1497                                                     UDAV_RCR_ALL|UDAV_RCR_PRMSC);
 1498                         } else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
 1499                                 udav_init(sc);
 1500                 } else {
 1501                         if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 1502                                 udav_stop(ifp, 1);
 1503                 }
 1504                 error = 0;
 1505                 break;
 1506         case SIOCADDMULTI:
 1507         case SIOCDELMULTI:
 1508                 udav_setmulti(sc);
 1509                 error = 0;
 1510                 break;
 1511 #endif
 1512         case SIOCGIFMEDIA:
 1513         case SIOCSIFMEDIA:
 1514                 mii = GET_MII(sc);
 1515                 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
 1516                 break;
 1517 
 1518         default:
 1519                 error = ether_ioctl(ifp, cmd, data);
 1520 #if defined(__NetBSD__)
 1521                 if (error == ENETRESET) {
 1522                         udav_setmulti(sc);
 1523                         error = 0;
 1524                 }
 1525 #endif
 1526                 break;
 1527         }
 1528 
 1529 #if defined(__NetBSD__)
 1530         splx(s);
 1531 #elif defined(__FreeBSD__)
 1532         UDAV_UNLOCK(sc);
 1533 #endif
 1534 
 1535         return (error);
 1536 }
 1537 
 1538 Static void
 1539 udav_watchdog(struct ifnet *ifp)
 1540 {
 1541         struct udav_softc *sc = ifp->if_softc;
 1542         struct ue_chain *c;
 1543         usbd_status stat;
 1544 #if defined(__NetBSD__)
 1545         int s;
 1546 #endif
 1547 
 1548         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
 1549 
 1550         ifp->if_oerrors++;
 1551         printf("%s: watchdog timeout\n", USBDEVNAME(sc->sc_dev));
 1552 
 1553 #if defined(__NetBSD__)
 1554         s = splusb();
 1555 #elif defined(__FreeBSD__)
 1556         UDAV_LOCK(sc)
 1557 #endif
 1558         c = &sc->sc_cdata.ue_tx_chain[0];
 1559         usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &stat);
 1560         udav_txeof(c->ue_xfer, c, stat);
 1561 
 1562 #if defined(__NetBSD__)
 1563         if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
 1564 #elif defined(__FreeBSD__)
 1565         if ( ifp->if_snd.ifq_head != NULL )
 1566 #endif
 1567                 udav_start(ifp);
 1568 #if defined(__NetBSD__)
 1569         splx(s);
 1570 #elif defined(__FreeBSD__)
 1571         UDAV_UNLOCK(sc);
 1572 #endif
 1573 }
 1574 
 1575 Static void
 1576 udav_stop_task(struct udav_softc *sc)
 1577 {
 1578         udav_stop(GET_IFP(sc), 1);
 1579 }
 1580 
 1581 /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */
 1582 Static void
 1583 udav_stop(struct ifnet *ifp, int disable)
 1584 {
 1585         struct udav_softc *sc = ifp->if_softc;
 1586         usbd_status err;
 1587 
 1588         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
 1589 
 1590         ifp->if_timer = 0;
 1591 
 1592         udav_reset(sc);
 1593 
 1594         usb_uncallout(sc->sc_stat_ch, udav_tick, sc);
 1595 
 1596         /* Stop transfers */
 1597         /* RX endpoint */
 1598         if (sc->sc_pipe_rx != NULL) {
 1599                 err = usbd_abort_pipe(sc->sc_pipe_rx);
 1600                 if (err)
 1601                         printf("%s: abort rx pipe failed: %s\n",
 1602                                USBDEVNAME(sc->sc_dev), usbd_errstr(err));
 1603                 err = usbd_close_pipe(sc->sc_pipe_rx);
 1604                 if (err)
 1605                         printf("%s: close rx pipe failed: %s\n",
 1606                                USBDEVNAME(sc->sc_dev), usbd_errstr(err));
 1607                 sc->sc_pipe_rx = NULL;
 1608         }
 1609 
 1610         /* TX endpoint */
 1611         if (sc->sc_pipe_tx != NULL) {
 1612                 err = usbd_abort_pipe(sc->sc_pipe_tx);
 1613                 if (err)
 1614                         printf("%s: abort tx pipe failed: %s\n",
 1615                                USBDEVNAME(sc->sc_dev), usbd_errstr(err));
 1616                 err = usbd_close_pipe(sc->sc_pipe_tx);
 1617                 if (err)
 1618                         printf("%s: close tx pipe failed: %s\n",
 1619                                USBDEVNAME(sc->sc_dev), usbd_errstr(err));
 1620                 sc->sc_pipe_tx = NULL;
 1621         }
 1622 
 1623 #if 0
 1624         /* XXX: Interrupt endpoint is not yet supported!! */
 1625         /* Interrupt endpoint */
 1626         if (sc->sc_pipe_intr != NULL) {
 1627                 err = usbd_abort_pipe(sc->sc_pipe_intr);
 1628                 if (err)
 1629                         printf("%s: abort intr pipe failed: %s\n",
 1630                                USBDEVNAME(sc->sc_dev), usbd_errstr(err));
 1631                 err = usbd_close_pipe(sc->sc_pipe_intr);
 1632                 if (err)
 1633                         printf("%s: close intr pipe failed: %s\n",
 1634                                USBDEVNAME(sc->sc_dev), usbd_errstr(err));
 1635                 sc->sc_pipe_intr = NULL;
 1636         }
 1637 #endif
 1638 
 1639         /* Free RX resources. */
 1640         usb_ether_rx_list_free(&sc->sc_cdata);
 1641         /* Free TX resources. */
 1642         usb_ether_tx_list_free(&sc->sc_cdata);
 1643 
 1644         sc->sc_link = 0;
 1645 #if defined(__FreeBSD__)
 1646         ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 1647 #else
 1648         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
 1649 #endif
 1650 }
 1651 
 1652 /* Set media options */
 1653 Static int
 1654 udav_ifmedia_change(struct ifnet *ifp)
 1655 {
 1656         struct udav_softc *sc = ifp->if_softc;
 1657         struct mii_data *mii = GET_MII(sc);
 1658 
 1659         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
 1660 
 1661         if (sc->sc_dying)
 1662                 return (0);
 1663 
 1664         sc->sc_link = 0;
 1665         if (mii->mii_instance) {
 1666                 struct mii_softc *miisc;
 1667                 for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
 1668                      miisc = LIST_NEXT(miisc, mii_list))
 1669                         mii_phy_reset(miisc);
 1670         }
 1671 
 1672         return (mii_mediachg(mii));
 1673 }
 1674 
 1675 /* Report current media status. */
 1676 Static void
 1677 udav_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr)
 1678 {
 1679         struct udav_softc *sc = ifp->if_softc;
 1680         struct mii_data *mii = GET_MII(sc);
 1681 
 1682         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
 1683 
 1684         if (sc->sc_dying)
 1685                 return;
 1686 
 1687 #if defined(__FreeBSD__)
 1688         if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
 1689 #else
 1690         if ((ifp->if_flags & IFF_RUNNING) == 0) {
 1691 #endif
 1692                 ifmr->ifm_active = IFM_ETHER | IFM_NONE;
 1693                 ifmr->ifm_status = 0;
 1694                 return;
 1695         }
 1696 
 1697         mii_pollstat(mii);
 1698         ifmr->ifm_active = mii->mii_media_active;
 1699         ifmr->ifm_status = mii->mii_media_status;
 1700 }
 1701 
 1702 Static void
 1703 udav_tick(void *xsc)
 1704 {
 1705         struct udav_softc *sc = xsc;
 1706 
 1707         if (sc == NULL)
 1708                 return;
 1709 
 1710         DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),
 1711                         __func__));
 1712 
 1713         if (sc->sc_dying)
 1714                 return;
 1715 
 1716         /* Perform periodic stuff in process context */
 1717         usb_add_task(sc->sc_udev, &sc->sc_tick_task);
 1718 }
 1719 
 1720 Static void
 1721 udav_tick_task(void *xsc)
 1722 {
 1723         struct udav_softc *sc = xsc;
 1724         struct ifnet *ifp;
 1725         struct mii_data *mii;
 1726 #if defined(__NetBSD__)
 1727         int s;
 1728 #endif
 1729 
 1730         if (sc == NULL)
 1731                 return;
 1732 
 1733         DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),
 1734                         __func__));
 1735 
 1736         if (sc->sc_dying)
 1737                 return;
 1738 
 1739         ifp = GET_IFP(sc);
 1740         mii = GET_MII(sc);
 1741 
 1742         if (mii == NULL)
 1743                 return;
 1744 
 1745 #if defined(__NetBSD__)
 1746         s = splnet();
 1747 #elif defined(__FreeBSD__)
 1748         UDAV_LOCK(sc);
 1749 #endif
 1750 
 1751         mii_tick(mii);
 1752         if (!sc->sc_link) {
 1753                 mii_pollstat(mii);
 1754                 if (mii->mii_media_status & IFM_ACTIVE &&
 1755                     IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
 1756                         DPRINTF(("%s: %s: got link\n",
 1757                                  USBDEVNAME(sc->sc_dev), __func__));
 1758                         sc->sc_link++;
 1759 #if defined(__NetBSD__)
 1760                         if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
 1761 #elif defined(__FreeBSD__)
 1762                         if ( ifp->if_snd.ifq_head != NULL )
 1763 #endif
 1764                                    udav_start(ifp);
 1765                 }
 1766         }
 1767 
 1768         usb_callout(sc->sc_stat_ch, hz, udav_tick, sc);
 1769 
 1770 #if defined(__NetBSD__)
 1771         splx(s);
 1772 #elif defined(__FreeBSD__)
 1773         UDAV_UNLOCK(sc);
 1774 #endif
 1775 }
 1776 
 1777 /* Get exclusive access to the MII registers */
 1778 Static void
 1779 udav_lock_mii(struct udav_softc *sc)
 1780 {
 1781         DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),
 1782                         __func__));
 1783 
 1784         sc->sc_refcnt++;
 1785 #if defined(__NetBSD__)
 1786         lockmgr(&sc->sc_mii_lock, LK_EXCLUSIVE, NULL);
 1787 #elif defined(__FreeBSD__)
 1788         lockmgr(&sc->sc_mii_lock, LK_EXCLUSIVE, NULL, NULL);
 1789 #endif
 1790 }
 1791 
 1792 Static void
 1793 udav_unlock_mii(struct udav_softc *sc)
 1794 {
 1795         DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),
 1796                        __func__));
 1797 
 1798 #if defined(__NetBSD__)
 1799         lockmgr(&sc->sc_mii_lock, LK_RELEASE, NULL);
 1800 #elif defined(__FreeBSD__)
 1801         lockmgr(&sc->sc_mii_lock, LK_RELEASE, NULL, NULL);
 1802 #endif
 1803         if (--sc->sc_refcnt < 0)
 1804                 usb_detach_wakeup(USBDEV(sc->sc_dev));
 1805 }
 1806 
 1807 Static int
 1808 udav_miibus_readreg(device_ptr_t dev, int phy, int reg)
 1809 {
 1810         struct udav_softc *sc;
 1811         u_int8_t val[2];
 1812         u_int16_t data16;
 1813 
 1814         if (dev == NULL)
 1815                 return (0);
 1816 
 1817         sc = USBGETSOFTC(dev);
 1818 
 1819         DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n",
 1820                  USBDEVNAME(sc->sc_dev), __func__, phy, reg));
 1821 
 1822         if (sc->sc_dying) {
 1823 #ifdef DIAGNOSTIC
 1824                 printf("%s: %s: dying\n", USBDEVNAME(sc->sc_dev),
 1825                        __func__);
 1826 #endif
 1827                 return (0);
 1828         }
 1829 
 1830         /* XXX: one PHY only for the internal PHY */
 1831         if (phy != 0) {
 1832                 DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
 1833                          USBDEVNAME(sc->sc_dev), __func__, phy));
 1834                 return (0);
 1835         }
 1836 
 1837         udav_lock_mii(sc);
 1838 
 1839         /* select internal PHY and set PHY register address */
 1840         udav_csr_write1(sc, UDAV_EPAR,
 1841                         UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
 1842 
 1843         /* select PHY operation and start read command */
 1844         udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRR);
 1845 
 1846         /* XXX: should be wait? */
 1847 
 1848         /* end read command */
 1849         UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRR);
 1850 
 1851         /* retrieve the result from data registers */
 1852         udav_csr_read(sc, UDAV_EPDRL, val, 2);
 1853 
 1854         udav_unlock_mii(sc);
 1855 
 1856         data16 = val[0] | (val[1] << 8);
 1857 
 1858         DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04x\n",
 1859                  USBDEVNAME(sc->sc_dev), __func__, phy, reg, data16));
 1860 
 1861         return (data16);
 1862 }
 1863 
 1864 Static void
 1865 udav_miibus_writereg(device_ptr_t dev, int phy, int reg, int data)
 1866 {
 1867         struct udav_softc *sc;
 1868         u_int8_t val[2];
 1869 
 1870         if (dev == NULL)
 1871                 return;
 1872 
 1873         sc = USBGETSOFTC(dev);
 1874 
 1875         DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n",
 1876                  USBDEVNAME(sc->sc_dev), __func__, phy, reg, data));
 1877 
 1878         if (sc->sc_dying) {
 1879 #ifdef DIAGNOSTIC
 1880                 printf("%s: %s: dying\n", USBDEVNAME(sc->sc_dev),
 1881                        __func__);
 1882 #endif
 1883                 return;
 1884         }
 1885 
 1886         /* XXX: one PHY only for the internal PHY */
 1887         if (phy != 0) {
 1888                 DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
 1889                          USBDEVNAME(sc->sc_dev), __func__, phy));
 1890                 return;
 1891         }
 1892 
 1893         udav_lock_mii(sc);
 1894 
 1895         /* select internal PHY and set PHY register address */
 1896         udav_csr_write1(sc, UDAV_EPAR,
 1897                         UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
 1898 
 1899         /* put the value to the data registers */
 1900         val[0] = data & 0xff;
 1901         val[1] = (data >> 8) & 0xff;
 1902         udav_csr_write(sc, UDAV_EPDRL, val, 2);
 1903 
 1904         /* select PHY operation and start write command */
 1905         udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRW);
 1906 
 1907         /* XXX: should be wait? */
 1908 
 1909         /* end write command */
 1910         UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRW);
 1911 
 1912         udav_unlock_mii(sc);
 1913 
 1914         return;
 1915 }
 1916 
 1917 Static void
 1918 udav_miibus_statchg(device_ptr_t dev)
 1919 {
 1920 #ifdef UDAV_DEBUG
 1921         struct udav_softc *sc;
 1922 
 1923         if (dev == NULL)
 1924                 return;
 1925 
 1926         sc = USBGETSOFTC(dev);
 1927         DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
 1928 #endif
 1929         /* Nothing to do */
 1930 }
 1931 
 1932 #if defined(__FreeBSD__)
 1933 /*
 1934  * Stop all chip I/O so that the kernel's probe routines don't
 1935  * get confused by errant DMAs when rebooting.
 1936  */
 1937 Static void
 1938 udav_shutdown(device_ptr_t dev)
 1939 {
 1940         struct udav_softc       *sc;
 1941 
 1942         sc = device_get_softc(dev);
 1943 
 1944         udav_stop_task(sc);
 1945 
 1946         return;
 1947 }
 1948 
 1949 Static void
 1950 udav_rxstart(struct ifnet *ifp)
 1951 {
 1952         struct udav_softc       *sc;
 1953         struct ue_chain *c;
 1954 
 1955         sc = ifp->if_softc;
 1956         UDAV_LOCK(sc);
 1957         c = &sc->sc_cdata.ue_rx_chain[sc->sc_cdata.ue_rx_prod];
 1958 
 1959         c->ue_mbuf = usb_ether_newbuf();
 1960         if (c->ue_mbuf == NULL) {
 1961                 printf("%s: no memory for rx list "
 1962                     "-- packet dropped!\n", USBDEVNAME(sc->sc_dev));
 1963                 ifp->if_ierrors++;
 1964                 UDAV_UNLOCK(sc);
 1965                 return;
 1966         }
 1967 
 1968         /* Setup new transfer. */
 1969         usbd_setup_xfer(c->ue_xfer, sc->sc_pipe_rx,
 1970                         c, c->ue_buf, UE_BUFSZ,
 1971                         USBD_SHORT_XFER_OK | USBD_NO_COPY,
 1972                         USBD_NO_TIMEOUT, udav_rxeof);
 1973         usbd_transfer(c->ue_xfer);
 1974 
 1975         UDAV_UNLOCK(sc);
 1976         return;
 1977 }
 1978 #endif

Cache object: 796d8dd291b50f1b3a68f9ed67a85b49


[ 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.