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

Cache object: b3fc623df4f113b7f3214183b3f2a02f


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