[BACK]Return to if_cue.c CVS log [TXT][DIR] Up to [local] / sys / dev / usb

Annotation of sys/dev/usb/if_cue.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb