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

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

1.1       nbrk        1: /*     $OpenBSD: if_upl.c,v 1.38 2007/06/14 10:11:15 mbalmer Exp $ */
                      2: /*     $NetBSD: if_upl.c,v 1.19 2002/07/11 21:14:26 augustss Exp $     */
                      3: /*
                      4:  * Copyright (c) 2000 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Lennart Augustsson (lennart@augustsson.net) at
                      9:  * Carlstedt Research & Technology.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *        This product includes software developed by the NetBSD
                     22:  *        Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
                     41:  * Prolific PL2301/PL2302 driver
                     42:  */
                     43:
                     44: #include "bpfilter.h"
                     45:
                     46: #include <sys/param.h>
                     47: #include <sys/systm.h>
                     48: #include <sys/timeout.h>
                     49: #include <sys/sockio.h>
                     50: #include <sys/mbuf.h>
                     51: #include <sys/malloc.h>
                     52: #include <sys/kernel.h>
                     53: #include <sys/socket.h>
                     54:
                     55: #include <sys/device.h>
                     56:
                     57: #include <net/if.h>
                     58: #include <net/if_types.h>
                     59: #include <net/if_dl.h>
                     60: #include <net/netisr.h>
                     61:
                     62: #if NBPFILTER > 0
                     63: #include <net/bpf.h>
                     64: #endif
                     65:
                     66: #ifdef INET
                     67: #include <netinet/in.h>
                     68: #include <netinet/in_var.h>
                     69: #include <netinet/in_systm.h>
                     70: #include <netinet/ip.h>
                     71: #include <netinet/if_ether.h>
                     72: #else
                     73: #error upl without INET?
                     74: #endif
                     75:
                     76: #include <dev/usb/usb.h>
                     77: #include <dev/usb/usbdi.h>
                     78: #include <dev/usb/usbdi_util.h>
                     79: #include <dev/usb/usbdevs.h>
                     80:
                     81: /*
                     82:  * 7  6  5  4  3  2  1  0
                     83:  * tx rx 1  0
                     84:  * 1110 0000 rxdata
                     85:  * 1010 0000 idle
                     86:  * 0010 0000 tx over
                     87:  * 0110      tx over + rxd
                     88:  */
                     89:
                     90: #define UPL_RXDATA             0x40
                     91: #define UPL_TXOK               0x80
                     92:
                     93: #define UPL_INTR_PKTLEN                1
                     94:
                     95: #define UPL_CONFIG_NO          1
                     96: #define UPL_IFACE_IDX          0
                     97:
                     98: /***/
                     99:
                    100: #define UPL_INTR_INTERVAL      20
                    101:
                    102: #define UPL_BUFSZ              1024
                    103:
                    104: #define UPL_RX_FRAMES          1
                    105: #define UPL_TX_FRAMES          1
                    106:
                    107: #define UPL_RX_LIST_CNT                1
                    108: #define UPL_TX_LIST_CNT                1
                    109:
                    110: #define UPL_ENDPT_RX           0x0
                    111: #define UPL_ENDPT_TX           0x1
                    112: #define UPL_ENDPT_INTR         0x2
                    113: #define UPL_ENDPT_MAX          0x3
                    114:
                    115: struct upl_type {
                    116:        u_int16_t               upl_vid;
                    117:        u_int16_t               upl_did;
                    118: };
                    119:
                    120: struct upl_softc;
                    121:
                    122: struct upl_chain {
                    123:        struct upl_softc        *upl_sc;
                    124:        usbd_xfer_handle        upl_xfer;
                    125:        char                    *upl_buf;
                    126:        struct mbuf             *upl_mbuf;
                    127:        int                     upl_idx;
                    128: };
                    129:
                    130: struct upl_cdata {
                    131:        struct upl_chain        upl_tx_chain[UPL_TX_LIST_CNT];
                    132:        struct upl_chain        upl_rx_chain[UPL_RX_LIST_CNT];
                    133:        int                     upl_tx_prod;
                    134:        int                     upl_tx_cons;
                    135:        int                     upl_tx_cnt;
                    136:        int                     upl_rx_prod;
                    137: };
                    138:
                    139: struct upl_softc {
                    140:        struct device           sc_dev;
                    141:
                    142:        struct ifnet            sc_if;
                    143:        struct timeout          sc_stat_ch;
                    144:
                    145:        usbd_device_handle      sc_udev;
                    146:        usbd_interface_handle   sc_iface;
                    147:        u_int16_t               sc_vendor;
                    148:        u_int16_t               sc_product;
                    149:        int                     sc_ed[UPL_ENDPT_MAX];
                    150:        usbd_pipe_handle        sc_ep[UPL_ENDPT_MAX];
                    151:        struct upl_cdata        sc_cdata;
                    152:
                    153:        uByte                   sc_ibuf;
                    154:
                    155:        char                    sc_dying;
                    156:        char                    sc_attached;
                    157:        u_int                   sc_rx_errs;
                    158:        struct timeval          sc_rx_notice;
                    159:        u_int                   sc_intr_errs;
                    160: };
                    161:
                    162: #ifdef UPL_DEBUG
                    163: #define DPRINTF(x)     do { if (upldebug) printf x; } while (0)
                    164: #define DPRINTFN(n,x)  do { if (upldebug >= (n)) printf x; } while (0)
                    165: int    upldebug = 0;
                    166: #else
                    167: #define DPRINTF(x)
                    168: #define DPRINTFN(n,x)
                    169: #endif
                    170:
                    171: /*
                    172:  * Various supported device vendors/products.
                    173:  */
                    174: struct upl_type sc_devs[] = {
                    175:        { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301 },
                    176:        { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302 },
                    177:        { 0, 0 }
                    178: };
                    179:
                    180: int upl_match(struct device *, void *, void *);
                    181: void upl_attach(struct device *, struct device *, void *);
                    182: int upl_detach(struct device *, int);
                    183: int upl_activate(struct device *, enum devact);
                    184:
                    185: struct cfdriver upl_cd = {
                    186:        NULL, "upl", DV_IFNET
                    187: };
                    188:
                    189: const struct cfattach upl_ca = {
                    190:        sizeof(struct upl_softc),
                    191:        upl_match,
                    192:        upl_attach,
                    193:        upl_detach,
                    194:        upl_activate,
                    195: };
                    196:
                    197: int upl_openpipes(struct upl_softc *);
                    198: int upl_tx_list_init(struct upl_softc *);
                    199: int upl_rx_list_init(struct upl_softc *);
                    200: int upl_newbuf(struct upl_softc *, struct upl_chain *, struct mbuf *);
                    201: int upl_send(struct upl_softc *, struct mbuf *, int);
                    202: void upl_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
                    203: void upl_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
                    204: void upl_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
                    205: void upl_start(struct ifnet *);
                    206: int upl_ioctl(struct ifnet *, u_long, caddr_t);
                    207: void upl_init(void *);
                    208: void upl_stop(struct upl_softc *);
                    209: void upl_watchdog(struct ifnet *);
                    210:
                    211: int upl_output(struct ifnet *, struct mbuf *, struct sockaddr *,
                    212:                      struct rtentry *);
                    213: void upl_input(struct ifnet *, struct mbuf *);
                    214:
                    215: /*
                    216:  * Probe for a Prolific chip.
                    217:  */
                    218: int
                    219: upl_match(struct device *parent, void *match, void *aux)
                    220: {
                    221:        struct usb_attach_arg           *uaa = aux;
                    222:        struct upl_type                 *t;
                    223:
                    224:        if (uaa->iface != NULL)
                    225:                return (UMATCH_NONE);
                    226:
                    227:        for (t = sc_devs; t->upl_vid != 0; t++)
                    228:                if (uaa->vendor == t->upl_vid && uaa->product == t->upl_did)
                    229:                        return (UMATCH_VENDOR_PRODUCT);
                    230:
                    231:        return (UMATCH_NONE);
                    232: }
                    233:
                    234: void
                    235: upl_attach(struct device *parent, struct device *self, void *aux)
                    236: {
                    237:        struct upl_softc        *sc = (struct upl_softc *)self;
                    238:        struct usb_attach_arg   *uaa = aux;
                    239:        char                    *devinfop;
                    240:        int                     s;
                    241:        usbd_device_handle      dev = uaa->device;
                    242:        usbd_interface_handle   iface;
                    243:        usbd_status             err;
                    244:        struct ifnet            *ifp;
                    245:        usb_interface_descriptor_t      *id;
                    246:        usb_endpoint_descriptor_t       *ed;
                    247:        int                     i;
                    248:
                    249:        DPRINTFN(5,(" : upl_attach: sc=%p, dev=%p", sc, dev));
                    250:
                    251:        devinfop = usbd_devinfo_alloc(dev, 0);
                    252:        printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
                    253:        usbd_devinfo_free(devinfop);
                    254:
                    255:        err = usbd_set_config_no(dev, UPL_CONFIG_NO, 1);
                    256:        if (err) {
                    257:                printf("%s: setting config no failed\n",
                    258:                    sc->sc_dev.dv_xname);
                    259:                return;
                    260:        }
                    261:
                    262:        sc->sc_udev = dev;
                    263:        sc->sc_product = uaa->product;
                    264:        sc->sc_vendor = uaa->vendor;
                    265:
                    266:        err = usbd_device2interface_handle(dev, UPL_IFACE_IDX, &iface);
                    267:        if (err) {
                    268:                printf("%s: getting interface handle failed\n",
                    269:                    sc->sc_dev.dv_xname);
                    270:                return;
                    271:        }
                    272:
                    273:        sc->sc_iface = iface;
                    274:        id = usbd_get_interface_descriptor(iface);
                    275:
                    276:        /* Find endpoints. */
                    277:        for (i = 0; i < id->bNumEndpoints; i++) {
                    278:                ed = usbd_interface2endpoint_descriptor(iface, i);
                    279:                if (ed == NULL) {
                    280:                        printf("%s: couldn't get ep %d\n",
                    281:                            sc->sc_dev.dv_xname, i);
                    282:                        return;
                    283:                }
                    284:                if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
                    285:                    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
                    286:                        sc->sc_ed[UPL_ENDPT_RX] = ed->bEndpointAddress;
                    287:                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
                    288:                           UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
                    289:                        sc->sc_ed[UPL_ENDPT_TX] = ed->bEndpointAddress;
                    290:                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
                    291:                           UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
                    292:                        sc->sc_ed[UPL_ENDPT_INTR] = ed->bEndpointAddress;
                    293:                }
                    294:        }
                    295:
                    296:        if (sc->sc_ed[UPL_ENDPT_RX] == 0 || sc->sc_ed[UPL_ENDPT_TX] == 0 ||
                    297:            sc->sc_ed[UPL_ENDPT_INTR] == 0) {
                    298:                printf("%s: missing endpoint\n", sc->sc_dev.dv_xname);
                    299:                return;
                    300:        }
                    301:
                    302:        s = splnet();
                    303:
                    304:        /* Initialize interface info.*/
                    305:        ifp = &sc->sc_if;
                    306:        ifp->if_softc = sc;
                    307:        ifp->if_mtu = UPL_BUFSZ;
                    308:        ifp->if_flags = IFF_POINTOPOINT | IFF_NOARP | IFF_SIMPLEX;
                    309:        ifp->if_ioctl = upl_ioctl;
                    310:        ifp->if_start = upl_start;
                    311:        ifp->if_watchdog = upl_watchdog;
                    312:        strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
                    313:
                    314:        ifp->if_type = IFT_OTHER;
                    315:        ifp->if_addrlen = 0;
                    316:        ifp->if_hdrlen = 0;
                    317:        ifp->if_output = upl_output;
                    318:        ifp->if_baudrate = 12000000;
                    319:        IFQ_SET_READY(&ifp->if_snd);
                    320:
                    321:        /* Attach the interface. */
                    322:        if_attach(ifp);
                    323:        if_alloc_sadl(ifp);
                    324:
                    325:        sc->sc_attached = 1;
                    326:        splx(s);
                    327:
                    328:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
                    329:            &sc->sc_dev);
                    330: }
                    331:
                    332: int
                    333: upl_detach(struct device *self, int flags)
                    334: {
                    335:        struct upl_softc        *sc = (struct upl_softc *)self;
                    336:        struct ifnet            *ifp = &sc->sc_if;
                    337:        int                     s;
                    338:
                    339:        DPRINTFN(2,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    340:
                    341:        s = splusb();
                    342:
                    343:        if (!sc->sc_attached) {
                    344:                /* Detached before attached finished, so just bail out. */
                    345:                splx(s);
                    346:                return (0);
                    347:        }
                    348:
                    349:        if (ifp->if_flags & IFF_RUNNING)
                    350:                upl_stop(sc);
                    351:
                    352:        if_detach(ifp);
                    353:
                    354: #ifdef DIAGNOSTIC
                    355:        if (sc->sc_ep[UPL_ENDPT_TX] != NULL ||
                    356:            sc->sc_ep[UPL_ENDPT_RX] != NULL ||
                    357:            sc->sc_ep[UPL_ENDPT_INTR] != NULL)
                    358:                printf("%s: detach has active endpoints\n",
                    359:                       sc->sc_dev.dv_xname);
                    360: #endif
                    361:
                    362:        sc->sc_attached = 0;
                    363:        splx(s);
                    364:
                    365:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
                    366:            &sc->sc_dev);
                    367:
                    368:        return (0);
                    369: }
                    370:
                    371: int
                    372: upl_activate(struct device *self, enum devact act)
                    373: {
                    374:        struct upl_softc *sc = (struct upl_softc *)self;
                    375:
                    376:        DPRINTFN(2,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    377:
                    378:        switch (act) {
                    379:        case DVACT_ACTIVATE:
                    380:                break;
                    381:
                    382:        case DVACT_DEACTIVATE:
                    383:                sc->sc_dying = 1;
                    384:                break;
                    385:        }
                    386:        return (0);
                    387: }
                    388:
                    389: /*
                    390:  * Initialize an RX descriptor and attach an MBUF cluster.
                    391:  */
                    392: int
                    393: upl_newbuf(struct upl_softc *sc, struct upl_chain *c, struct mbuf *m)
                    394: {
                    395:        struct mbuf             *m_new = NULL;
                    396:
                    397:        DPRINTFN(8,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    398:
                    399:        if (m == NULL) {
                    400:                MGETHDR(m_new, M_DONTWAIT, MT_DATA);
                    401:                if (m_new == NULL) {
                    402:                        printf("%s: no memory for rx list "
                    403:                            "-- packet dropped!\n", sc->sc_dev.dv_xname);
                    404:                        return (ENOBUFS);
                    405:                }
                    406:
                    407:                MCLGET(m_new, M_DONTWAIT);
                    408:                if (!(m_new->m_flags & M_EXT)) {
                    409:                        printf("%s: no memory for rx list "
                    410:                            "-- packet dropped!\n", sc->sc_dev.dv_xname);
                    411:                        m_freem(m_new);
                    412:                        return (ENOBUFS);
                    413:                }
                    414:                m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
                    415:        } else {
                    416:                m_new = m;
                    417:                m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
                    418:                m_new->m_data = m_new->m_ext.ext_buf;
                    419:        }
                    420:
                    421:        c->upl_mbuf = m_new;
                    422:
                    423:        return (0);
                    424: }
                    425:
                    426: int
                    427: upl_rx_list_init(struct upl_softc *sc)
                    428: {
                    429:        struct upl_cdata        *cd;
                    430:        struct upl_chain        *c;
                    431:        int                     i;
                    432:
                    433:        DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    434:
                    435:        cd = &sc->sc_cdata;
                    436:        for (i = 0; i < UPL_RX_LIST_CNT; i++) {
                    437:                c = &cd->upl_rx_chain[i];
                    438:                c->upl_sc = sc;
                    439:                c->upl_idx = i;
                    440:                if (upl_newbuf(sc, c, NULL) == ENOBUFS)
                    441:                        return (ENOBUFS);
                    442:                if (c->upl_xfer == NULL) {
                    443:                        c->upl_xfer = usbd_alloc_xfer(sc->sc_udev);
                    444:                        if (c->upl_xfer == NULL)
                    445:                                return (ENOBUFS);
                    446:                        c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ);
                    447:                        if (c->upl_buf == NULL) {
                    448:                                usbd_free_xfer(c->upl_xfer);
                    449:                                return (ENOBUFS);
                    450:                        }
                    451:                }
                    452:        }
                    453:
                    454:        return (0);
                    455: }
                    456:
                    457: int
                    458: upl_tx_list_init(struct upl_softc *sc)
                    459: {
                    460:        struct upl_cdata        *cd;
                    461:        struct upl_chain        *c;
                    462:        int                     i;
                    463:
                    464:        DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
                    465:
                    466:        cd = &sc->sc_cdata;
                    467:        for (i = 0; i < UPL_TX_LIST_CNT; i++) {
                    468:                c = &cd->upl_tx_chain[i];
                    469:                c->upl_sc = sc;
                    470:                c->upl_idx = i;
                    471:                c->upl_mbuf = NULL;
                    472:                if (c->upl_xfer == NULL) {
                    473:                        c->upl_xfer = usbd_alloc_xfer(sc->sc_udev);
                    474:                        if (c->upl_xfer == NULL)
                    475:                                return (ENOBUFS);
                    476:                        c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ);
                    477:                        if (c->upl_buf == NULL) {
                    478:                                usbd_free_xfer(c->upl_xfer);
                    479:                                return (ENOBUFS);
                    480:                        }
                    481:                }
                    482:        }
                    483:
                    484:        return (0);
                    485: }
                    486:
                    487: /*
                    488:  * A frame has been uploaded: pass the resulting mbuf chain up to
                    489:  * the higher level protocols.
                    490:  */
                    491: void
                    492: upl_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
                    493: {
                    494:        struct upl_chain        *c = priv;
                    495:        struct upl_softc        *sc = c->upl_sc;
                    496:        struct ifnet            *ifp = &sc->sc_if;
                    497:        struct mbuf             *m;
                    498:        int                     total_len = 0;
                    499:        int                     s;
                    500:
                    501:        if (sc->sc_dying)
                    502:                return;
                    503:
                    504:        if (!(ifp->if_flags & IFF_RUNNING))
                    505:                return;
                    506:
                    507:        if (status != USBD_NORMAL_COMPLETION) {
                    508:                if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
                    509:                        return;
                    510:                sc->sc_rx_errs++;
                    511:                if (usbd_ratecheck(&sc->sc_rx_notice)) {
                    512:                        printf("%s: %u usb errors on rx: %s\n",
                    513:                            sc->sc_dev.dv_xname, sc->sc_rx_errs,
                    514:                            usbd_errstr(status));
                    515:                        sc->sc_rx_errs = 0;
                    516:                }
                    517:                if (status == USBD_STALLED)
                    518:                        usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]);
                    519:                goto done;
                    520:        }
                    521:
                    522:        usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
                    523:
                    524:        DPRINTFN(9,("%s: %s: enter status=%d length=%d\n",
                    525:                    sc->sc_dev.dv_xname, __func__, status, total_len));
                    526:
                    527:        m = c->upl_mbuf;
                    528:        memcpy(mtod(c->upl_mbuf, char *), c->upl_buf, total_len);
                    529:
                    530:        ifp->if_ipackets++;
                    531:        m->m_pkthdr.len = m->m_len = total_len;
                    532:
                    533:        m->m_pkthdr.rcvif = ifp;
                    534:
                    535:        s = splnet();
                    536:
                    537:        /* XXX ugly */
                    538:        if (upl_newbuf(sc, c, NULL) == ENOBUFS) {
                    539:                ifp->if_ierrors++;
                    540:                goto done1;
                    541:        }
                    542:
                    543: #if NBPFILTER > 0
                    544:        /*
                    545:         * Handle BPF listeners. Let the BPF user see the packet, but
                    546:         * don't pass it up to the ether_input() layer unless it's
                    547:         * a broadcast packet, multicast packet, matches our ethernet
                    548:         * address or the interface is in promiscuous mode.
                    549:         */
                    550:        if (ifp->if_bpf) {
                    551:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                    552:        }
                    553: #endif
                    554:
                    555:        DPRINTFN(10,("%s: %s: deliver %d\n", sc->sc_dev.dv_xname,
                    556:                    __func__, m->m_len));
                    557:
                    558:        ether_input_mbuf(ifp, m);
                    559:
                    560:  done1:
                    561:        splx(s);
                    562:
                    563:  done:
                    564: #if 1
                    565:        /* Setup new transfer. */
                    566:        usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX],
                    567:            c, c->upl_buf, UPL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
                    568:            USBD_NO_TIMEOUT, upl_rxeof);
                    569:        usbd_transfer(c->upl_xfer);
                    570:
                    571:        DPRINTFN(10,("%s: %s: start rx\n", sc->sc_dev.dv_xname,
                    572:                    __func__));
                    573: #endif
                    574: }
                    575:
                    576: /*
                    577:  * A frame was downloaded to the chip. It's safe for us to clean up
                    578:  * the list buffers.
                    579:  */
                    580: void
                    581: upl_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
                    582: {
                    583:        struct upl_chain        *c = priv;
                    584:        struct upl_softc        *sc = c->upl_sc;
                    585:        struct ifnet            *ifp = &sc->sc_if;
                    586:        int                     s;
                    587:
                    588:        if (sc->sc_dying)
                    589:                return;
                    590:
                    591:        s = splnet();
                    592:
                    593:        DPRINTFN(10,("%s: %s: enter status=%d\n", sc->sc_dev.dv_xname,
                    594:                    __func__, status));
                    595:
                    596:        ifp->if_timer = 0;
                    597:        ifp->if_flags &= ~IFF_OACTIVE;
                    598:
                    599:        if (status != USBD_NORMAL_COMPLETION) {
                    600:                if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
                    601:                        splx(s);
                    602:                        return;
                    603:                }
                    604:                ifp->if_oerrors++;
                    605:                printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname,
                    606:                    usbd_errstr(status));
                    607:                if (status == USBD_STALLED)
                    608:                        usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_TX]);
                    609:                splx(s);
                    610:                return;
                    611:        }
                    612:
                    613:        ifp->if_opackets++;
                    614:
                    615:        m_freem(c->upl_mbuf);
                    616:        c->upl_mbuf = NULL;
                    617:
                    618:        if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
                    619:                upl_start(ifp);
                    620:
                    621:        splx(s);
                    622: }
                    623:
                    624: int
                    625: upl_send(struct upl_softc *sc, struct mbuf *m, int idx)
                    626: {
                    627:        int                     total_len;
                    628:        struct upl_chain        *c;
                    629:        usbd_status             err;
                    630:
                    631:        c = &sc->sc_cdata.upl_tx_chain[idx];
                    632:
                    633:        /*
                    634:         * Copy the mbuf data into a contiguous buffer, leaving two
                    635:         * bytes at the beginning to hold the frame length.
                    636:         */
                    637:        m_copydata(m, 0, m->m_pkthdr.len, c->upl_buf);
                    638:        c->upl_mbuf = m;
                    639:
                    640:        total_len = m->m_pkthdr.len;
                    641:
                    642:        DPRINTFN(10,("%s: %s: total_len=%d\n",
                    643:                     sc->sc_dev.dv_xname, __func__, total_len));
                    644:
                    645:        usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_TX],
                    646:            c, c->upl_buf, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT,
                    647:            upl_txeof);
                    648:
                    649:        /* Transmit */
                    650:        err = usbd_transfer(c->upl_xfer);
                    651:        if (err != USBD_IN_PROGRESS) {
                    652:                printf("%s: upl_send error=%s\n", sc->sc_dev.dv_xname,
                    653:                       usbd_errstr(err));
                    654:                upl_stop(sc);
                    655:                return (EIO);
                    656:        }
                    657:
                    658:        sc->sc_cdata.upl_tx_cnt++;
                    659:
                    660:        return (0);
                    661: }
                    662:
                    663: void
                    664: upl_start(struct ifnet *ifp)
                    665: {
                    666:        struct upl_softc        *sc = ifp->if_softc;
                    667:        struct mbuf             *m_head = NULL;
                    668:
                    669:        if (sc->sc_dying)
                    670:                return;
                    671:
                    672:        DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
                    673:
                    674:        if (ifp->if_flags & IFF_OACTIVE)
                    675:                return;
                    676:
                    677:        IFQ_POLL(&ifp->if_snd, m_head);
                    678:        if (m_head == NULL)
                    679:                return;
                    680:
                    681:        if (upl_send(sc, m_head, 0)) {
                    682:                ifp->if_flags |= IFF_OACTIVE;
                    683:                return;
                    684:        }
                    685:
                    686:        IFQ_DEQUEUE(&ifp->if_snd, m_head);
                    687:
                    688: #if NBPFILTER > 0
                    689:        /*
                    690:         * If there's a BPF listener, bounce a copy of this frame
                    691:         * to him.
                    692:         */
                    693:        if (ifp->if_bpf)
                    694:                bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
                    695: #endif
                    696:
                    697:        ifp->if_flags |= IFF_OACTIVE;
                    698:
                    699:        /*
                    700:         * Set a timeout in case the chip goes out to lunch.
                    701:         */
                    702:        ifp->if_timer = 5;
                    703: }
                    704:
                    705: void
                    706: upl_init(void *xsc)
                    707: {
                    708:        struct upl_softc        *sc = xsc;
                    709:        struct ifnet            *ifp = &sc->sc_if;
                    710:        int                     s;
                    711:
                    712:        if (sc->sc_dying)
                    713:                return;
                    714:
                    715:        DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
                    716:
                    717:        if (ifp->if_flags & IFF_RUNNING)
                    718:                return;
                    719:
                    720:        s = splnet();
                    721:
                    722:        /* Init TX ring. */
                    723:        if (upl_tx_list_init(sc) == ENOBUFS) {
                    724:                printf("%s: tx list init failed\n", sc->sc_dev.dv_xname);
                    725:                splx(s);
                    726:                return;
                    727:        }
                    728:
                    729:        /* Init RX ring. */
                    730:        if (upl_rx_list_init(sc) == ENOBUFS) {
                    731:                printf("%s: rx list init failed\n", sc->sc_dev.dv_xname);
                    732:                splx(s);
                    733:                return;
                    734:        }
                    735:
                    736:        if (sc->sc_ep[UPL_ENDPT_RX] == NULL) {
                    737:                if (upl_openpipes(sc)) {
                    738:                        splx(s);
                    739:                        return;
                    740:                }
                    741:        }
                    742:
                    743:        ifp->if_flags |= IFF_RUNNING;
                    744:        ifp->if_flags &= ~IFF_OACTIVE;
                    745:
                    746:        splx(s);
                    747: }
                    748:
                    749: int
                    750: upl_openpipes(struct upl_softc *sc)
                    751: {
                    752:        struct upl_chain        *c;
                    753:        usbd_status             err;
                    754:        int                     i;
                    755:
                    756:        /* Open RX and TX pipes. */
                    757:        err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_RX],
                    758:            USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_RX]);
                    759:        if (err) {
                    760:                printf("%s: open rx pipe failed: %s\n",
                    761:                    sc->sc_dev.dv_xname, usbd_errstr(err));
                    762:                return (EIO);
                    763:        }
                    764:        err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_TX],
                    765:            USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_TX]);
                    766:        if (err) {
                    767:                printf("%s: open tx pipe failed: %s\n",
                    768:                    sc->sc_dev.dv_xname, usbd_errstr(err));
                    769:                return (EIO);
                    770:        }
                    771:        err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UPL_ENDPT_INTR],
                    772:            USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_INTR], sc,
                    773:            &sc->sc_ibuf, UPL_INTR_PKTLEN, upl_intr,
                    774:            UPL_INTR_INTERVAL);
                    775:        if (err) {
                    776:                printf("%s: open intr pipe failed: %s\n",
                    777:                    sc->sc_dev.dv_xname, usbd_errstr(err));
                    778:                return (EIO);
                    779:        }
                    780:
                    781:
                    782: #if 1
                    783:        /* Start up the receive pipe. */
                    784:        for (i = 0; i < UPL_RX_LIST_CNT; i++) {
                    785:                c = &sc->sc_cdata.upl_rx_chain[i];
                    786:                usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX],
                    787:                    c, c->upl_buf, UPL_BUFSZ,
                    788:                    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
                    789:                    upl_rxeof);
                    790:                usbd_transfer(c->upl_xfer);
                    791:        }
                    792: #endif
                    793:
                    794:        return (0);
                    795: }
                    796:
                    797: void
                    798: upl_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
                    799: {
                    800:        struct upl_softc        *sc = priv;
                    801:        struct ifnet            *ifp = &sc->sc_if;
                    802:        uByte                   stat;
                    803:
                    804:        DPRINTFN(15,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
                    805:
                    806:        if (sc->sc_dying)
                    807:                return;
                    808:
                    809:        if (!(ifp->if_flags & IFF_RUNNING))
                    810:                return;
                    811:
                    812:        if (status != USBD_NORMAL_COMPLETION) {
                    813:                if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
                    814:                        return;
                    815:                }
                    816:                sc->sc_intr_errs++;
                    817:                if (usbd_ratecheck(&sc->sc_rx_notice)) {
                    818:                        printf("%s: %u usb errors on intr: %s\n",
                    819:                            sc->sc_dev.dv_xname, sc->sc_rx_errs,
                    820:                            usbd_errstr(status));
                    821:                        sc->sc_intr_errs = 0;
                    822:                }
                    823:                if (status == USBD_STALLED)
                    824:                        usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]);
                    825:                return;
                    826:        }
                    827:
                    828:        stat = sc->sc_ibuf;
                    829:
                    830:        if (stat == 0)
                    831:                return;
                    832:
                    833:        DPRINTFN(10,("%s: %s: stat=0x%02x\n", sc->sc_dev.dv_xname,
                    834:                     __func__, stat));
                    835:
                    836: }
                    837:
                    838: int
                    839: upl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
                    840: {
                    841:        struct upl_softc        *sc = ifp->if_softc;
                    842:        struct ifaddr           *ifa = (struct ifaddr *)data;
                    843:        struct ifreq            *ifr = (struct ifreq *)data;
                    844:        int                     s, error = 0;
                    845:
                    846:        if (sc->sc_dying)
                    847:                return (EIO);
                    848:
                    849:        DPRINTFN(5,("%s: %s: cmd=0x%08lx\n",
                    850:                    sc->sc_dev.dv_xname, __func__, command));
                    851:
                    852:        s = splnet();
                    853:
                    854:        switch(command) {
                    855:        case SIOCSIFADDR:
                    856:                ifp->if_flags |= IFF_UP;
                    857:                upl_init(sc);
                    858:
                    859:                switch (ifa->ifa_addr->sa_family) {
                    860: #ifdef INET
                    861:                case AF_INET:
                    862:                        break;
                    863: #endif /* INET */
                    864:                }
                    865:                break;
                    866:
                    867:        case SIOCSIFMTU:
                    868:                if (ifr->ifr_mtu > UPL_BUFSZ)
                    869:                        error = EINVAL;
                    870:                else
                    871:                        ifp->if_mtu = ifr->ifr_mtu;
                    872:                break;
                    873:
                    874:        case SIOCSIFFLAGS:
                    875:                if (ifp->if_flags & IFF_UP) {
                    876:                        if (!(ifp->if_flags & IFF_RUNNING))
                    877:                                upl_init(sc);
                    878:                } else {
                    879:                        if (ifp->if_flags & IFF_RUNNING)
                    880:                                upl_stop(sc);
                    881:                }
                    882:                error = 0;
                    883:                break;
                    884:        default:
                    885:                error = EINVAL;
                    886:                break;
                    887:        }
                    888:
                    889:        splx(s);
                    890:
                    891:        return (error);
                    892: }
                    893:
                    894: void
                    895: upl_watchdog(struct ifnet *ifp)
                    896: {
                    897:        struct upl_softc        *sc = ifp->if_softc;
                    898:
                    899:        DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
                    900:
                    901:        if (sc->sc_dying)
                    902:                return;
                    903:
                    904:        ifp->if_oerrors++;
                    905:        printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
                    906:
                    907:        upl_stop(sc);
                    908:        upl_init(sc);
                    909:
                    910:        if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
                    911:                upl_start(ifp);
                    912: }
                    913:
                    914: /*
                    915:  * Stop the adapter and free any mbufs allocated to the
                    916:  * RX and TX lists.
                    917:  */
                    918: void
                    919: upl_stop(struct upl_softc *sc)
                    920: {
                    921:        usbd_status             err;
                    922:        struct ifnet            *ifp;
                    923:        int                     i;
                    924:
                    925:        DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
                    926:
                    927:        ifp = &sc->sc_if;
                    928:        ifp->if_timer = 0;
                    929:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                    930:
                    931:        /* Stop transfers. */
                    932:        if (sc->sc_ep[UPL_ENDPT_RX] != NULL) {
                    933:                err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_RX]);
                    934:                if (err) {
                    935:                        printf("%s: abort rx pipe failed: %s\n",
                    936:                        sc->sc_dev.dv_xname, usbd_errstr(err));
                    937:                }
                    938:                err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_RX]);
                    939:                if (err) {
                    940:                        printf("%s: close rx pipe failed: %s\n",
                    941:                        sc->sc_dev.dv_xname, usbd_errstr(err));
                    942:                }
                    943:                sc->sc_ep[UPL_ENDPT_RX] = NULL;
                    944:        }
                    945:
                    946:        if (sc->sc_ep[UPL_ENDPT_TX] != NULL) {
                    947:                err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_TX]);
                    948:                if (err) {
                    949:                        printf("%s: abort tx pipe failed: %s\n",
                    950:                        sc->sc_dev.dv_xname, usbd_errstr(err));
                    951:                }
                    952:                err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_TX]);
                    953:                if (err) {
                    954:                        printf("%s: close tx pipe failed: %s\n",
                    955:                            sc->sc_dev.dv_xname, usbd_errstr(err));
                    956:                }
                    957:                sc->sc_ep[UPL_ENDPT_TX] = NULL;
                    958:        }
                    959:
                    960:        if (sc->sc_ep[UPL_ENDPT_INTR] != NULL) {
                    961:                err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
                    962:                if (err) {
                    963:                        printf("%s: abort intr pipe failed: %s\n",
                    964:                        sc->sc_dev.dv_xname, usbd_errstr(err));
                    965:                }
                    966:                err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
                    967:                if (err) {
                    968:                        printf("%s: close intr pipe failed: %s\n",
                    969:                            sc->sc_dev.dv_xname, usbd_errstr(err));
                    970:                }
                    971:                sc->sc_ep[UPL_ENDPT_INTR] = NULL;
                    972:        }
                    973:
                    974:        /* Free RX resources. */
                    975:        for (i = 0; i < UPL_RX_LIST_CNT; i++) {
                    976:                if (sc->sc_cdata.upl_rx_chain[i].upl_mbuf != NULL) {
                    977:                        m_freem(sc->sc_cdata.upl_rx_chain[i].upl_mbuf);
                    978:                        sc->sc_cdata.upl_rx_chain[i].upl_mbuf = NULL;
                    979:                }
                    980:                if (sc->sc_cdata.upl_rx_chain[i].upl_xfer != NULL) {
                    981:                        usbd_free_xfer(sc->sc_cdata.upl_rx_chain[i].upl_xfer);
                    982:                        sc->sc_cdata.upl_rx_chain[i].upl_xfer = NULL;
                    983:                }
                    984:        }
                    985:
                    986:        /* Free TX resources. */
                    987:        for (i = 0; i < UPL_TX_LIST_CNT; i++) {
                    988:                if (sc->sc_cdata.upl_tx_chain[i].upl_mbuf != NULL) {
                    989:                        m_freem(sc->sc_cdata.upl_tx_chain[i].upl_mbuf);
                    990:                        sc->sc_cdata.upl_tx_chain[i].upl_mbuf = NULL;
                    991:                }
                    992:                if (sc->sc_cdata.upl_tx_chain[i].upl_xfer != NULL) {
                    993:                        usbd_free_xfer(sc->sc_cdata.upl_tx_chain[i].upl_xfer);
                    994:                        sc->sc_cdata.upl_tx_chain[i].upl_xfer = NULL;
                    995:                }
                    996:        }
                    997: }
                    998:
                    999: int
                   1000: upl_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
                   1001:           struct rtentry *rt0)
                   1002: {
                   1003:        int s, len, error;
                   1004:
                   1005:        DPRINTFN(10,("%s: %s: enter\n",
                   1006:                     ((struct upl_softc *)ifp->if_softc)->sc_dev.dv_xname,
                   1007:                     __func__));
                   1008:
                   1009:        len = m->m_pkthdr.len;
                   1010:        s = splnet();
                   1011:        /*
                   1012:         * Queue message on interface, and start output if interface
                   1013:         * not yet active.
                   1014:         */
                   1015:        IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
                   1016:        if (error) {
                   1017:                /* mbuf is already freed */
                   1018:                splx(s);
                   1019:                return (error);
                   1020:        }
                   1021:        ifp->if_obytes += len;
                   1022:        if ((ifp->if_flags & IFF_OACTIVE) == 0)
                   1023:                (*ifp->if_start)(ifp);
                   1024:        splx(s);
                   1025:
                   1026:        return (0);
                   1027: }
                   1028:
                   1029: void
                   1030: upl_input(struct ifnet *ifp, struct mbuf *m)
                   1031: {
                   1032:        struct ifqueue *inq;
                   1033:        int s;
                   1034:
                   1035:        /* XXX Assume all traffic is IP */
                   1036:
                   1037:        schednetisr(NETISR_IP);
                   1038:        inq = &ipintrq;
                   1039:
                   1040:        s = splnet();
                   1041:        if (IF_QFULL(inq)) {
                   1042:                IF_DROP(inq);
                   1043:                splx(s);
                   1044: #if 0
                   1045:                if (sc->sc_flags & SC_DEBUG)
                   1046:                        printf("%s: input queue full\n", ifp->if_xname);
                   1047: #endif
                   1048:                ifp->if_iqdrops++;
                   1049:                return;
                   1050:        }
                   1051:        IF_ENQUEUE(inq, m);
                   1052:        splx(s);
                   1053:        ifp->if_ipackets++;
                   1054:        ifp->if_ibytes += m->m_len;
                   1055: }

CVSweb