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

Annotation of sys/dev/usb/if_cdcef.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_cdcef.c,v 1.17 2007/06/14 06:55:10 mbalmer Exp $   */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2007 Dale Rahn <drahn@openbsd.org>
        !             5:  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
        !             6:  *
        !             7:  * Permission to use, copy, modify, and distribute this software for any
        !             8:  * purpose with or without fee is hereby granted, provided that the above
        !             9:  * copyright notice and this permission notice appear in all copies.
        !            10:  *
        !            11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            18:  */
        !            19:
        !            20: /*
        !            21:  * USB Communication Device Class Ethernet Emulation Model function driver
        !            22:  * (counterpart of the host-side cdce(4) driver)
        !            23:  */
        !            24: #include <bpfilter.h>
        !            25:
        !            26:
        !            27: #include <sys/param.h>
        !            28: #include <sys/device.h>
        !            29: #include <sys/socket.h>
        !            30: #include <sys/systm.h>
        !            31: #include <sys/mbuf.h>
        !            32: #include <sys/timeout.h>
        !            33:
        !            34: #include <net/if.h>
        !            35:
        !            36: #include <dev/usb/usb.h>
        !            37: #include <dev/usb/usbdi.h>
        !            38: #include <dev/usb/usbf.h>
        !            39: #include <dev/usb/usbcdc.h>
        !            40:
        !            41: #if NBPFILTER > 0
        !            42: #include <net/bpf.h>
        !            43: #endif
        !            44:
        !            45: #include <netinet/in.h>
        !            46: #include <netinet/in_systm.h>
        !            47: #include <netinet/in_var.h>
        !            48: #include <netinet/ip.h>
        !            49: #include <netinet/if_ether.h>
        !            50:
        !            51:
        !            52: #define CDCEF_VENDOR_ID                0x0001
        !            53: #define CDCEF_PRODUCT_ID       0x0001
        !            54: #define CDCEF_DEVICE_CODE      0x0100
        !            55: #define CDCEF_VENDOR_STRING    "OpenBSD.org"
        !            56: #define CDCEF_PRODUCT_STRING   "CDC Ethernet Emulation"
        !            57: #define CDCEF_SERIAL_STRING    "1.00"
        !            58:
        !            59: #define CDCEF_BUFSZ            1600
        !            60:
        !            61:
        !            62: struct cdcef_softc {
        !            63:        struct usbf_function    sc_dev;
        !            64:        usbf_config_handle      sc_config;
        !            65:        usbf_interface_handle   sc_iface;
        !            66:        usbf_endpoint_handle    sc_ep_in;
        !            67:        usbf_endpoint_handle    sc_ep_out;
        !            68:        usbf_pipe_handle        sc_pipe_in;
        !            69:        usbf_pipe_handle        sc_pipe_out;
        !            70:        usbf_xfer_handle        sc_xfer_in;
        !            71:        usbf_xfer_handle        sc_xfer_out;
        !            72:        void                    *sc_buffer_in;
        !            73:        void                    *sc_buffer_out;
        !            74:
        !            75:        struct timeout          start_to;
        !            76:
        !            77:        struct mbuf             *sc_xmit_mbuf;
        !            78:
        !            79:        struct arpcom           sc_arpcom;
        !            80: #define GET_IFP(sc) (&(sc)->sc_arpcom.ac_if)
        !            81:
        !            82:        int                     sc_rxeof_errors;
        !            83:        int                     sc_unit;
        !            84:        int                     sc_attached;
        !            85:        int                     sc_listening;
        !            86: };
        !            87:
        !            88: int            cdcef_match(struct device *, void *, void *);
        !            89: void           cdcef_attach(struct device *, struct device *, void *);
        !            90:
        !            91: usbf_status    cdcef_do_request(usbf_function_handle,
        !            92:                                 usb_device_request_t *, void **);
        !            93:
        !            94: void           cdcef_start(struct ifnet *);
        !            95:
        !            96: void           cdcef_txeof(usbf_xfer_handle, usbf_private_handle,
        !            97:                            usbf_status);
        !            98: void           cdcef_rxeof(usbf_xfer_handle, usbf_private_handle,
        !            99:                            usbf_status);
        !           100: int            cdcef_ioctl(struct ifnet *ifp, u_long command, caddr_t data);
        !           101: void           cdcef_watchdog(struct ifnet *ifp);
        !           102: void           cdcef_init(struct cdcef_softc *);
        !           103: void           cdcef_stop(struct cdcef_softc *);
        !           104: int            cdcef_encap(struct cdcef_softc *sc, struct mbuf *m, int idx);
        !           105: struct mbuf *  cdcef_newbuf(void);
        !           106: void           cdcef_start_timeout (void *);
        !           107:
        !           108: struct cfattach cdcef_ca = {
        !           109:        sizeof(struct cdcef_softc), cdcef_match, cdcef_attach
        !           110: };
        !           111:
        !           112: struct cfdriver cdcef_cd = {
        !           113:        NULL, "cdcef", DV_DULL
        !           114: };
        !           115:
        !           116: struct usbf_function_methods cdcef_methods = {
        !           117:        NULL,                   /* set_config */
        !           118:        cdcef_do_request
        !           119: };
        !           120:
        !           121: #ifndef CDCEF_DEBUG
        !           122: #define DPRINTF(x)     do {} while (0)
        !           123: #else
        !           124: #define DPRINTF(x)     printf x
        !           125: #endif
        !           126:
        !           127: #define DEVNAME(sc)    ((sc)->sc_dev.bdev.dv_xname)
        !           128:
        !           129: /*
        !           130:  * USB function match/attach/detach
        !           131:  */
        !           132:
        !           133: int
        !           134: cdcef_match(struct device *parent, void *match, void *aux)
        !           135: {
        !           136:        return UMATCH_GENERIC;
        !           137: }
        !           138:
        !           139: void
        !           140: cdcef_attach(struct device *parent, struct device *self, void *aux)
        !           141: {
        !           142:        struct cdcef_softc *sc = (struct cdcef_softc *)self;
        !           143:        struct usbf_attach_arg *uaa = aux;
        !           144:        usbf_device_handle dev = uaa->device;
        !           145:        char *devinfop;
        !           146:        struct ifnet *ifp;
        !           147:        usbf_status err;
        !           148:        usb_cdc_union_descriptor_t udesc;
        !           149:        int s;
        !           150:        u_int16_t macaddr_hi;
        !           151:
        !           152:
        !           153:        /* Set the device identification according to the function. */
        !           154:        usbf_devinfo_setup(dev, UDCLASS_IN_INTERFACE, 0, 0, CDCEF_VENDOR_ID,
        !           155:            CDCEF_PRODUCT_ID, CDCEF_DEVICE_CODE, CDCEF_VENDOR_STRING,
        !           156:            CDCEF_PRODUCT_STRING, CDCEF_SERIAL_STRING);
        !           157:
        !           158:        devinfop = usbf_devinfo_alloc(dev);
        !           159:        printf(": %s\n", devinfop);
        !           160:        usbf_devinfo_free(devinfop);
        !           161:
        !           162:        /* Fill in the fields needed by the parent device. */
        !           163:        sc->sc_dev.methods = &cdcef_methods;
        !           164:
        !           165:        /* timeout to start delayed tranfers */
        !           166:        timeout_set(&sc->start_to, cdcef_start_timeout, sc);
        !           167:
        !           168:        /*
        !           169:         * Build descriptors according to the device class specification.
        !           170:         */
        !           171:        err = usbf_add_config(dev, &sc->sc_config);
        !           172:        if (err) {
        !           173:                printf("%s: usbf_add_config failed\n", DEVNAME(sc));
        !           174:                return;
        !           175:        }
        !           176:        err = usbf_add_interface(sc->sc_config, UICLASS_CDC,
        !           177:            UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, NULL,
        !           178:            &sc->sc_iface);
        !           179:        if (err) {
        !           180:                printf("%s: usbf_add_interface failed\n", DEVNAME(sc));
        !           181:                return;
        !           182:        }
        !           183:        /* XXX don't use hard-coded values 128 and 16. */
        !           184:        err = usbf_add_endpoint(sc->sc_iface, UE_DIR_IN | 2, UE_BULK,
        !           185:            64, 16, &sc->sc_ep_in) ||
        !           186:            usbf_add_endpoint(sc->sc_iface, UE_DIR_OUT | 1, UE_BULK,
        !           187:            64, 16, &sc->sc_ep_out);
        !           188:        if (err) {
        !           189:                printf("%s: usbf_add_endpoint failed\n", DEVNAME(sc));
        !           190:                return;
        !           191:        }
        !           192:
        !           193:        /* Append a CDC union descriptor. */
        !           194:        bzero(&udesc, sizeof udesc);
        !           195:        udesc.bLength = sizeof udesc;
        !           196:        udesc.bDescriptorType = UDESC_CS_INTERFACE;
        !           197:        udesc.bDescriptorSubtype = UDESCSUB_CDC_UNION;
        !           198:        udesc.bSlaveInterface[0] = usbf_interface_number(sc->sc_iface);
        !           199:        err = usbf_add_config_desc(sc->sc_config,
        !           200:            (usb_descriptor_t *)&udesc, NULL);
        !           201:        if (err) {
        !           202:                printf("%s: usbf_add_config_desc failed\n", DEVNAME(sc));
        !           203:                return;
        !           204:        }
        !           205:
        !           206:        /*
        !           207:         * Close the configuration and build permanent descriptors.
        !           208:         */
        !           209:        err = usbf_end_config(sc->sc_config);
        !           210:        if (err) {
        !           211:                printf("%s: usbf_end_config failed\n", DEVNAME(sc));
        !           212:                return;
        !           213:        }
        !           214:
        !           215:        /* Preallocate xfers and data buffers. */
        !           216:        sc->sc_xfer_in = usbf_alloc_xfer(dev);
        !           217:        sc->sc_xfer_out = usbf_alloc_xfer(dev);
        !           218:        sc->sc_buffer_in = usbf_alloc_buffer(sc->sc_xfer_in,
        !           219:            CDCEF_BUFSZ);
        !           220:        sc->sc_buffer_out = usbf_alloc_buffer(sc->sc_xfer_out,
        !           221:            CDCEF_BUFSZ);
        !           222:        if (sc->sc_buffer_in == NULL || sc->sc_buffer_out == NULL) {
        !           223:                printf("%s: usbf_alloc_buffer failed\n", DEVNAME(sc));
        !           224:                return;
        !           225:        }
        !           226:
        !           227:        /* Open the bulk pipes. */
        !           228:        err = usbf_open_pipe(sc->sc_iface,
        !           229:            usbf_endpoint_address(sc->sc_ep_out), &sc->sc_pipe_out) ||
        !           230:            usbf_open_pipe(sc->sc_iface,
        !           231:            usbf_endpoint_address(sc->sc_ep_in), &sc->sc_pipe_in);
        !           232:        if (err) {
        !           233:                printf("%s: usbf_open_pipe failed\n", DEVNAME(sc));
        !           234:                return;
        !           235:        }
        !           236:
        !           237:        /* Get ready to receive packets. */
        !           238:        usbf_setup_xfer(sc->sc_xfer_out, sc->sc_pipe_out, sc,
        !           239:            sc->sc_buffer_out, CDCEF_BUFSZ, USBD_SHORT_XFER_OK, 0, cdcef_rxeof);
        !           240:        err = usbf_transfer(sc->sc_xfer_out);
        !           241:        if (err && err != USBF_IN_PROGRESS) {
        !           242:                printf("%s: usbf_transfer failed\n", DEVNAME(sc));
        !           243:                return;
        !           244:        }
        !           245:
        !           246:        s = splnet();
        !           247:
        !           248:        macaddr_hi = htons(0x2acb);
        !           249:        bcopy(&macaddr_hi, &sc->sc_arpcom.ac_enaddr[0], sizeof(u_int16_t));
        !           250:        bcopy(&ticks, &sc->sc_arpcom.ac_enaddr[2], sizeof(u_int32_t));
        !           251:        sc->sc_arpcom.ac_enaddr[5] = (u_int8_t)(sc->sc_unit);
        !           252:
        !           253:        printf("%s: address %s\n", DEVNAME(sc),
        !           254:            ether_sprintf(sc->sc_arpcom.ac_enaddr));
        !           255:
        !           256:        ifp = GET_IFP(sc);
        !           257:        ifp->if_softc = sc;
        !           258:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !           259:        ifp->if_ioctl = cdcef_ioctl;
        !           260:        ifp->if_start = cdcef_start;
        !           261:        ifp->if_watchdog = cdcef_watchdog;
        !           262:        strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
        !           263:
        !           264:        IFQ_SET_READY(&ifp->if_snd);
        !           265:
        !           266:        if_attach(ifp);
        !           267:        ether_ifattach(ifp);
        !           268:
        !           269:        sc->sc_attached = 1;
        !           270:        splx(s);
        !           271: }
        !           272:
        !           273: usbf_status
        !           274: cdcef_do_request(usbf_function_handle fun, usb_device_request_t *req,
        !           275:     void **data)
        !           276: {
        !           277:        printf("cdcef_do_request\n");
        !           278:        return USBF_STALLED;
        !           279: }
        !           280:
        !           281: void
        !           282: cdcef_start(struct ifnet *ifp)
        !           283: {
        !           284:        struct cdcef_softc      *sc = ifp->if_softc;
        !           285:        struct mbuf             *m_head = NULL;
        !           286:
        !           287:        if(ifp->if_flags & IFF_OACTIVE)
        !           288:                return;
        !           289:
        !           290:        IFQ_POLL(&ifp->if_snd, m_head);
        !           291:        if (m_head == NULL) {
        !           292:                return;
        !           293:        }
        !           294:
        !           295:        if (sc->sc_listening == 0 || m_head->m_pkthdr.len > CDCEF_BUFSZ) {
        !           296:                /*
        !           297:                 * drop packet because reciever is not listening,
        !           298:                 * or if packet is larger than xmit buffer
        !           299:                 */
        !           300:                IFQ_DEQUEUE(&ifp->if_snd, m_head);
        !           301:                m_freem(m_head);
        !           302:                return;
        !           303:        }
        !           304:
        !           305:        if (cdcef_encap(sc, m_head, 0)) {
        !           306:                ifp->if_flags |= IFF_OACTIVE;
        !           307:                return;
        !           308:        }
        !           309:
        !           310:        IFQ_DEQUEUE(&ifp->if_snd, m_head);
        !           311:
        !           312: #if NBPFILTER > 0
        !           313:        if (ifp->if_bpf)
        !           314:                bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
        !           315: #endif
        !           316:
        !           317:        ifp->if_flags |= IFF_OACTIVE;
        !           318:
        !           319:        ifp->if_timer = 6;
        !           320: }
        !           321:
        !           322: void
        !           323: cdcef_txeof(usbf_xfer_handle xfer, usbf_private_handle priv,
        !           324:     usbf_status err)
        !           325: {
        !           326:        struct cdcef_softc *sc = priv;
        !           327:        struct ifnet *ifp = GET_IFP(sc);
        !           328:        int s;
        !           329:
        !           330:        s = splnet();
        !           331: #if 0
        !           332:        printf("cdcef_txeof: xfer=%p, priv=%p, %s\n", xfer, priv,
        !           333:            usbf_errstr(err));
        !           334: #endif
        !           335:
        !           336:        ifp->if_timer = 0;
        !           337:        ifp->if_flags &= ~IFF_OACTIVE;
        !           338:
        !           339:        if (sc->sc_xmit_mbuf != NULL) {
        !           340:                m_freem(sc->sc_xmit_mbuf);
        !           341:                sc->sc_xmit_mbuf = NULL;
        !           342:        }
        !           343:
        !           344:        if (err)
        !           345:                ifp->if_oerrors++;
        !           346:        else
        !           347:                ifp->if_opackets++;
        !           348:
        !           349:        if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
        !           350:                timeout_add(&sc->start_to, 1); /* XXX  */
        !           351:
        !           352:        splx(s);
        !           353: }
        !           354: void
        !           355: cdcef_start_timeout (void *v)
        !           356: {
        !           357:        struct cdcef_softc *sc = v;
        !           358:        struct ifnet *ifp = GET_IFP(sc);
        !           359:        int s;
        !           360:
        !           361:        s = splnet();
        !           362:        cdcef_start(ifp);
        !           363:        splx(s);
        !           364: }
        !           365:
        !           366:
        !           367: void
        !           368: cdcef_rxeof(usbf_xfer_handle xfer, usbf_private_handle priv,
        !           369:     usbf_status status)
        !           370: {
        !           371:        struct cdcef_softc      *sc = priv;
        !           372:        int total_len = 0;
        !           373:        struct ifnet            *ifp = GET_IFP(sc);
        !           374:        struct mbuf             *m = NULL;
        !           375:
        !           376:
        !           377:        int s;
        !           378:
        !           379: #if 0
        !           380:        printf("cdcef_rxeof: xfer=%p, priv=%p, %s\n", xfer, priv,
        !           381:            usbf_errstr(status));
        !           382: #endif
        !           383:
        !           384:        if (status != USBF_NORMAL_COMPLETION) {
        !           385:                if (status == USBF_NOT_STARTED || status == USBF_CANCELLED)
        !           386:                        return;
        !           387:                if (sc->sc_rxeof_errors == 0)
        !           388:                        printf("%s: usb error on rx: %s\n",
        !           389:                            DEVNAME(sc), usbf_errstr(status));
        !           390:                /* XXX - no stalls on client */
        !           391:                if (sc->sc_rxeof_errors++ > 10) {
        !           392:                        printf("%s: too many errors, disabling\n",
        !           393:                            DEVNAME(sc));
        !           394:                        /* sc->sc_dying = 1; */
        !           395:                        // return;
        !           396:                }
        !           397:                goto done;
        !           398:        }
        !           399:        sc->sc_rxeof_errors = 0;
        !           400:
        !           401:        /* upon first incoming packet we know the host is listening */
        !           402:        if (sc->sc_listening == 0) {
        !           403:                sc->sc_listening = 1;
        !           404:        }
        !           405:
        !           406:
        !           407:        usbf_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
        !           408:
        !           409:        /* total_len -= 4; Strip off CRC added for Zaurus - XXX*/
        !           410:        if (total_len <= 1)
        !           411:                goto done;
        !           412:
        !           413:        if (total_len < sizeof(struct ether_header)) {
        !           414:                ifp->if_ierrors++;
        !           415:                goto done;
        !           416:        }
        !           417:
        !           418:        s = splnet();
        !           419:        if (ifp->if_flags & IFF_RUNNING) {
        !           420:                m = cdcef_newbuf();
        !           421:                if (m == NULL) {
        !           422:                        /* message? */
        !           423:                        ifp->if_ierrors++;
        !           424:                        goto done1;
        !           425:                }
        !           426:
        !           427:                m->m_pkthdr.len = m->m_len = total_len;
        !           428:                bcopy(sc->sc_buffer_out, mtod(m, char *), total_len);
        !           429:                m->m_pkthdr.rcvif = ifp;
        !           430:
        !           431:                ifp->if_ipackets++;
        !           432:
        !           433: #if NBPFILTER > 0
        !           434:                if (ifp->if_bpf)
        !           435:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !           436: #endif
        !           437:
        !           438:                ether_input_mbuf(ifp, m);
        !           439:        }
        !           440:
        !           441: done1:
        !           442:        splx(s);
        !           443:
        !           444: done:
        !           445:        /* Setup another xfer. */
        !           446:        usbf_setup_xfer(xfer, sc->sc_pipe_out, sc, sc->sc_buffer_out,
        !           447:            CDCEF_BUFSZ, USBD_SHORT_XFER_OK, 0, cdcef_rxeof);
        !           448:
        !           449:        status = usbf_transfer(xfer);
        !           450:        if (status && status != USBF_IN_PROGRESS) {
        !           451:                printf("%s: usbf_transfer failed\n", DEVNAME(sc));
        !           452:                return;
        !           453:        }
        !           454: }
        !           455:
        !           456: struct mbuf *
        !           457: cdcef_newbuf(void)
        !           458: {
        !           459:        struct mbuf             *m;
        !           460:
        !           461:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           462:        if (m == NULL)
        !           463:                return (NULL);
        !           464:
        !           465:        MCLGET(m, M_DONTWAIT);
        !           466:        if (!(m->m_flags & M_EXT)) {
        !           467:                m_freem(m);
        !           468:                return (NULL);
        !           469:        }
        !           470:
        !           471:        m->m_len = m->m_pkthdr.len = MCLBYTES;
        !           472:        m_adj(m, ETHER_ALIGN);
        !           473:
        !           474:        return (m);
        !           475: }
        !           476:
        !           477: int
        !           478: cdcef_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
        !           479: {
        !           480:        struct cdcef_softc      *sc = ifp->if_softc;
        !           481:        struct ifaddr           *ifa = (struct ifaddr *)data;
        !           482:        struct ifreq            *ifr = (struct ifreq *)data;
        !           483:        int                      s, error = 0;
        !           484:
        !           485:        s = splnet();
        !           486:
        !           487:        switch (command) {
        !           488:        case SIOCSIFADDR:
        !           489:                ifp->if_flags |= IFF_UP;
        !           490:                cdcef_init(sc);
        !           491:                switch (ifa->ifa_addr->sa_family) {
        !           492:                case AF_INET:
        !           493:                        arp_ifinit(&sc->sc_arpcom, ifa);
        !           494:                        break;
        !           495:                }
        !           496:                break;
        !           497:
        !           498:        case SIOCSIFMTU:
        !           499:                if (ifr->ifr_mtu > ETHERMTU)
        !           500:                        error = EINVAL;
        !           501:                else
        !           502:                        ifp->if_mtu = ifr->ifr_mtu;
        !           503:                break;
        !           504:
        !           505:        case SIOCSIFFLAGS:
        !           506:                if (ifp->if_flags & IFF_UP) {
        !           507:                        if (!(ifp->if_flags & IFF_RUNNING))
        !           508:                                cdcef_init(sc);
        !           509:                } else {
        !           510:                        if (ifp->if_flags & IFF_RUNNING)
        !           511:                                cdcef_stop(sc);
        !           512:                }
        !           513:                error = 0;
        !           514:                break;
        !           515:
        !           516:        case SIOCADDMULTI:
        !           517:        case SIOCDELMULTI:
        !           518:                error = (command == SIOCADDMULTI) ?
        !           519:                    ether_addmulti(ifr, &sc->sc_arpcom) :
        !           520:                    ether_delmulti(ifr, &sc->sc_arpcom);
        !           521:
        !           522:                if (error == ENETRESET)
        !           523:                        error = 0;
        !           524:                break;
        !           525:
        !           526:        default:
        !           527:                error = EINVAL;
        !           528:                break;
        !           529:        }
        !           530:
        !           531:        splx(s);
        !           532:
        !           533:        return (error);
        !           534: }
        !           535:
        !           536: void
        !           537: cdcef_watchdog(struct ifnet *ifp)
        !           538: {
        !           539:        struct cdcef_softc      *sc = ifp->if_softc;
        !           540:        int s;
        !           541:
        !           542: #if 0
        !           543:        if (sc->sc_dying)
        !           544:                return;
        !           545: #endif
        !           546:
        !           547:        ifp->if_oerrors++;
        !           548:        printf("%s: watchdog timeout\n", DEVNAME(sc));
        !           549:
        !           550:        s = splusb();
        !           551:        ifp->if_timer = 0;
        !           552:        ifp->if_flags &= ~IFF_OACTIVE;
        !           553:
        !           554:        /* cancel recieve pipe? */
        !           555:        usbf_abort_pipe(sc->sc_pipe_in); /* in is tx pipe */
        !           556:        splx(s);
        !           557: }
        !           558:
        !           559: void
        !           560: cdcef_init(struct cdcef_softc *sc)
        !           561: {
        !           562:        int s;
        !           563:        struct ifnet    *ifp = GET_IFP(sc);
        !           564:        if (ifp->if_flags & IFF_RUNNING)
        !           565:                return;
        !           566:        s = splnet();
        !           567:
        !           568:        ifp->if_flags |= IFF_RUNNING;
        !           569:        ifp->if_flags &= ~IFF_OACTIVE;
        !           570:
        !           571:        splx(s);
        !           572: }
        !           573:
        !           574: int
        !           575: cdcef_encap(struct cdcef_softc *sc, struct mbuf *m, int idx)
        !           576: {
        !           577:        usbf_status err;
        !           578:
        !           579:        m_copydata(m, 0, m->m_pkthdr.len, sc->sc_buffer_in);
        !           580:        /* NO CRC */
        !           581:
        !           582:        usbf_setup_xfer(sc->sc_xfer_in, sc->sc_pipe_in, sc, sc->sc_buffer_in,
        !           583:            m->m_pkthdr.len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
        !           584:            10000, cdcef_txeof);
        !           585:
        !           586:        err = usbf_transfer(sc->sc_xfer_in);
        !           587:        if (err && err != USBD_IN_PROGRESS) {
        !           588:                printf("encap error\n");
        !           589:                cdcef_stop(sc);
        !           590:                return (EIO);
        !           591:        }
        !           592:        sc->sc_xmit_mbuf = m;
        !           593:
        !           594:        return (0);
        !           595: }
        !           596:
        !           597:
        !           598: void
        !           599: cdcef_stop(struct cdcef_softc *sc)
        !           600: {
        !           601:        struct ifnet    *ifp = GET_IFP(sc);
        !           602:
        !           603:        ifp->if_timer = 0;
        !           604:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !           605:
        !           606:        /* cancel recieve pipe? */
        !           607:
        !           608:        if (sc->sc_xmit_mbuf != NULL) {
        !           609:                m_freem(sc->sc_xmit_mbuf);
        !           610:                sc->sc_xmit_mbuf = NULL;
        !           611:        }
        !           612: }

CVSweb