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

Cache object: db37efc93f4ca4741205792a2089e64c


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