root/dev/usb/if_cue.c

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

DEFINITIONS

This source file includes following definitions.
  1. cue_csr_read_1
  2. cue_csr_read_2
  3. cue_csr_write_1
  4. cue_csr_write_2
  5. cue_mem
  6. cue_getmac
  7. cue_setmulti
  8. cue_reset
  9. cue_match
  10. cue_attach
  11. cue_detach
  12. cue_activate
  13. cue_newbuf
  14. cue_rx_list_init
  15. cue_tx_list_init
  16. cue_rxeof
  17. cue_txeof
  18. cue_tick
  19. cue_tick_task
  20. cue_send
  21. cue_start
  22. cue_init
  23. cue_open_pipes
  24. cue_ioctl
  25. cue_watchdog
  26. cue_stop

    1 /*      $OpenBSD: if_cue.c,v 1.45 2007/06/14 10:11:15 mbalmer Exp $ */
    2 /*      $NetBSD: if_cue.c,v 1.40 2002/07/11 21:14:26 augustss Exp $     */
    3 /*
    4  * Copyright (c) 1997, 1998, 1999, 2000
    5  *      Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Bill Paul.
   18  * 4. Neither the name of the author nor the names of any co-contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
   26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   32  * THE POSSIBILITY OF SUCH DAMAGE.
   33  *
   34  * $FreeBSD: src/sys/dev/usb/if_cue.c,v 1.4 2000/01/16 22:45:06 wpaul Exp $
   35  */
   36 
   37 /*
   38  * CATC USB-EL1210A USB to ethernet driver. Used in the CATC Netmate
   39  * adapters and others.
   40  *
   41  * Written by Bill Paul <wpaul@ee.columbia.edu>
   42  * Electrical Engineering Department
   43  * Columbia University, New York City
   44  */
   45 
   46 /*
   47  * The CATC USB-EL1210A provides USB ethernet support at 10Mbps. The
   48  * RX filter uses a 512-bit multicast hash table, single perfect entry
   49  * for the station address, and promiscuous mode. Unlike the ADMtek
   50  * and KLSI chips, the CATC ASIC supports read and write combining
   51  * mode where multiple packets can be transferred using a single bulk
   52  * transaction, which helps performance a great deal.
   53  */
   54 
   55 /*
   56  * Ported to NetBSD and somewhat rewritten by Lennart Augustsson.
   57  */
   58 
   59 #include "bpfilter.h"
   60 
   61 #include <sys/param.h>
   62 #include <sys/systm.h>
   63 #include <sys/sockio.h>
   64 #include <sys/mbuf.h>
   65 #include <sys/malloc.h>
   66 #include <sys/kernel.h>
   67 #include <sys/socket.h>
   68 #include <sys/timeout.h>
   69 #include <sys/device.h>
   70 
   71 #include <net/if.h>
   72 #include <net/if_dl.h>
   73 
   74 #if NBPFILTER > 0
   75 #include <net/bpf.h>
   76 #endif
   77 
   78 #ifdef INET
   79 #include <netinet/in.h>
   80 #include <netinet/in_systm.h>
   81 #include <netinet/in_var.h>
   82 #include <netinet/ip.h>
   83 #include <netinet/if_ether.h>
   84 #endif
   85 
   86 #include <dev/usb/usb.h>
   87 #include <dev/usb/usbdi.h>
   88 #include <dev/usb/usbdi_util.h>
   89 #include <dev/usb/usbdevs.h>
   90 
   91 #include <dev/usb/if_cuereg.h>
   92 
   93 #ifdef CUE_DEBUG
   94 #define DPRINTF(x)      do { if (cuedebug) printf x; } while (0)
   95 #define DPRINTFN(n,x)   do { if (cuedebug >= (n)) printf x; } while (0)
   96 int     cuedebug = 0;
   97 #else
   98 #define DPRINTF(x)
   99 #define DPRINTFN(n,x)
  100 #endif
  101 
  102 /*
  103  * Various supported device vendors/products.
  104  */
  105 struct usb_devno cue_devs[] = {
  106         { USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE },
  107         { USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE2 },
  108         { USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTLINK },
  109         /* Belkin F5U111 adapter covered by NETMATE entry */
  110 };
  111 #define cue_lookup(v, p) (usb_lookup(cue_devs, v, p))
  112 
  113 int cue_match(struct device *, void *, void *); 
  114 void cue_attach(struct device *, struct device *, void *); 
  115 int cue_detach(struct device *, int); 
  116 int cue_activate(struct device *, enum devact); 
  117 
  118 struct cfdriver cue_cd = { 
  119         NULL, "cue", DV_IFNET 
  120 }; 
  121 
  122 const struct cfattach cue_ca = { 
  123         sizeof(struct cue_softc), 
  124         cue_match, 
  125         cue_attach, 
  126         cue_detach, 
  127         cue_activate, 
  128 };
  129 
  130 int cue_open_pipes(struct cue_softc *);
  131 int cue_tx_list_init(struct cue_softc *);
  132 int cue_rx_list_init(struct cue_softc *);
  133 int cue_newbuf(struct cue_softc *, struct cue_chain *, struct mbuf *);
  134 int cue_send(struct cue_softc *, struct mbuf *, int);
  135 void cue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
  136 void cue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
  137 void cue_tick(void *);
  138 void cue_tick_task(void *);
  139 void cue_start(struct ifnet *);
  140 int cue_ioctl(struct ifnet *, u_long, caddr_t);
  141 void cue_init(void *);
  142 void cue_stop(struct cue_softc *);
  143 void cue_watchdog(struct ifnet *);
  144 
  145 void cue_setmulti(struct cue_softc *);
  146 void cue_reset(struct cue_softc *);
  147 
  148 int cue_csr_read_1(struct cue_softc *, int);
  149 int cue_csr_write_1(struct cue_softc *, int, int);
  150 int cue_csr_read_2(struct cue_softc *, int);
  151 #if 0
  152 int cue_csr_write_2(struct cue_softc *, int, int);
  153 #endif
  154 int cue_mem(struct cue_softc *, int, int, void *, int);
  155 int cue_getmac(struct cue_softc *, void *);
  156 
  157 #define CUE_SETBIT(sc, reg, x)                          \
  158         cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) | (x))
  159 
  160 #define CUE_CLRBIT(sc, reg, x)                          \
  161         cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) & ~(x))
  162 
  163 int
  164 cue_csr_read_1(struct cue_softc *sc, int reg)
  165 {
  166         usb_device_request_t    req;
  167         usbd_status             err;
  168         u_int8_t                val = 0;
  169 
  170         if (sc->cue_dying)
  171                 return (0);
  172 
  173         req.bmRequestType = UT_READ_VENDOR_DEVICE;
  174         req.bRequest = CUE_CMD_READREG;
  175         USETW(req.wValue, 0);
  176         USETW(req.wIndex, reg);
  177         USETW(req.wLength, 1);
  178 
  179         err = usbd_do_request(sc->cue_udev, &req, &val);
  180 
  181         if (err) {
  182                 DPRINTF(("%s: cue_csr_read_1: reg=0x%x err=%s\n",
  183                          sc->cue_dev.dv_xname, reg, usbd_errstr(err)));
  184                 return (0);
  185         }
  186 
  187         DPRINTFN(10,("%s: cue_csr_read_1 reg=0x%x val=0x%x\n",
  188                      sc->cue_dev.dv_xname, reg, val));
  189 
  190         return (val);
  191 }
  192 
  193 int
  194 cue_csr_read_2(struct cue_softc *sc, int reg)
  195 {
  196         usb_device_request_t    req;
  197         usbd_status             err;
  198         uWord                   val;
  199 
  200         if (sc->cue_dying)
  201                 return (0);
  202 
  203         req.bmRequestType = UT_READ_VENDOR_DEVICE;
  204         req.bRequest = CUE_CMD_READREG;
  205         USETW(req.wValue, 0);
  206         USETW(req.wIndex, reg);
  207         USETW(req.wLength, 2);
  208 
  209         err = usbd_do_request(sc->cue_udev, &req, &val);
  210 
  211         DPRINTFN(10,("%s: cue_csr_read_2 reg=0x%x val=0x%x\n",
  212                      sc->cue_dev.dv_xname, reg, UGETW(val)));
  213 
  214         if (err) {
  215                 DPRINTF(("%s: cue_csr_read_2: reg=0x%x err=%s\n",
  216                          sc->cue_dev.dv_xname, reg, usbd_errstr(err)));
  217                 return (0);
  218         }
  219 
  220         return (UGETW(val));
  221 }
  222 
  223 int
  224 cue_csr_write_1(struct cue_softc *sc, int reg, int val)
  225 {
  226         usb_device_request_t    req;
  227         usbd_status             err;
  228 
  229         if (sc->cue_dying)
  230                 return (0);
  231 
  232         DPRINTFN(10,("%s: cue_csr_write_1 reg=0x%x val=0x%x\n",
  233                      sc->cue_dev.dv_xname, reg, val));
  234 
  235         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  236         req.bRequest = CUE_CMD_WRITEREG;
  237         USETW(req.wValue, val);
  238         USETW(req.wIndex, reg);
  239         USETW(req.wLength, 0);
  240 
  241         err = usbd_do_request(sc->cue_udev, &req, NULL);
  242 
  243         if (err) {
  244                 DPRINTF(("%s: cue_csr_write_1: reg=0x%x err=%s\n",
  245                          sc->cue_dev.dv_xname, reg, usbd_errstr(err)));
  246                 return (-1);
  247         }
  248 
  249         DPRINTFN(20,("%s: cue_csr_write_1, after reg=0x%x val=0x%x\n",
  250                      sc->cue_dev.dv_xname, reg, cue_csr_read_1(sc, reg)));
  251 
  252         return (0);
  253 }
  254 
  255 #if 0
  256 int
  257 cue_csr_write_2(struct cue_softc *sc, int reg, int aval)
  258 {
  259         usb_device_request_t    req;
  260         usbd_status             err;
  261         uWord                   val;
  262         int                     s;
  263 
  264         if (sc->cue_dying)
  265                 return (0);
  266 
  267         DPRINTFN(10,("%s: cue_csr_write_2 reg=0x%x val=0x%x\n",
  268                      sc->cue_dev.dv_xname, reg, aval));
  269 
  270         USETW(val, aval);
  271         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  272         req.bRequest = CUE_CMD_WRITEREG;
  273         USETW(req.wValue, val);
  274         USETW(req.wIndex, reg);
  275         USETW(req.wLength, 0);
  276 
  277         err = usbd_do_request(sc->cue_udev, &req, NULL);
  278 
  279         if (err) {
  280                 DPRINTF(("%s: cue_csr_write_2: reg=0x%x err=%s\n",
  281                          sc->cue_dev.dv_xname, reg, usbd_errstr(err)));
  282                 return (-1);
  283         }
  284 
  285         return (0);
  286 }
  287 #endif
  288 
  289 int
  290 cue_mem(struct cue_softc *sc, int cmd, int addr, void *buf, int len)
  291 {
  292         usb_device_request_t    req;
  293         usbd_status             err;
  294 
  295         DPRINTFN(10,("%s: cue_mem cmd=0x%x addr=0x%x len=%d\n",
  296                      sc->cue_dev.dv_xname, cmd, addr, len));
  297 
  298         if (cmd == CUE_CMD_READSRAM)
  299                 req.bmRequestType = UT_READ_VENDOR_DEVICE;
  300         else
  301                 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  302         req.bRequest = cmd;
  303         USETW(req.wValue, 0);
  304         USETW(req.wIndex, addr);
  305         USETW(req.wLength, len);
  306 
  307         err = usbd_do_request(sc->cue_udev, &req, buf);
  308 
  309         if (err) {
  310                 DPRINTF(("%s: cue_csr_mem: addr=0x%x err=%s\n",
  311                          sc->cue_dev.dv_xname, addr, usbd_errstr(err)));
  312                 return (-1);
  313         }
  314 
  315         return (0);
  316 }
  317 
  318 int
  319 cue_getmac(struct cue_softc *sc, void *buf)
  320 {
  321         usb_device_request_t    req;
  322         usbd_status             err;
  323 
  324         DPRINTFN(10,("%s: cue_getmac\n", sc->cue_dev.dv_xname));
  325 
  326         req.bmRequestType = UT_READ_VENDOR_DEVICE;
  327         req.bRequest = CUE_CMD_GET_MACADDR;
  328         USETW(req.wValue, 0);
  329         USETW(req.wIndex, 0);
  330         USETW(req.wLength, ETHER_ADDR_LEN);
  331 
  332         err = usbd_do_request(sc->cue_udev, &req, buf);
  333 
  334         if (err) {
  335                 printf("%s: read MAC address failed\n",
  336                        sc->cue_dev.dv_xname);
  337                 return (-1);
  338         }
  339 
  340         return (0);
  341 }
  342 
  343 #define CUE_BITS        9
  344 
  345 void
  346 cue_setmulti(struct cue_softc *sc)
  347 {
  348         struct ifnet            *ifp;
  349         struct ether_multi      *enm;
  350         struct ether_multistep  step;
  351         u_int32_t               h, i;
  352 
  353         ifp = GET_IFP(sc);
  354 
  355         DPRINTFN(2,("%s: cue_setmulti if_flags=0x%x\n",
  356                     sc->cue_dev.dv_xname, ifp->if_flags));
  357 
  358         if (ifp->if_flags & IFF_PROMISC) {
  359 allmulti:
  360                 ifp->if_flags |= IFF_ALLMULTI;
  361                 for (i = 0; i < CUE_MCAST_TABLE_LEN; i++)
  362                         sc->cue_mctab[i] = 0xFF;
  363                 cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
  364                     &sc->cue_mctab, CUE_MCAST_TABLE_LEN);
  365                 return;
  366         }
  367 
  368         /* first, zot all the existing hash bits */
  369         for (i = 0; i < CUE_MCAST_TABLE_LEN; i++)
  370                 sc->cue_mctab[i] = 0;
  371 
  372         /* now program new ones */
  373         ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
  374         while (enm != NULL) {
  375                 if (memcmp(enm->enm_addrlo,
  376                     enm->enm_addrhi, ETHER_ADDR_LEN) != 0)
  377                         goto allmulti;
  378 
  379                 h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) &
  380                     ((1 << CUE_BITS) - 1);
  381                 sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
  382                 ETHER_NEXT_MULTI(step, enm);
  383         }
  384 
  385         ifp->if_flags &= ~IFF_ALLMULTI;
  386 
  387         /*
  388          * Also include the broadcast address in the filter
  389          * so we can receive broadcast frames.
  390          */
  391         if (ifp->if_flags & IFF_BROADCAST) {
  392                 h = ether_crc32_le(etherbroadcastaddr, ETHER_ADDR_LEN) &
  393                     ((1 << CUE_BITS) - 1);
  394                 sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
  395         }
  396 
  397         cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR,
  398             &sc->cue_mctab, CUE_MCAST_TABLE_LEN);
  399 }
  400 
  401 void
  402 cue_reset(struct cue_softc *sc)
  403 {
  404         usb_device_request_t    req;
  405         usbd_status             err;
  406 
  407         DPRINTFN(2,("%s: cue_reset\n", sc->cue_dev.dv_xname));
  408 
  409         if (sc->cue_dying)
  410                 return;
  411 
  412         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
  413         req.bRequest = CUE_CMD_RESET;
  414         USETW(req.wValue, 0);
  415         USETW(req.wIndex, 0);
  416         USETW(req.wLength, 0);
  417 
  418         err = usbd_do_request(sc->cue_udev, &req, NULL);
  419 
  420         if (err)
  421                 printf("%s: reset failed\n", sc->cue_dev.dv_xname);
  422 
  423         /* Wait a little while for the chip to get its brains in order. */
  424         usbd_delay_ms(sc->cue_udev, 1);
  425 }
  426 
  427 /*
  428  * Probe for a CATC chip.
  429  */
  430 int
  431 cue_match(struct device *parent, void *match, void *aux)
  432 {
  433         struct usb_attach_arg   *uaa = aux;
  434 
  435         if (uaa->iface != NULL)
  436                 return (UMATCH_NONE);
  437 
  438         return (cue_lookup(uaa->vendor, uaa->product) != NULL ?
  439                 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
  440 }
  441 
  442 /*
  443  * Attach the interface. Allocate softc structures, do ifmedia
  444  * setup and ethernet/BPF attach.
  445  */
  446 void
  447 cue_attach(struct device *parent, struct device *self, void *aux)
  448 {
  449         struct cue_softc        *sc = (struct cue_softc *)self;
  450         struct usb_attach_arg   *uaa = aux;
  451         char                    *devinfop;
  452         int                     s;
  453         u_char                  eaddr[ETHER_ADDR_LEN];
  454         usbd_device_handle      dev = uaa->device;
  455         usbd_interface_handle   iface;
  456         usbd_status             err;
  457         struct ifnet            *ifp;
  458         usb_interface_descriptor_t      *id;
  459         usb_endpoint_descriptor_t       *ed;
  460         int                     i;
  461 
  462         DPRINTFN(5,(" : cue_attach: sc=%p, dev=%p", sc, dev));
  463 
  464         devinfop = usbd_devinfo_alloc(dev, 0);
  465         printf("\n%s: %s\n", sc->cue_dev.dv_xname, devinfop);
  466         usbd_devinfo_free(devinfop);
  467 
  468         err = usbd_set_config_no(dev, CUE_CONFIG_NO, 1);
  469         if (err) {
  470                 printf("%s: setting config no failed\n",
  471                     sc->cue_dev.dv_xname);
  472                 return;
  473         }
  474 
  475         sc->cue_udev = dev;
  476         sc->cue_product = uaa->product;
  477         sc->cue_vendor = uaa->vendor;
  478 
  479         usb_init_task(&sc->cue_tick_task, cue_tick_task, sc);
  480         usb_init_task(&sc->cue_stop_task, (void (*)(void *))cue_stop, sc);
  481 
  482         err = usbd_device2interface_handle(dev, CUE_IFACE_IDX, &iface);
  483         if (err) {
  484                 printf("%s: getting interface handle failed\n",
  485                     sc->cue_dev.dv_xname);
  486                 return;
  487         }
  488 
  489         sc->cue_iface = iface;
  490         id = usbd_get_interface_descriptor(iface);
  491 
  492         /* Find endpoints. */
  493         for (i = 0; i < id->bNumEndpoints; i++) {
  494                 ed = usbd_interface2endpoint_descriptor(iface, i);
  495                 if (ed == NULL) {
  496                         printf("%s: couldn't get ep %d\n",
  497                             sc->cue_dev.dv_xname, i);
  498                         return;
  499                 }
  500                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  501                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  502                         sc->cue_ed[CUE_ENDPT_RX] = ed->bEndpointAddress;
  503                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  504                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  505                         sc->cue_ed[CUE_ENDPT_TX] = ed->bEndpointAddress;
  506                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  507                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
  508                         sc->cue_ed[CUE_ENDPT_INTR] = ed->bEndpointAddress;
  509                 }
  510         }
  511 
  512 #if 0
  513         /* Reset the adapter. */
  514         cue_reset(sc);
  515 #endif
  516         /*
  517          * Get station address.
  518          */
  519         cue_getmac(sc, &eaddr);
  520 
  521         s = splnet();
  522 
  523         /*
  524          * A CATC chip was detected. Inform the world.
  525          */
  526         printf("%s: address %s\n", sc->cue_dev.dv_xname,
  527             ether_sprintf(eaddr));
  528 
  529         bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
  530 
  531         /* Initialize interface info.*/
  532         ifp = GET_IFP(sc);
  533         ifp->if_softc = sc;
  534         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  535         ifp->if_ioctl = cue_ioctl;
  536         ifp->if_start = cue_start;
  537         ifp->if_watchdog = cue_watchdog;
  538         strlcpy(ifp->if_xname, sc->cue_dev.dv_xname, IFNAMSIZ);
  539 
  540         IFQ_SET_READY(&ifp->if_snd);
  541 
  542         /* Attach the interface. */
  543         if_attach(ifp);
  544         ether_ifattach(ifp);
  545 
  546         timeout_set(&sc->cue_stat_ch, NULL, NULL);
  547 
  548         sc->cue_attached = 1;
  549         splx(s);
  550 
  551         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cue_udev,
  552             &sc->cue_dev);
  553 }
  554 
  555 int
  556 cue_detach(struct device *self, int flags)
  557 {
  558         struct cue_softc        *sc = (struct cue_softc *)self;
  559         struct ifnet            *ifp = GET_IFP(sc);
  560         int                     s;
  561 
  562         DPRINTFN(2,("%s: %s: enter\n", sc->cue_dev.dv_xname, __func__));
  563 
  564         timeout_del(&sc->cue_stat_ch);
  565         /*
  566          * Remove any pending task.  It cannot be executing because it run
  567          * in the same thread as detach.
  568          */
  569         usb_rem_task(sc->cue_udev, &sc->cue_tick_task);
  570         usb_rem_task(sc->cue_udev, &sc->cue_stop_task);
  571 
  572         if (!sc->cue_attached) {
  573                 /* Detached before attached finished, so just bail out. */
  574                 return (0);
  575         }
  576 
  577         s = splusb();
  578 
  579         if (ifp->if_flags & IFF_RUNNING)
  580                 cue_stop(sc);
  581 
  582         ether_ifdetach(ifp);
  583 
  584         if_detach(ifp);
  585 
  586 #ifdef DIAGNOSTIC
  587         if (sc->cue_ep[CUE_ENDPT_TX] != NULL ||
  588             sc->cue_ep[CUE_ENDPT_RX] != NULL ||
  589             sc->cue_ep[CUE_ENDPT_INTR] != NULL)
  590                 printf("%s: detach has active endpoints\n",
  591                        sc->cue_dev.dv_xname);
  592 #endif
  593 
  594         sc->cue_attached = 0;
  595         splx(s);
  596 
  597         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->cue_udev,
  598             &sc->cue_dev);
  599 
  600         return (0);
  601 }
  602 
  603 int
  604 cue_activate(struct device *self, enum devact act)
  605 {
  606         struct cue_softc *sc = (struct cue_softc *)self;
  607 
  608         DPRINTFN(2,("%s: %s: enter\n", sc->cue_dev.dv_xname, __func__));
  609 
  610         switch (act) {
  611         case DVACT_ACTIVATE:
  612                 break;
  613 
  614         case DVACT_DEACTIVATE:
  615                 sc->cue_dying = 1;
  616                 break;
  617         }
  618         return (0);
  619 }
  620 
  621 /*
  622  * Initialize an RX descriptor and attach an MBUF cluster.
  623  */
  624 int
  625 cue_newbuf(struct cue_softc *sc, struct cue_chain *c, struct mbuf *m)
  626 {
  627         struct mbuf             *m_new = NULL;
  628 
  629         if (m == NULL) {
  630                 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
  631                 if (m_new == NULL) {
  632                         printf("%s: no memory for rx list "
  633                             "-- packet dropped!\n", sc->cue_dev.dv_xname);
  634                         return (ENOBUFS);
  635                 }
  636 
  637                 MCLGET(m_new, M_DONTWAIT);
  638                 if (!(m_new->m_flags & M_EXT)) {
  639                         printf("%s: no memory for rx list "
  640                             "-- packet dropped!\n", sc->cue_dev.dv_xname);
  641                         m_freem(m_new);
  642                         return (ENOBUFS);
  643                 }
  644                 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
  645         } else {
  646                 m_new = m;
  647                 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
  648                 m_new->m_data = m_new->m_ext.ext_buf;
  649         }
  650 
  651         m_adj(m_new, ETHER_ALIGN);
  652         c->cue_mbuf = m_new;
  653 
  654         return (0);
  655 }
  656 
  657 int
  658 cue_rx_list_init(struct cue_softc *sc)
  659 {
  660         struct cue_cdata        *cd;
  661         struct cue_chain        *c;
  662         int                     i;
  663 
  664         cd = &sc->cue_cdata;
  665         for (i = 0; i < CUE_RX_LIST_CNT; i++) {
  666                 c = &cd->cue_rx_chain[i];
  667                 c->cue_sc = sc;
  668                 c->cue_idx = i;
  669                 if (cue_newbuf(sc, c, NULL) == ENOBUFS)
  670                         return (ENOBUFS);
  671                 if (c->cue_xfer == NULL) {
  672                         c->cue_xfer = usbd_alloc_xfer(sc->cue_udev);
  673                         if (c->cue_xfer == NULL)
  674                                 return (ENOBUFS);
  675                         c->cue_buf = usbd_alloc_buffer(c->cue_xfer, CUE_BUFSZ);
  676                         if (c->cue_buf == NULL) {
  677                                 usbd_free_xfer(c->cue_xfer);
  678                                 return (ENOBUFS);
  679                         }
  680                 }
  681         }
  682 
  683         return (0);
  684 }
  685 
  686 int
  687 cue_tx_list_init(struct cue_softc *sc)
  688 {
  689         struct cue_cdata        *cd;
  690         struct cue_chain        *c;
  691         int                     i;
  692 
  693         cd = &sc->cue_cdata;
  694         for (i = 0; i < CUE_TX_LIST_CNT; i++) {
  695                 c = &cd->cue_tx_chain[i];
  696                 c->cue_sc = sc;
  697                 c->cue_idx = i;
  698                 c->cue_mbuf = NULL;
  699                 if (c->cue_xfer == NULL) {
  700                         c->cue_xfer = usbd_alloc_xfer(sc->cue_udev);
  701                         if (c->cue_xfer == NULL)
  702                                 return (ENOBUFS);
  703                         c->cue_buf = usbd_alloc_buffer(c->cue_xfer, CUE_BUFSZ);
  704                         if (c->cue_buf == NULL) {
  705                                 usbd_free_xfer(c->cue_xfer);
  706                                 return (ENOBUFS);
  707                         }
  708                 }
  709         }
  710 
  711         return (0);
  712 }
  713 
  714 /*
  715  * A frame has been uploaded: pass the resulting mbuf chain up to
  716  * the higher level protocols.
  717  */
  718 void
  719 cue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
  720 {
  721         struct cue_chain        *c = priv;
  722         struct cue_softc        *sc = c->cue_sc;
  723         struct ifnet            *ifp = GET_IFP(sc);
  724         struct mbuf             *m;
  725         int                     total_len = 0;
  726         u_int16_t               len;
  727         int                     s;
  728 
  729         DPRINTFN(10,("%s: %s: enter status=%d\n", sc->cue_dev.dv_xname,
  730                      __func__, status));
  731 
  732         if (sc->cue_dying)
  733                 return;
  734 
  735         if (!(ifp->if_flags & IFF_RUNNING))
  736                 return;
  737 
  738         if (status != USBD_NORMAL_COMPLETION) {
  739                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
  740                         return;
  741                 sc->cue_rx_errs++;
  742                 if (usbd_ratecheck(&sc->cue_rx_notice)) {
  743                         printf("%s: %u usb errors on rx: %s\n",
  744                             sc->cue_dev.dv_xname, sc->cue_rx_errs,
  745                             usbd_errstr(status));
  746                         sc->cue_rx_errs = 0;
  747                 }
  748                 if (status == USBD_STALLED)
  749                         usbd_clear_endpoint_stall_async(sc->cue_ep[CUE_ENDPT_RX]);
  750                 goto done;
  751         }
  752 
  753         usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
  754 
  755         memcpy(mtod(c->cue_mbuf, char *), c->cue_buf, total_len);
  756 
  757         m = c->cue_mbuf;
  758         len = UGETW(mtod(m, u_int8_t *));
  759 
  760         /* No errors; receive the packet. */
  761         total_len = len;
  762 
  763         if (len < sizeof(struct ether_header)) {
  764                 ifp->if_ierrors++;
  765                 goto done;
  766         }
  767 
  768         ifp->if_ipackets++;
  769         m_adj(m, sizeof(u_int16_t));
  770         m->m_pkthdr.len = m->m_len = total_len;
  771 
  772         m->m_pkthdr.rcvif = ifp;
  773 
  774         s = splnet();
  775 
  776         /* XXX ugly */
  777         if (cue_newbuf(sc, c, NULL) == ENOBUFS) {
  778                 ifp->if_ierrors++;
  779                 goto done1;
  780         }
  781 
  782 #if NBPFILTER > 0
  783         /*
  784          * Handle BPF listeners. Let the BPF user see the packet, but
  785          * don't pass it up to the ether_input() layer unless it's
  786          * a broadcast packet, multicast packet, matches our ethernet
  787          * address or the interface is in promiscuous mode.
  788          */
  789         if (ifp->if_bpf)
  790                 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
  791 #endif
  792 
  793         DPRINTFN(10,("%s: %s: deliver %d\n", sc->cue_dev.dv_xname,
  794                     __func__, m->m_len));
  795         ether_input_mbuf(ifp, m);
  796  done1:
  797         splx(s);
  798 
  799 done:
  800         /* Setup new transfer. */
  801         usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX],
  802             c, c->cue_buf, CUE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
  803             USBD_NO_TIMEOUT, cue_rxeof);
  804         usbd_transfer(c->cue_xfer);
  805 
  806         DPRINTFN(10,("%s: %s: start rx\n", sc->cue_dev.dv_xname,
  807                     __func__));
  808 }
  809 
  810 /*
  811  * A frame was downloaded to the chip. It's safe for us to clean up
  812  * the list buffers.
  813  */
  814 void
  815 cue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
  816 {
  817         struct cue_chain        *c = priv;
  818         struct cue_softc        *sc = c->cue_sc;
  819         struct ifnet            *ifp = GET_IFP(sc);
  820         int                     s;
  821 
  822         if (sc->cue_dying)
  823                 return;
  824 
  825         s = splnet();
  826 
  827         DPRINTFN(10,("%s: %s: enter status=%d\n", sc->cue_dev.dv_xname,
  828                     __func__, status));
  829 
  830         ifp->if_timer = 0;
  831         ifp->if_flags &= ~IFF_OACTIVE;
  832 
  833         if (status != USBD_NORMAL_COMPLETION) {
  834                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
  835                         splx(s);
  836                         return;
  837                 }
  838                 ifp->if_oerrors++;
  839                 printf("%s: usb error on tx: %s\n", sc->cue_dev.dv_xname,
  840                     usbd_errstr(status));
  841                 if (status == USBD_STALLED)
  842                         usbd_clear_endpoint_stall_async(sc->cue_ep[CUE_ENDPT_TX]);
  843                 splx(s);
  844                 return;
  845         }
  846 
  847         ifp->if_opackets++;
  848 
  849         m_freem(c->cue_mbuf);
  850         c->cue_mbuf = NULL;
  851 
  852         if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
  853                 cue_start(ifp);
  854 
  855         splx(s);
  856 }
  857 
  858 void
  859 cue_tick(void *xsc)
  860 {
  861         struct cue_softc        *sc = xsc;
  862 
  863         if (sc == NULL)
  864                 return;
  865 
  866         if (sc->cue_dying)
  867                 return;
  868 
  869         DPRINTFN(2,("%s: %s: enter\n", sc->cue_dev.dv_xname, __func__));
  870 
  871         /* Perform statistics update in process context. */
  872         usb_add_task(sc->cue_udev, &sc->cue_tick_task);
  873 }
  874 
  875 void
  876 cue_tick_task(void *xsc)
  877 {
  878         struct cue_softc        *sc = xsc;
  879         struct ifnet            *ifp;
  880 
  881         if (sc->cue_dying)
  882                 return;
  883 
  884         DPRINTFN(2,("%s: %s: enter\n", sc->cue_dev.dv_xname, __func__));
  885 
  886         ifp = GET_IFP(sc);
  887 
  888         ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_SINGLECOLL);
  889         ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_MULTICOLL);
  890         ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_EXCESSCOLL);
  891 
  892         if (cue_csr_read_2(sc, CUE_RX_FRAMEERR))
  893                 ifp->if_ierrors++;
  894 }
  895 
  896 int
  897 cue_send(struct cue_softc *sc, struct mbuf *m, int idx)
  898 {
  899         int                     total_len;
  900         struct cue_chain        *c;
  901         usbd_status             err;
  902 
  903         c = &sc->cue_cdata.cue_tx_chain[idx];
  904 
  905         /*
  906          * Copy the mbuf data into a contiguous buffer, leaving two
  907          * bytes at the beginning to hold the frame length.
  908          */
  909         m_copydata(m, 0, m->m_pkthdr.len, c->cue_buf + 2);
  910         c->cue_mbuf = m;
  911 
  912         total_len = m->m_pkthdr.len + 2;
  913 
  914         DPRINTFN(10,("%s: %s: total_len=%d\n",
  915                      sc->cue_dev.dv_xname, __func__, total_len));
  916 
  917         /* The first two bytes are the frame length */
  918         c->cue_buf[0] = (u_int8_t)m->m_pkthdr.len;
  919         c->cue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8);
  920 
  921         /* XXX 10000 */
  922         usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_TX],
  923             c, c->cue_buf, total_len, USBD_NO_COPY, 10000, cue_txeof);
  924 
  925         /* Transmit */
  926         err = usbd_transfer(c->cue_xfer);
  927         if (err != USBD_IN_PROGRESS) {
  928                 printf("%s: cue_send error=%s\n", sc->cue_dev.dv_xname,
  929                        usbd_errstr(err));
  930                 /* Stop the interface from process context. */
  931                 usb_add_task(sc->cue_udev, &sc->cue_stop_task);
  932                 return (EIO);
  933         }
  934 
  935         sc->cue_cdata.cue_tx_cnt++;
  936 
  937         return (0);
  938 }
  939 
  940 void
  941 cue_start(struct ifnet *ifp)
  942 {
  943         struct cue_softc        *sc = ifp->if_softc;
  944         struct mbuf             *m_head = NULL;
  945 
  946         if (sc->cue_dying)
  947                 return;
  948 
  949         DPRINTFN(10,("%s: %s: enter\n", sc->cue_dev.dv_xname,__func__));
  950 
  951         if (ifp->if_flags & IFF_OACTIVE)
  952                 return;
  953 
  954         IFQ_POLL(&ifp->if_snd, m_head);
  955         if (m_head == NULL)
  956                 return;
  957 
  958         if (cue_send(sc, m_head, 0)) {
  959                 ifp->if_flags |= IFF_OACTIVE;
  960                 return;
  961         }
  962 
  963         IFQ_DEQUEUE(&ifp->if_snd, m_head);
  964 
  965 #if NBPFILTER > 0
  966         /*
  967          * If there's a BPF listener, bounce a copy of this frame
  968          * to him.
  969          */
  970         if (ifp->if_bpf)
  971                 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
  972 #endif
  973 
  974         ifp->if_flags |= IFF_OACTIVE;
  975 
  976         /*
  977          * Set a timeout in case the chip goes out to lunch.
  978          */
  979         ifp->if_timer = 5;
  980 }
  981 
  982 void
  983 cue_init(void *xsc)
  984 {
  985         struct cue_softc        *sc = xsc;
  986         struct ifnet            *ifp = GET_IFP(sc);
  987         int                     i, s, ctl;
  988         u_char                  *eaddr;
  989 
  990         if (sc->cue_dying)
  991                 return;
  992 
  993         DPRINTFN(10,("%s: %s: enter\n", sc->cue_dev.dv_xname,__func__));
  994 
  995         if (ifp->if_flags & IFF_RUNNING)
  996                 return;
  997 
  998         s = splnet();
  999 
 1000         /*
 1001          * Cancel pending I/O and free all RX/TX buffers.
 1002          */
 1003 #if 1
 1004         cue_reset(sc);
 1005 #endif
 1006 
 1007         /* Set advanced operation modes. */
 1008         cue_csr_write_1(sc, CUE_ADVANCED_OPMODES,
 1009             CUE_AOP_EMBED_RXLEN | 0x03); /* 1 wait state */
 1010 
 1011         eaddr = sc->arpcom.ac_enaddr;
 1012         /* Set MAC address */
 1013         for (i = 0; i < ETHER_ADDR_LEN; i++)
 1014                 cue_csr_write_1(sc, CUE_PAR0 - i, eaddr[i]);
 1015 
 1016         /* Enable RX logic. */
 1017         ctl = CUE_ETHCTL_RX_ON | CUE_ETHCTL_MCAST_ON;
 1018         if (ifp->if_flags & IFF_PROMISC)
 1019                 ctl |= CUE_ETHCTL_PROMISC;
 1020         cue_csr_write_1(sc, CUE_ETHCTL, ctl);
 1021 
 1022         /* Init TX ring. */
 1023         if (cue_tx_list_init(sc) == ENOBUFS) {
 1024                 printf("%s: tx list init failed\n", sc->cue_dev.dv_xname);
 1025                 splx(s);
 1026                 return;
 1027         }
 1028 
 1029         /* Init RX ring. */
 1030         if (cue_rx_list_init(sc) == ENOBUFS) {
 1031                 printf("%s: rx list init failed\n", sc->cue_dev.dv_xname);
 1032                 splx(s);
 1033                 return;
 1034         }
 1035 
 1036         /* Load the multicast filter. */
 1037         cue_setmulti(sc);
 1038 
 1039         /*
 1040          * Set the number of RX and TX buffers that we want
 1041          * to reserve inside the ASIC.
 1042          */
 1043         cue_csr_write_1(sc, CUE_RX_BUFPKTS, CUE_RX_FRAMES);
 1044         cue_csr_write_1(sc, CUE_TX_BUFPKTS, CUE_TX_FRAMES);
 1045 
 1046         /* Set advanced operation modes. */
 1047         cue_csr_write_1(sc, CUE_ADVANCED_OPMODES,
 1048             CUE_AOP_EMBED_RXLEN | 0x01); /* 1 wait state */
 1049 
 1050         /* Program the LED operation. */
 1051         cue_csr_write_1(sc, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK);
 1052 
 1053         if (sc->cue_ep[CUE_ENDPT_RX] == NULL) {
 1054                 if (cue_open_pipes(sc)) {
 1055                         splx(s);
 1056                         return;
 1057                 }
 1058         }
 1059 
 1060         ifp->if_flags |= IFF_RUNNING;
 1061         ifp->if_flags &= ~IFF_OACTIVE;
 1062 
 1063         splx(s);
 1064 
 1065         timeout_del(&sc->cue_stat_ch);
 1066         timeout_set(&sc->cue_stat_ch, cue_tick, sc);
 1067         timeout_add(&sc->cue_stat_ch, hz);
 1068 }
 1069 
 1070 int
 1071 cue_open_pipes(struct cue_softc *sc)
 1072 {
 1073         struct cue_chain        *c;
 1074         usbd_status             err;
 1075         int                     i;
 1076 
 1077         /* Open RX and TX pipes. */
 1078         err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_RX],
 1079             USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_RX]);
 1080         if (err) {
 1081                 printf("%s: open rx pipe failed: %s\n",
 1082                     sc->cue_dev.dv_xname, usbd_errstr(err));
 1083                 return (EIO);
 1084         }
 1085         err = usbd_open_pipe(sc->cue_iface, sc->cue_ed[CUE_ENDPT_TX],
 1086             USBD_EXCLUSIVE_USE, &sc->cue_ep[CUE_ENDPT_TX]);
 1087         if (err) {
 1088                 printf("%s: open tx pipe failed: %s\n",
 1089                     sc->cue_dev.dv_xname, usbd_errstr(err));
 1090                 return (EIO);
 1091         }
 1092 
 1093         /* Start up the receive pipe. */
 1094         for (i = 0; i < CUE_RX_LIST_CNT; i++) {
 1095                 c = &sc->cue_cdata.cue_rx_chain[i];
 1096                 usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX],
 1097                     c, c->cue_buf, CUE_BUFSZ,
 1098                     USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
 1099                     cue_rxeof);
 1100                 usbd_transfer(c->cue_xfer);
 1101         }
 1102 
 1103         return (0);
 1104 }
 1105 
 1106 int
 1107 cue_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 1108 {
 1109         struct cue_softc        *sc = ifp->if_softc;
 1110         struct ifaddr           *ifa = (struct ifaddr *)data;
 1111         struct ifreq            *ifr = (struct ifreq *)data;
 1112         int                     s, error = 0;
 1113 
 1114         if (sc->cue_dying)
 1115                 return (EIO);
 1116 
 1117         s = splnet();
 1118 
 1119         switch(command) {
 1120         case SIOCSIFADDR:
 1121                 ifp->if_flags |= IFF_UP;
 1122                 cue_init(sc);
 1123 
 1124                 switch (ifa->ifa_addr->sa_family) {
 1125 #ifdef INET
 1126                 case AF_INET:
 1127                         arp_ifinit(&sc->arpcom, ifa);
 1128                         break;
 1129 #endif /* INET */
 1130                 }
 1131                 break;
 1132 
 1133         case SIOCSIFMTU:
 1134                 if (ifr->ifr_mtu > ETHERMTU)
 1135                         error = EINVAL;
 1136                 else
 1137                         ifp->if_mtu = ifr->ifr_mtu;
 1138                 break;
 1139 
 1140         case SIOCSIFFLAGS:
 1141                 if (ifp->if_flags & IFF_UP) {
 1142                         if (ifp->if_flags & IFF_RUNNING &&
 1143                             ifp->if_flags & IFF_PROMISC &&
 1144                             !(sc->cue_if_flags & IFF_PROMISC)) {
 1145                                 CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
 1146                                 cue_setmulti(sc);
 1147                         } else if (ifp->if_flags & IFF_RUNNING &&
 1148                             !(ifp->if_flags & IFF_PROMISC) &&
 1149                             sc->cue_if_flags & IFF_PROMISC) {
 1150                                 CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC);
 1151                                 cue_setmulti(sc);
 1152                         } else if (!(ifp->if_flags & IFF_RUNNING))
 1153                                 cue_init(sc);
 1154                 } else {
 1155                         if (ifp->if_flags & IFF_RUNNING)
 1156                                 cue_stop(sc);
 1157                 }
 1158                 sc->cue_if_flags = ifp->if_flags;
 1159                 error = 0;
 1160                 break;
 1161         case SIOCADDMULTI:
 1162         case SIOCDELMULTI:
 1163                 error = (command == SIOCADDMULTI) ?
 1164                     ether_addmulti(ifr, &sc->arpcom) :
 1165                     ether_delmulti(ifr, &sc->arpcom);
 1166 
 1167                 if (error == ENETRESET) {
 1168                         /*
 1169                          * Multicast list has changed; set the hardware
 1170                          * filter accordingly.
 1171                          */
 1172                         if (ifp->if_flags & IFF_RUNNING)
 1173                                 cue_setmulti(sc);
 1174                         error = 0;
 1175                 }
 1176                 break;
 1177         default:
 1178                 error = EINVAL;
 1179                 break;
 1180         }
 1181 
 1182         splx(s);
 1183 
 1184         return (error);
 1185 }
 1186 
 1187 void
 1188 cue_watchdog(struct ifnet *ifp)
 1189 {
 1190         struct cue_softc        *sc = ifp->if_softc;
 1191         struct cue_chain        *c;
 1192         usbd_status             stat;
 1193         int                     s;
 1194 
 1195         DPRINTFN(5,("%s: %s: enter\n", sc->cue_dev.dv_xname,__func__));
 1196 
 1197         if (sc->cue_dying)
 1198                 return;
 1199 
 1200         ifp->if_oerrors++;
 1201         printf("%s: watchdog timeout\n", sc->cue_dev.dv_xname);
 1202 
 1203         s = splusb();
 1204         c = &sc->cue_cdata.cue_tx_chain[0];
 1205         usbd_get_xfer_status(c->cue_xfer, NULL, NULL, NULL, &stat);
 1206         cue_txeof(c->cue_xfer, c, stat);
 1207 
 1208         if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
 1209                 cue_start(ifp);
 1210         splx(s);
 1211 }
 1212 
 1213 /*
 1214  * Stop the adapter and free any mbufs allocated to the
 1215  * RX and TX lists.
 1216  */
 1217 void
 1218 cue_stop(struct cue_softc *sc)
 1219 {
 1220         usbd_status             err;
 1221         struct ifnet            *ifp;
 1222         int                     i;
 1223 
 1224         DPRINTFN(10,("%s: %s: enter\n", sc->cue_dev.dv_xname,__func__));
 1225 
 1226         ifp = GET_IFP(sc);
 1227         ifp->if_timer = 0;
 1228         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
 1229 
 1230         cue_csr_write_1(sc, CUE_ETHCTL, 0);
 1231         cue_reset(sc);
 1232         timeout_del(&sc->cue_stat_ch);
 1233 
 1234         /* Stop transfers. */
 1235         if (sc->cue_ep[CUE_ENDPT_RX] != NULL) {
 1236                 err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_RX]);
 1237                 if (err) {
 1238                         printf("%s: abort rx pipe failed: %s\n",
 1239                         sc->cue_dev.dv_xname, usbd_errstr(err));
 1240                 }
 1241                 err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_RX]);
 1242                 if (err) {
 1243                         printf("%s: close rx pipe failed: %s\n",
 1244                         sc->cue_dev.dv_xname, usbd_errstr(err));
 1245                 }
 1246                 sc->cue_ep[CUE_ENDPT_RX] = NULL;
 1247         }
 1248 
 1249         if (sc->cue_ep[CUE_ENDPT_TX] != NULL) {
 1250                 err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_TX]);
 1251                 if (err) {
 1252                         printf("%s: abort tx pipe failed: %s\n",
 1253                         sc->cue_dev.dv_xname, usbd_errstr(err));
 1254                 }
 1255                 err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_TX]);
 1256                 if (err) {
 1257                         printf("%s: close tx pipe failed: %s\n",
 1258                             sc->cue_dev.dv_xname, usbd_errstr(err));
 1259                 }
 1260                 sc->cue_ep[CUE_ENDPT_TX] = NULL;
 1261         }
 1262 
 1263         if (sc->cue_ep[CUE_ENDPT_INTR] != NULL) {
 1264                 err = usbd_abort_pipe(sc->cue_ep[CUE_ENDPT_INTR]);
 1265                 if (err) {
 1266                         printf("%s: abort intr pipe failed: %s\n",
 1267                         sc->cue_dev.dv_xname, usbd_errstr(err));
 1268                 }
 1269                 err = usbd_close_pipe(sc->cue_ep[CUE_ENDPT_INTR]);
 1270                 if (err) {
 1271                         printf("%s: close intr pipe failed: %s\n",
 1272                             sc->cue_dev.dv_xname, usbd_errstr(err));
 1273                 }
 1274                 sc->cue_ep[CUE_ENDPT_INTR] = NULL;
 1275         }
 1276 
 1277         /* Free RX resources. */
 1278         for (i = 0; i < CUE_RX_LIST_CNT; i++) {
 1279                 if (sc->cue_cdata.cue_rx_chain[i].cue_mbuf != NULL) {
 1280                         m_freem(sc->cue_cdata.cue_rx_chain[i].cue_mbuf);
 1281                         sc->cue_cdata.cue_rx_chain[i].cue_mbuf = NULL;
 1282                 }
 1283                 if (sc->cue_cdata.cue_rx_chain[i].cue_xfer != NULL) {
 1284                         usbd_free_xfer(sc->cue_cdata.cue_rx_chain[i].cue_xfer);
 1285                         sc->cue_cdata.cue_rx_chain[i].cue_xfer = NULL;
 1286                 }
 1287         }
 1288 
 1289         /* Free TX resources. */
 1290         for (i = 0; i < CUE_TX_LIST_CNT; i++) {
 1291                 if (sc->cue_cdata.cue_tx_chain[i].cue_mbuf != NULL) {
 1292                         m_freem(sc->cue_cdata.cue_tx_chain[i].cue_mbuf);
 1293                         sc->cue_cdata.cue_tx_chain[i].cue_mbuf = NULL;
 1294                 }
 1295                 if (sc->cue_cdata.cue_tx_chain[i].cue_xfer != NULL) {
 1296                         usbd_free_xfer(sc->cue_cdata.cue_tx_chain[i].cue_xfer);
 1297                         sc->cue_cdata.cue_tx_chain[i].cue_xfer = NULL;
 1298                 }
 1299         }
 1300 }

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