[BACK]Return to ucom.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Annotation of src/sys/dev/usb/ucom.c, Revision 1.118.8.1

1.118.8.1! snj         1: /*     $NetBSD: ucom.c,v 1.118 2016/12/14 15:11:29 skrll Exp $ */
1.1       augustss    2:
                      3: /*
1.22      augustss    4:  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
1.1       augustss    5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
1.23      augustss    8:  * by Lennart Augustsson (lennart@augustsson.net) at
1.1       augustss    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:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     21:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     23:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     30:  * POSSIBILITY OF SUCH DAMAGE.
                     31:  */
1.22      augustss   32: /*
                     33:  * This code is very heavily based on the 16550 driver, com.c.
                     34:  */
1.40      lukem      35:
                     36: #include <sys/cdefs.h>
1.118.8.1! snj        37: __KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.118 2016/12/14 15:11:29 skrll Exp $");
1.115     skrll      38:
                     39: #ifdef _KERNEL_OPT
                     40: #include "opt_usb.h"
                     41: #endif
1.1       augustss   42:
                     43: #include <sys/param.h>
                     44: #include <sys/systm.h>
                     45: #include <sys/kernel.h>
                     46: #include <sys/ioctl.h>
1.3       augustss   47: #include <sys/conf.h>
1.1       augustss   48: #include <sys/tty.h>
                     49: #include <sys/file.h>
                     50: #include <sys/select.h>
                     51: #include <sys/proc.h>
                     52: #include <sys/vnode.h>
1.12      augustss   53: #include <sys/device.h>
1.1       augustss   54: #include <sys/poll.h>
1.82      martin     55: #include <sys/queue.h>
1.63      elad       56: #include <sys/kauth.h>
1.111     skrll      57: #include <sys/sysctl.h>
1.106     gdt        58: #include <sys/timepps.h>
1.109     riastrad   59: #include <sys/rndsource.h>
1.1       augustss   60:
                     61: #include <dev/usb/usb.h>
                     62:
                     63: #include <dev/usb/usbdi.h>
                     64: #include <dev/usb/usbdi_util.h>
                     65: #include <dev/usb/usbdevs.h>
                     66: #include <dev/usb/usb_quirks.h>
1.111     skrll      67: #include <dev/usb/usbhist.h>
1.1       augustss   68:
1.12      augustss   69: #include <dev/usb/ucomvar.h>
                     70:
1.13      augustss   71: #include "ucom.h"
                     72:
1.53      drochner   73: #include "locators.h"
                     74:
1.13      augustss   75: #if NUCOM > 0
                     76:
1.111     skrll      77: #ifdef USB_DEBUG
                     78: #ifndef UCOM_DEBUG
                     79: #define ucomdebug 0
                     80: #else
1.12      augustss   81: int ucomdebug = 0;
1.111     skrll      82:
                     83: SYSCTL_SETUP(sysctl_hw_ucom_setup, "sysctl hw.ucom setup")
                     84: {
1.117     skrll      85:        int err;
                     86:        const struct sysctlnode *rnode;
                     87:        const struct sysctlnode *cnode;
                     88:
                     89:        err = sysctl_createv(clog, 0, NULL, &rnode,
                     90:            CTLFLAG_PERMANENT, CTLTYPE_NODE, "ucom",
                     91:            SYSCTL_DESCR("ucom global controls"),
                     92:            NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
                     93:
                     94:        if (err)
                     95:                goto fail;
                     96:
                     97:        /* control debugging printfs */
                     98:        err = sysctl_createv(clog, 0, &rnode, &cnode,
                     99:            CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
                    100:            "debug", SYSCTL_DESCR("Enable debugging output"),
                    101:            NULL, 0, &ucomdebug, sizeof(ucomdebug), CTL_CREATE, CTL_EOL);
                    102:        if (err)
                    103:                goto fail;
1.111     skrll     104:
1.117     skrll     105:        return;
1.111     skrll     106: fail:
1.117     skrll     107:        aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err);
1.111     skrll     108: }
                    109:
                    110: #endif /* UCOM_DEBUG */
                    111: #endif /* USB_DEBUG */
                    112:
                    113: #define DPRINTF(FMT,A,B,C,D)    USBHIST_LOGN(ucomdebug,1,FMT,A,B,C,D)
                    114: #define DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGN(ucomdebug,N,FMT,A,B,C,D)
                    115: #define UCOMHIST_FUNC()         USBHIST_FUNC()
                    116: #define UCOMHIST_CALLED(name)   USBHIST_CALLED(ucomdebug)
1.12      augustss  117:
1.108     christos  118: #define        UCOMCALLUNIT_MASK       TTCALLUNIT_MASK
                    119: #define        UCOMUNIT_MASK           TTUNIT_MASK
                    120: #define        UCOMDIALOUT_MASK        TTDIALOUT_MASK
                    121:
                    122: #define        UCOMCALLUNIT(x)         TTCALLUNIT(x)
                    123: #define        UCOMUNIT(x)             TTUNIT(x)
                    124: #define        UCOMDIALOUT(x)          TTDIALOUT(x)
1.12      augustss  125:
1.82      martin    126: /*
                    127:  * XXX: We can submit multiple input/output buffers to the usb stack
                    128:  * to improve throughput, but the usb stack is too lame to deal with this
                    129:  * in a number of places.
                    130:  */
                    131: #define        UCOM_IN_BUFFS   1
                    132: #define        UCOM_OUT_BUFFS  1
                    133:
                    134: struct ucom_buffer {
                    135:        SIMPLEQ_ENTRY(ucom_buffer) ub_link;
1.111     skrll     136:        struct usbd_xfer *ub_xfer;
1.82      martin    137:        u_char *ub_data;
                    138:        u_int ub_len;
                    139:        u_int ub_index;
                    140: };
                    141:
1.1       augustss  142: struct ucom_softc {
1.85      dyoung    143:        device_t                sc_dev;         /* base device */
1.12      augustss  144:
1.111     skrll     145:        struct usbd_device *    sc_udev;        /* USB device */
                    146:        struct usbd_interface * sc_iface;       /* data interface */
1.12      augustss  147:
                    148:        int                     sc_bulkin_no;   /* bulk in endpoint address */
1.115     skrll     149:        struct usbd_pipe *      sc_bulkin_pipe;/* bulk in pipe */
1.19      augustss  150:        u_int                   sc_ibufsize;    /* read buffer size */
1.22      augustss  151:        u_int                   sc_ibufsizepad; /* read buffer size padded */
1.82      martin    152:        struct ucom_buffer      sc_ibuff[UCOM_IN_BUFFS];
                    153:        SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_empty;
                    154:        SIMPLEQ_HEAD(, ucom_buffer) sc_ibuff_full;
1.12      augustss  155:
                    156:        int                     sc_bulkout_no;  /* bulk out endpoint address */
1.111     skrll     157:        struct usbd_pipe *      sc_bulkout_pipe;/* bulk out pipe */
1.19      augustss  158:        u_int                   sc_obufsize;    /* write buffer size */
1.82      martin    159:        u_int                   sc_opkthdrlen;  /* header length of */
                    160:        struct ucom_buffer      sc_obuff[UCOM_OUT_BUFFS];
                    161:        SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_free;
                    162:        SIMPLEQ_HEAD(, ucom_buffer) sc_obuff_full;
                    163:
                    164:        void                    *sc_si;
1.12      augustss  165:
1.90      jakllsch  166:        const struct ucom_methods *sc_methods;
1.12      augustss  167:        void                    *sc_parent;
                    168:        int                     sc_portno;
                    169:
                    170:        struct tty              *sc_tty;        /* our tty */
                    171:        u_char                  sc_lsr;
                    172:        u_char                  sc_msr;
                    173:        u_char                  sc_mcr;
1.82      martin    174:        volatile u_char         sc_rx_stopped;
                    175:        u_char                  sc_rx_unblock;
1.12      augustss  176:        u_char                  sc_tx_stopped;
                    177:        int                     sc_swflags;
                    178:
1.115     skrll     179:        enum ucom_state {
                    180:            UCOM_DEAD,
                    181:            UCOM_ATTACHED,
                    182:            UCOM_OPENING,
                    183:            UCOM_CLOSING,
                    184:            UCOM_OPEN
                    185:        }                       sc_state;
1.17      augustss  186:        int                     sc_refcnt;
1.115     skrll     187:        bool                    sc_dying;       /* disconnecting */
1.31      explorer  188:
1.106     gdt       189:        struct pps_state        sc_pps_state;   /* pps state */
                    190:
1.111     skrll     191:        krndsource_t            sc_rndsource;   /* random source */
                    192:
                    193:        kmutex_t                sc_lock;
1.115     skrll     194:        kcondvar_t              sc_statecv;
1.111     skrll     195:        kcondvar_t              sc_detachcv;
1.1       augustss  196: };
                    197:
1.44      gehenna   198: dev_type_open(ucomopen);
                    199: dev_type_close(ucomclose);
                    200: dev_type_read(ucomread);
                    201: dev_type_write(ucomwrite);
                    202: dev_type_ioctl(ucomioctl);
                    203: dev_type_stop(ucomstop);
                    204: dev_type_tty(ucomtty);
                    205: dev_type_poll(ucompoll);
                    206:
                    207: const struct cdevsw ucom_cdevsw = {
1.103     dholland  208:        .d_open = ucomopen,
                    209:        .d_close = ucomclose,
                    210:        .d_read = ucomread,
                    211:        .d_write = ucomwrite,
                    212:        .d_ioctl = ucomioctl,
                    213:        .d_stop = ucomstop,
                    214:        .d_tty = ucomtty,
                    215:        .d_poll = ucompoll,
                    216:        .d_mmap = nommap,
                    217:        .d_kqfilter = ttykqfilter,
1.105     dholland  218:        .d_discard = nodiscard,
1.111     skrll     219:        .d_flag = D_TTY | D_MPSAFE
1.44      gehenna   220: };
1.12      augustss  221:
1.82      martin    222: static void    ucom_cleanup(struct ucom_softc *);
                    223: static int     ucomparam(struct tty *, struct termios *);
                    224: static int     ucomhwiflow(struct tty *, int);
                    225: static void    ucomstart(struct tty *);
                    226: static void    ucom_shutdown(struct ucom_softc *);
                    227: static int     ucom_do_ioctl(struct ucom_softc *, u_long, void *,
1.60      christos  228:                              int, struct lwp *);
1.82      martin    229: static void    ucom_dtr(struct ucom_softc *, int);
                    230: static void    ucom_rts(struct ucom_softc *, int);
                    231: static void    ucom_break(struct ucom_softc *, int);
                    232: static void    tiocm_to_ucom(struct ucom_softc *, u_long, int);
                    233: static int     ucom_to_tiocm(struct ucom_softc *);
                    234:
1.111     skrll     235: static void    ucomreadcb(struct usbd_xfer *, void *, usbd_status);
1.82      martin    236: static void    ucom_submit_write(struct ucom_softc *, struct ucom_buffer *);
                    237: static void    ucom_write_status(struct ucom_softc *, struct ucom_buffer *,
1.115     skrll     238:                    usbd_status);
1.82      martin    239:
1.111     skrll     240: static void    ucomwritecb(struct usbd_xfer *, void *, usbd_status);
1.82      martin    241: static void    ucom_read_complete(struct ucom_softc *);
1.115     skrll     242: static int     ucomsubmitread(struct ucom_softc *, struct ucom_buffer *);
1.82      martin    243: static void    ucom_softintr(void *);
1.1       augustss  244:
1.85      dyoung    245: int ucom_match(device_t, cfdata_t, void *);
                    246: void ucom_attach(device_t, device_t, void *);
                    247: int ucom_detach(device_t, int);
                    248: int ucom_activate(device_t, enum devact);
                    249: extern struct cfdriver ucom_cd;
                    250: CFATTACH_DECL_NEW(ucom, sizeof(struct ucom_softc), ucom_match, ucom_attach,
                    251:     ucom_detach, ucom_activate);
1.1       augustss  252:
1.85      dyoung    253: int
                    254: ucom_match(device_t parent, cfdata_t match, void *aux)
1.1       augustss  255: {
1.111     skrll     256:        return 1;
1.1       augustss  257: }
                    258:
1.85      dyoung    259: void
                    260: ucom_attach(device_t parent, device_t self, void *aux)
1.1       augustss  261: {
1.77      cube      262:        struct ucom_softc *sc = device_private(self);
1.111     skrll     263:        struct ucom_attach_args *ucaa = aux;
1.12      augustss  264:
1.111     skrll     265:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                    266:
                    267:        if (ucaa->ucaa_info != NULL)
                    268:                aprint_normal(": %s", ucaa->ucaa_info);
1.83      pooka     269:        aprint_normal("\n");
1.12      augustss  270:
1.111     skrll     271:        prop_dictionary_set_int32(device_properties(self), "port",
                    272:            ucaa->ucaa_portno);
1.110     joerg     273:
1.77      cube      274:        sc->sc_dev = self;
1.111     skrll     275:        sc->sc_udev = ucaa->ucaa_device;
                    276:        sc->sc_iface = ucaa->ucaa_iface;
                    277:        sc->sc_bulkout_no = ucaa->ucaa_bulkout;
                    278:        sc->sc_bulkin_no = ucaa->ucaa_bulkin;
                    279:        sc->sc_ibufsize = ucaa->ucaa_ibufsize;
                    280:        sc->sc_ibufsizepad = ucaa->ucaa_ibufsizepad;
                    281:        sc->sc_obufsize = ucaa->ucaa_obufsize;
                    282:        sc->sc_opkthdrlen = ucaa->ucaa_opkthdrlen;
                    283:        sc->sc_methods = ucaa->ucaa_methods;
                    284:        sc->sc_parent = ucaa->ucaa_arg;
                    285:        sc->sc_portno = ucaa->ucaa_portno;
1.12      augustss  286:
1.82      martin    287:        sc->sc_lsr = 0;
                    288:        sc->sc_msr = 0;
                    289:        sc->sc_mcr = 0;
                    290:        sc->sc_tx_stopped = 0;
                    291:        sc->sc_swflags = 0;
                    292:        sc->sc_refcnt = 0;
1.115     skrll     293:        sc->sc_dying = false;
                    294:        sc->sc_state = UCOM_DEAD;
1.82      martin    295:
1.111     skrll     296:        sc->sc_si = softint_establish(SOFTINT_USB, ucom_softintr, sc);
                    297:        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB);
1.115     skrll     298:        cv_init(&sc->sc_statecv, "ucomstate");
1.111     skrll     299:        cv_init(&sc->sc_detachcv, "ucomdtch");
                    300:
                    301:        SIMPLEQ_INIT(&sc->sc_ibuff_empty);
                    302:        SIMPLEQ_INIT(&sc->sc_ibuff_full);
                    303:        SIMPLEQ_INIT(&sc->sc_obuff_free);
                    304:        SIMPLEQ_INIT(&sc->sc_obuff_full);
                    305:
                    306:        memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff));
                    307:        memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff));
                    308:
1.118.8.1! snj       309:        DPRINTF("open pipes in=%jd out=%jd",
        !           310:            sc->sc_bulkin_no, sc->sc_bulkout_no, 0, 0);
1.111     skrll     311:
                    312:        struct ucom_buffer *ub;
                    313:        usbd_status err;
                    314:        int error;
                    315:
                    316:        /* Open the bulk pipes */
                    317:        err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no,
                    318:            USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
                    319:        if (err) {
1.118.8.1! snj       320:                DPRINTF("open bulk in error (addr %jd), err=%jd",
1.111     skrll     321:                    sc->sc_bulkin_no, err, 0, 0);
                    322:                error = EIO;
                    323:                goto fail_0;
                    324:        }
1.115     skrll     325:        /* Allocate input buffers */
                    326:        for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
                    327:            ub++) {
                    328:                error = usbd_create_xfer(sc->sc_bulkin_pipe,
                    329:                    sc->sc_ibufsizepad, USBD_SHORT_XFER_OK, 0,
                    330:                    &ub->ub_xfer);
                    331:                if (error)
                    332:                        goto fail_1;
                    333:                ub->ub_data = usbd_get_buffer(ub->ub_xfer);
                    334:        }
                    335:
1.111     skrll     336:        err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
                    337:            USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
                    338:        if (err) {
1.118.8.1! snj       339:                DPRINTF("open bulk out error (addr %jd), err=%jd",
1.111     skrll     340:                    sc->sc_bulkout_no, err, 0, 0);
                    341:                error = EIO;
                    342:                goto fail_1;
                    343:        }
                    344:        for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
                    345:            ub++) {
1.115     skrll     346:                error = usbd_create_xfer(sc->sc_bulkout_pipe,
                    347:                    sc->sc_obufsize, 0, 0, &ub->ub_xfer);
1.111     skrll     348:                if (error)
                    349:                        goto fail_2;
                    350:                ub->ub_data = usbd_get_buffer(ub->ub_xfer);
                    351:                SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
                    352:        }
1.82      martin    353:
1.115     skrll     354:        struct tty *tp = tty_alloc();
1.12      augustss  355:        tp->t_oproc = ucomstart;
                    356:        tp->t_param = ucomparam;
1.82      martin    357:        tp->t_hwiflow = ucomhwiflow;
1.12      augustss  358:        sc->sc_tty = tp;
                    359:
1.118.8.1! snj       360:        DPRINTF("tty_attach %#jx", (uintptr_t)tp, 0, 0, 0);
1.12      augustss  361:        tty_attach(tp);
                    362:
1.85      dyoung    363:        rnd_attach_source(&sc->sc_rndsource, device_xname(sc->sc_dev),
1.107     tls       364:                          RND_TYPE_TTY, RND_FLAG_DEFAULT);
1.31      explorer  365:
1.74      smb       366:        if (!pmf_device_register(self, NULL, NULL))
                    367:                aprint_error_dev(self, "couldn't establish power handler\n");
1.115     skrll     368:
                    369:        sc->sc_state = UCOM_ATTACHED;
                    370:
1.85      dyoung    371:        return;
1.111     skrll     372:
                    373: fail_2:
1.115     skrll     374:        for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
1.111     skrll     375:            ub++) {
                    376:                if (ub->ub_xfer)
                    377:                        usbd_destroy_xfer(ub->ub_xfer);
                    378:        }
1.115     skrll     379:
                    380:        usbd_close_pipe(sc->sc_bulkout_pipe);
                    381:
                    382: fail_1:
                    383:        for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
1.111     skrll     384:            ub++) {
                    385:                if (ub->ub_xfer)
                    386:                        usbd_destroy_xfer(ub->ub_xfer);
                    387:        }
                    388:        usbd_close_pipe(sc->sc_bulkin_pipe);
                    389:
                    390: fail_0:
                    391:        aprint_error_dev(self, "attach failed, error=%d\n", error);
                    392:
                    393:        return;
1.12      augustss  394: }
                    395:
1.85      dyoung    396: int
                    397: ucom_detach(device_t self, int flags)
1.12      augustss  398: {
1.77      cube      399:        struct ucom_softc *sc = device_private(self);
1.36      augustss  400:        struct tty *tp = sc->sc_tty;
1.12      augustss  401:        int maj, mn;
1.111     skrll     402:        int i;
                    403:
                    404:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
1.12      augustss  405:
1.118.8.1! snj       406:        DPRINTF("sc=%#jx flags=%jd tp=%#jx", (uintptr_t)sc, flags,
        !           407:            (uintptr_t)tp, 0);
        !           408:        DPRINTF("... pipe=%jd,%jd", sc->sc_bulkin_no, sc->sc_bulkout_no, 0, 0);
1.12      augustss  409:
1.111     skrll     410:        mutex_enter(&sc->sc_lock);
1.115     skrll     411:        sc->sc_dying = true;
1.111     skrll     412:        mutex_exit(&sc->sc_lock);
                    413:
1.74      smb       414:        pmf_device_deregister(self);
1.12      augustss  415:
1.33      augustss  416:        if (sc->sc_bulkin_pipe != NULL)
                    417:                usbd_abort_pipe(sc->sc_bulkin_pipe);
                    418:        if (sc->sc_bulkout_pipe != NULL)
                    419:                usbd_abort_pipe(sc->sc_bulkout_pipe);
1.12      augustss  420:
1.111     skrll     421:        mutex_enter(&sc->sc_lock);
1.115     skrll     422:
                    423:        /* wait for open/close to finish */
                    424:        while (sc->sc_state == UCOM_OPENING || sc->sc_state == UCOM_CLOSING) {
                    425:                int error = cv_wait_sig(&sc->sc_statecv, &sc->sc_lock);
                    426:
                    427:                if (error) {
                    428:                        mutex_exit(&sc->sc_lock);
                    429:                        return error;
                    430:                }
                    431:        }
                    432:
                    433:        sc->sc_refcnt--;
1.111     skrll     434:        while (sc->sc_refcnt > 0) {
1.35      augustss  435:                /* Wake up anyone waiting */
1.36      augustss  436:                if (tp != NULL) {
1.71      ad        437:                        mutex_spin_enter(&tty_lock);
1.36      augustss  438:                        CLR(tp->t_state, TS_CARR_ON);
                    439:                        CLR(tp->t_cflag, CLOCAL | MDMBUF);
                    440:                        ttyflush(tp, FREAD|FWRITE);
1.71      ad        441:                        mutex_spin_exit(&tty_lock);
1.36      augustss  442:                }
1.17      augustss  443:                /* Wait for processes to go away. */
1.115     skrll     444:                if (cv_timedwait(&sc->sc_detachcv, &sc->sc_lock, hz * 60)) {
                    445:                        printf("%s: %s didn't detach\n", __func__,
                    446:                            device_xname(sc->sc_dev));
                    447:                }
1.17      augustss  448:        }
1.82      martin    449:
                    450:        softint_disestablish(sc->sc_si);
1.111     skrll     451:        mutex_exit(&sc->sc_lock);
1.12      augustss  452:
                    453:        /* locate the major number */
1.44      gehenna   454:        maj = cdevsw_lookup_major(&ucom_cdevsw);
1.12      augustss  455:
                    456:        /* Nuke the vnodes for any open instances. */
1.62      thorpej   457:        mn = device_unit(self);
1.118.8.1! snj       458:        DPRINTF("maj=%jd mn=%jd", maj, mn, 0, 0);
1.12      augustss  459:        vdevgone(maj, mn, mn, VCHR);
1.22      augustss  460:        vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR);
                    461:        vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR);
1.12      augustss  462:
                    463:        /* Detach and free the tty. */
1.36      augustss  464:        if (tp != NULL) {
                    465:                tty_detach(tp);
1.87      rmind     466:                tty_free(tp);
1.33      augustss  467:                sc->sc_tty = NULL;
                    468:        }
1.12      augustss  469:
1.82      martin    470:        for (i = 0; i < UCOM_IN_BUFFS; i++) {
                    471:                if (sc->sc_ibuff[i].ub_xfer != NULL)
1.111     skrll     472:                        usbd_destroy_xfer(sc->sc_ibuff[i].ub_xfer);
1.82      martin    473:        }
                    474:
                    475:        for (i = 0; i < UCOM_OUT_BUFFS; i++) {
                    476:                if (sc->sc_obuff[i].ub_xfer != NULL)
1.111     skrll     477:                        usbd_destroy_xfer(sc->sc_obuff[i].ub_xfer);
                    478:        }
                    479:
                    480:        if (sc->sc_bulkin_pipe != NULL) {
                    481:                usbd_close_pipe(sc->sc_bulkin_pipe);
                    482:                sc->sc_bulkin_pipe = NULL;
                    483:        }
                    484:
                    485:        if (sc->sc_bulkout_pipe != NULL) {
                    486:                usbd_close_pipe(sc->sc_bulkout_pipe);
                    487:                sc->sc_bulkout_pipe = NULL;
1.82      martin    488:        }
                    489:
1.31      explorer  490:        /* Detach the random source */
                    491:        rnd_detach_source(&sc->sc_rndsource);
                    492:
1.111     skrll     493:        mutex_destroy(&sc->sc_lock);
1.115     skrll     494:        cv_destroy(&sc->sc_statecv);
1.111     skrll     495:        cv_destroy(&sc->sc_detachcv);
                    496:
                    497:        return 0;
1.12      augustss  498: }
                    499:
                    500: int
1.85      dyoung    501: ucom_activate(device_t self, enum devact act)
1.12      augustss  502: {
1.77      cube      503:        struct ucom_softc *sc = device_private(self);
1.12      augustss  504:
1.111     skrll     505:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                    506:
1.118.8.1! snj       507:        DPRINTFN(5, "%jd", act, 0, 0, 0);
1.34      augustss  508:
1.12      augustss  509:        switch (act) {
                    510:        case DVACT_DEACTIVATE:
1.111     skrll     511:                mutex_enter(&sc->sc_lock);
1.115     skrll     512:                sc->sc_dying = true;
1.111     skrll     513:                mutex_exit(&sc->sc_lock);
1.81      dyoung    514:                return 0;
                    515:        default:
                    516:                return EOPNOTSUPP;
1.12      augustss  517:        }
                    518: }
                    519:
                    520: void
1.24      augustss  521: ucom_shutdown(struct ucom_softc *sc)
1.12      augustss  522: {
                    523:        struct tty *tp = sc->sc_tty;
                    524:
1.111     skrll     525:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                    526:
1.12      augustss  527:        /*
                    528:         * Hang up if necessary.  Wait a bit, so the other side has time to
                    529:         * notice even if we immediately open the port again.
                    530:         */
                    531:        if (ISSET(tp->t_cflag, HUPCL)) {
                    532:                ucom_dtr(sc, 0);
1.111     skrll     533:                /* XXX will only timeout */
1.116     skrll     534:                (void) kpause(ttclos, false, hz, NULL);
1.12      augustss  535:        }
                    536: }
                    537:
                    538: int
1.69      christos  539: ucomopen(dev_t dev, int flag, int mode, struct lwp *l)
1.12      augustss  540: {
1.115     skrll     541:        const int unit = UCOMUNIT(dev);
                    542:        struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
                    543:        int error = 0;
1.43      augustss  544:
1.111     skrll     545:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                    546:
1.12      augustss  547:        if (sc == NULL)
1.111     skrll     548:                return ENXIO;
1.12      augustss  549:
1.111     skrll     550:        mutex_enter(&sc->sc_lock);
                    551:        if (sc->sc_dying) {
1.115     skrll     552:                DPRINTF("... dying", 0, 0, 0, 0);
1.111     skrll     553:                mutex_exit(&sc->sc_lock);
                    554:                return EIO;
                    555:        }
1.12      augustss  556:
1.111     skrll     557:        if (!device_is_active(sc->sc_dev)) {
                    558:                mutex_exit(&sc->sc_lock);
                    559:                return ENXIO;
                    560:        }
1.12      augustss  561:
1.115     skrll     562:        struct tty *tp = sc->sc_tty;
1.12      augustss  563:
1.118.8.1! snj       564:        DPRINTF("unit=%jd, tp=%#jx", unit, (uintptr_t)tp, 0, 0);
1.12      augustss  565:
1.111     skrll     566:        if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) {
                    567:                mutex_exit(&sc->sc_lock);
                    568:                return EBUSY;
                    569:        }
1.12      augustss  570:
                    571:        /*
1.113     mlelstv   572:         * Wait while the device is initialized by the
                    573:         * first opener or cleaned up by the last closer.
1.12      augustss  574:         */
1.115     skrll     575:        while (sc->sc_state == UCOM_OPENING || sc->sc_state == UCOM_CLOSING) {
                    576:                error = cv_wait_sig(&sc->sc_statecv, &sc->sc_lock);
                    577:
                    578:                if (sc->sc_dying)
                    579:                        error = EIO;
1.17      augustss  580:
1.111     skrll     581:                if (error) {
                    582:                        mutex_exit(&sc->sc_lock);
                    583:                        return error;
                    584:                }
1.17      augustss  585:        }
1.115     skrll     586:        enum ucom_state state = sc->sc_state;
1.111     skrll     587:
1.115     skrll     588:        KASSERTMSG(state == UCOM_OPEN || state == UCOM_ATTACHED,
                    589:            "state is %d", state);
1.43      augustss  590:
1.115     skrll     591:        bool cleanup = false;
                    592:        /* If this is the first open then perform the initialisation */
1.12      augustss  593:        if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
1.115     skrll     594:                KASSERT(state == UCOM_ATTACHED);
1.12      augustss  595:                tp->t_dev = dev;
1.115     skrll     596:                cleanup = true;
                    597:                sc->sc_state = UCOM_OPENING;
1.12      augustss  598:
1.115     skrll     599:                mutex_exit(&sc->sc_lock);
1.22      augustss  600:                if (sc->sc_methods->ucom_open != NULL) {
                    601:                        error = sc->sc_methods->ucom_open(sc->sc_parent,
1.115     skrll     602:                            sc->sc_portno);
1.22      augustss  603:                        if (error) {
1.115     skrll     604:                                goto fail_2;
1.22      augustss  605:                        }
                    606:                }
                    607:
1.12      augustss  608:                ucom_status_change(sc);
                    609:
1.106     gdt       610:                /* Clear PPS capture state on first open. */
                    611:                mutex_spin_enter(&timecounter_lock);
                    612:                memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state));
                    613:                sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
                    614:                pps_init(&sc->sc_pps_state);
                    615:                mutex_spin_exit(&timecounter_lock);
                    616:
1.12      augustss  617:                /*
                    618:                 * Initialize the termios status to the defaults.  Add in the
                    619:                 * sticky bits from TIOCSFLAGS.
                    620:                 */
1.115     skrll     621:                struct termios t;
                    622:
1.12      augustss  623:                t.c_ispeed = 0;
                    624:                t.c_ospeed = TTYDEF_SPEED;
                    625:                t.c_cflag = TTYDEF_CFLAG;
                    626:                if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
                    627:                        SET(t.c_cflag, CLOCAL);
                    628:                if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
                    629:                        SET(t.c_cflag, CRTSCTS);
                    630:                if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
                    631:                        SET(t.c_cflag, MDMBUF);
                    632:                /* Make sure ucomparam() will do something. */
                    633:                tp->t_ospeed = 0;
                    634:                (void) ucomparam(tp, &t);
                    635:                tp->t_iflag = TTYDEF_IFLAG;
                    636:                tp->t_oflag = TTYDEF_OFLAG;
                    637:                tp->t_lflag = TTYDEF_LFLAG;
                    638:                ttychars(tp);
                    639:                ttsetwater(tp);
                    640:
                    641:                /*
                    642:                 * Turn on DTR.  We must always do this, even if carrier is not
                    643:                 * present, because otherwise we'd have to use TIOCSDTR
                    644:                 * immediately after setting CLOCAL, which applications do not
                    645:                 * expect.  We always assert DTR while the device is open
1.64      gson      646:                 * unless explicitly requested to deassert it.  Ditto RTS.
1.12      augustss  647:                 */
                    648:                ucom_dtr(sc, 1);
1.102     jakllsch  649:                ucom_rts(sc, 1);
1.12      augustss  650:
1.115     skrll     651:                mutex_enter(&sc->sc_lock);
                    652:                if (sc->sc_dying) {
                    653:                        DPRINTF("... dying", 0, 0, 0, 0);
                    654:                        error = EIO;
                    655:                        goto fail_1;
                    656:                }
                    657:
1.82      martin    658:                sc->sc_rx_unblock = 0;
                    659:                sc->sc_rx_stopped = 0;
                    660:                sc->sc_tx_stopped = 0;
                    661:
1.115     skrll     662:                for (size_t i = 0; i < UCOM_IN_BUFFS; i++) {
                    663:                        struct ucom_buffer *ub = &sc->sc_ibuff[i];
                    664:                        error = ucomsubmitread(sc, ub);
                    665:                        if (error) {
                    666:                                mutex_exit(&sc->sc_lock);
1.82      martin    667:                                goto fail_2;
                    668:                        }
1.28      toshii    669:                }
1.12      augustss  670:        }
1.115     skrll     671:        sc->sc_state = UCOM_OPEN;
                    672:        cv_signal(&sc->sc_statecv);
1.111     skrll     673:        mutex_exit(&sc->sc_lock);
1.12      augustss  674:
1.118.8.1! snj       675:        DPRINTF("unit=%jd, tp=%#jx dialout %jd nonblock %jd", unit,
        !           676:            (uintptr_t)tp, !!UCOMDIALOUT(dev), !!ISSET(flag, O_NONBLOCK));
1.12      augustss  677:        error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
                    678:        if (error)
                    679:                goto bad;
                    680:
1.32      eeh       681:        error = (*tp->t_linesw->l_open)(dev, tp);
1.12      augustss  682:        if (error)
                    683:                goto bad;
                    684:
1.111     skrll     685:        return 0;
1.26      toshii    686:
1.115     skrll     687: bad:
                    688:        cleanup = !ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0;
                    689:
1.26      toshii    690: fail_2:
1.115     skrll     691:        if (cleanup) {
1.12      augustss  692:                /*
1.115     skrll     693:                 * We failed to open the device, and nobody else had
                    694:                 * it opened.  Clean up the state as appropriate.
1.12      augustss  695:                 */
                    696:                ucom_cleanup(sc);
                    697:        }
1.115     skrll     698:
                    699:        mutex_enter(&sc->sc_lock);
                    700:
                    701: fail_1:
                    702:        sc->sc_state = state;
                    703:        cv_signal(&sc->sc_statecv);
                    704:        mutex_exit(&sc->sc_lock);
1.12      augustss  705:
1.111     skrll     706:        return error;
1.12      augustss  707: }
                    708:
                    709: int
1.69      christos  710: ucomclose(dev_t dev, int flag, int mode, struct lwp *l)
1.12      augustss  711: {
1.115     skrll     712:        const int unit = UCOMUNIT(dev);
                    713:        struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
                    714:        int error = 0;
1.12      augustss  715:
1.111     skrll     716:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                    717:
1.118.8.1! snj       718:        DPRINTF("unit=%jd", UCOMUNIT(dev), 0, 0, 0);
1.101     jakllsch  719:
                    720:        if (sc == NULL)
                    721:                return 0;
                    722:
1.111     skrll     723:        mutex_enter(&sc->sc_lock);
1.115     skrll     724:        if (sc->sc_dying) {
                    725:                DPRINTF("... dying", 0, 0, 0, 0);
                    726:                mutex_exit(&sc->sc_lock);
                    727:                return ENXIO;
                    728:        }
                    729:
                    730:        /*
                    731:         * Wait until any opens/closes have finished
                    732:         */
                    733:        while (sc->sc_state == UCOM_OPENING || sc->sc_state == UCOM_CLOSING) {
                    734:                error = cv_wait_sig(&sc->sc_statecv, &sc->sc_lock);
                    735:
                    736:                if (sc->sc_dying)
                    737:                        error = EIO;
                    738:
                    739:                if (error) {
                    740:                        mutex_exit(&sc->sc_lock);
                    741:                        return error;
                    742:                }
                    743:        }
1.101     jakllsch  744:
1.115     skrll     745:        struct tty *tp = sc->sc_tty;
1.113     mlelstv   746:
1.111     skrll     747:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
1.115     skrll     748:                KASSERT(sc->sc_state == UCOM_ATTACHED);
                    749:                mutex_exit(&sc->sc_lock);
                    750:                return 0;
1.111     skrll     751:        }
1.12      augustss  752:
1.115     skrll     753:        KASSERT(sc->sc_state == UCOM_OPEN);
                    754:        sc->sc_state = UCOM_CLOSING;
                    755:        mutex_exit(&sc->sc_lock);
1.17      augustss  756:
1.32      eeh       757:        (*tp->t_linesw->l_close)(tp, flag);
1.12      augustss  758:        ttyclose(tp);
                    759:
1.115     skrll     760:        /* state when we're done - default to open */
                    761:        enum ucom_state state = UCOM_OPEN;
1.12      augustss  762:        if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
                    763:                /*
                    764:                 * Although we got a last close, the device may still be in
                    765:                 * use; e.g. if this was the dialout node, and there are still
                    766:                 * processes waiting for carrier on the non-dialout node.
                    767:                 */
                    768:                ucom_cleanup(sc);
1.115     skrll     769:                if (sc->sc_methods->ucom_close != NULL)
                    770:                        sc->sc_methods->ucom_close(sc->sc_parent,
                    771:                            sc->sc_portno);
                    772:                state = UCOM_ATTACHED;
1.12      augustss  773:        }
                    774:
1.115     skrll     775:        mutex_enter(&sc->sc_lock);
                    776:        sc->sc_state = state;
                    777:        cv_signal(&sc->sc_statecv);
1.111     skrll     778:        mutex_exit(&sc->sc_lock);
                    779:
1.115     skrll     780:        return error;
1.12      augustss  781: }
1.43      augustss  782:
1.12      augustss  783: int
1.24      augustss  784: ucomread(dev_t dev, struct uio *uio, int flag)
1.12      augustss  785: {
1.115     skrll     786:        const int unit = UCOMUNIT(dev);
                    787:        struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.17      augustss  788:        int error;
1.12      augustss  789:
1.111     skrll     790:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                    791:
                    792:        if (sc == NULL)
                    793:                return EIO;
                    794:
                    795:        mutex_enter(&sc->sc_lock);
                    796:        if (sc->sc_dying) {
1.115     skrll     797:                DPRINTF("... dying", 0, 0, 0, 0);
1.111     skrll     798:                mutex_exit(&sc->sc_lock);
                    799:                return EIO;
                    800:        }
1.43      augustss  801:
1.115     skrll     802:        struct tty *tp = sc->sc_tty;
1.101     jakllsch  803:
1.17      augustss  804:        sc->sc_refcnt++;
1.111     skrll     805:        mutex_exit(&sc->sc_lock);
1.115     skrll     806:
1.32      eeh       807:        error = ((*tp->t_linesw->l_read)(tp, uio, flag));
1.115     skrll     808:
1.111     skrll     809:        mutex_enter(&sc->sc_lock);
1.17      augustss  810:        if (--sc->sc_refcnt < 0)
1.115     skrll     811:                cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj       812:        DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0);
1.111     skrll     813:        mutex_exit(&sc->sc_lock);
                    814:
                    815:        return error;
1.12      augustss  816: }
1.43      augustss  817:
1.12      augustss  818: int
1.24      augustss  819: ucomwrite(dev_t dev, struct uio *uio, int flag)
1.12      augustss  820: {
1.115     skrll     821:        const int unit = UCOMUNIT(dev);
                    822:        struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.17      augustss  823:        int error;
1.12      augustss  824:
1.115     skrll     825:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                    826:
1.111     skrll     827:        if (sc == NULL)
                    828:                return EIO;
                    829:
                    830:        mutex_enter(&sc->sc_lock);
                    831:        if (sc->sc_dying) {
1.115     skrll     832:                DPRINTF("... dying", 0, 0, 0, 0);
1.111     skrll     833:                mutex_exit(&sc->sc_lock);
                    834:                return EIO;
                    835:        }
1.43      augustss  836:
1.115     skrll     837:        struct tty *tp = sc->sc_tty;
1.101     jakllsch  838:
1.17      augustss  839:        sc->sc_refcnt++;
1.111     skrll     840:        mutex_exit(&sc->sc_lock);
1.115     skrll     841:
1.32      eeh       842:        error = ((*tp->t_linesw->l_write)(tp, uio, flag));
1.115     skrll     843:
1.111     skrll     844:        mutex_enter(&sc->sc_lock);
1.38      scw       845:        if (--sc->sc_refcnt < 0)
1.115     skrll     846:                cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj       847:        DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0);
1.111     skrll     848:        mutex_exit(&sc->sc_lock);
                    849:
                    850:        return error;
1.38      scw       851: }
                    852:
                    853: int
1.60      christos  854: ucompoll(dev_t dev, int events, struct lwp *l)
1.38      scw       855: {
1.115     skrll     856:        const int unit = UCOMUNIT(dev);
                    857:        struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
                    858:
                    859:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
1.38      scw       860:
1.111     skrll     861:        if (sc == NULL)
                    862:                return POLLHUP;
1.43      augustss  863:
1.111     skrll     864:        mutex_enter(&sc->sc_lock);
                    865:        if (sc->sc_dying) {
1.115     skrll     866:                DPRINTF("... dying", 0, 0, 0, 0);
1.111     skrll     867:                mutex_exit(&sc->sc_lock);
                    868:                return POLLHUP;
                    869:        }
1.115     skrll     870:        struct tty *tp = sc->sc_tty;
1.94      jakllsch  871:
1.38      scw       872:        sc->sc_refcnt++;
1.111     skrll     873:        mutex_exit(&sc->sc_lock);
1.115     skrll     874:
                    875:        int revents = ((*tp->t_linesw->l_poll)(tp, events, l));
                    876:
1.111     skrll     877:        mutex_enter(&sc->sc_lock);
1.17      augustss  878:        if (--sc->sc_refcnt < 0)
1.115     skrll     879:                cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj       880:        DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0);
1.111     skrll     881:        mutex_exit(&sc->sc_lock);
                    882:
                    883:        return revents;
1.12      augustss  884: }
                    885:
                    886: struct tty *
1.24      augustss  887: ucomtty(dev_t dev)
1.12      augustss  888: {
1.115     skrll     889:        const int unit = UCOMUNIT(dev);
                    890:        struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.12      augustss  891:
1.111     skrll     892:        return sc != NULL ? sc->sc_tty : NULL;
1.12      augustss  893: }
                    894:
                    895: int
1.70      christos  896: ucomioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1.12      augustss  897: {
1.115     skrll     898:        const int unit = UCOMUNIT(dev);
                    899:        struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.17      augustss  900:        int error;
                    901:
1.115     skrll     902:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                    903:
1.111     skrll     904:        if (sc == NULL)
                    905:                return EIO;
                    906:
                    907:        mutex_enter(&sc->sc_lock);
                    908:        if (sc->sc_dying) {
1.115     skrll     909:                DPRINTF("... dying", 0, 0, 0, 0);
1.111     skrll     910:                mutex_exit(&sc->sc_lock);
                    911:                return EIO;
                    912:        }
1.101     jakllsch  913:
1.17      augustss  914:        sc->sc_refcnt++;
1.114     skrll     915:        mutex_exit(&sc->sc_lock);
1.115     skrll     916:
1.60      christos  917:        error = ucom_do_ioctl(sc, cmd, data, flag, l);
1.115     skrll     918:
1.114     skrll     919:        mutex_enter(&sc->sc_lock);
1.17      augustss  920:        if (--sc->sc_refcnt < 0)
1.115     skrll     921:                cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj       922:        DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(dev), sc->sc_refcnt, 0, 0);
1.111     skrll     923:        mutex_exit(&sc->sc_lock);
1.115     skrll     924:
1.111     skrll     925:        return error;
1.17      augustss  926: }
                    927:
1.82      martin    928: static int
1.115     skrll     929: ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, void *data, int flag,
                    930:     struct lwp *l)
1.17      augustss  931: {
1.12      augustss  932:        struct tty *tp = sc->sc_tty;
                    933:        int error;
                    934:
1.111     skrll     935:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                    936:
1.118.8.1! snj       937:        DPRINTF("cmd=0x%08jx", cmd, 0, 0, 0);
1.12      augustss  938:
1.60      christos  939:        error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
1.42      atatat    940:        if (error != EPASSTHROUGH)
1.111     skrll     941:                return error;
1.12      augustss  942:
1.60      christos  943:        error = ttioctl(tp, cmd, data, flag, l);
1.42      atatat    944:        if (error != EPASSTHROUGH)
1.111     skrll     945:                return error;
1.12      augustss  946:
                    947:        if (sc->sc_methods->ucom_ioctl != NULL) {
                    948:                error = sc->sc_methods->ucom_ioctl(sc->sc_parent,
1.115     skrll     949:                    sc->sc_portno, cmd, data, flag, l->l_proc);
1.42      atatat    950:                if (error != EPASSTHROUGH)
1.111     skrll     951:                        return error;
1.12      augustss  952:        }
                    953:
                    954:        error = 0;
                    955:
1.118.8.1! snj       956:        DPRINTF("our cmd=0x%08jx", cmd, 0, 0, 0);
1.12      augustss  957:
                    958:        switch (cmd) {
                    959:        case TIOCSBRK:
                    960:                ucom_break(sc, 1);
                    961:                break;
                    962:
                    963:        case TIOCCBRK:
                    964:                ucom_break(sc, 0);
                    965:                break;
                    966:
                    967:        case TIOCSDTR:
                    968:                ucom_dtr(sc, 1);
                    969:                break;
                    970:
                    971:        case TIOCCDTR:
                    972:                ucom_dtr(sc, 0);
                    973:                break;
                    974:
                    975:        case TIOCGFLAGS:
1.114     skrll     976:                mutex_enter(&sc->sc_lock);
1.12      augustss  977:                *(int *)data = sc->sc_swflags;
1.114     skrll     978:                mutex_exit(&sc->sc_lock);
1.12      augustss  979:                break;
                    980:
                    981:        case TIOCSFLAGS:
1.67      elad      982:                error = kauth_authorize_device_tty(l->l_cred,
                    983:                    KAUTH_DEVICE_TTY_PRIVSET, tp);
1.12      augustss  984:                if (error)
                    985:                        break;
1.114     skrll     986:                mutex_enter(&sc->sc_lock);
1.12      augustss  987:                sc->sc_swflags = *(int *)data;
1.114     skrll     988:                mutex_exit(&sc->sc_lock);
1.12      augustss  989:                break;
                    990:
                    991:        case TIOCMSET:
                    992:        case TIOCMBIS:
                    993:        case TIOCMBIC:
                    994:                tiocm_to_ucom(sc, cmd, *(int *)data);
                    995:                break;
                    996:
                    997:        case TIOCMGET:
                    998:                *(int *)data = ucom_to_tiocm(sc);
                    999:                break;
                   1000:
1.106     gdt      1001:        case PPS_IOC_CREATE:
                   1002:        case PPS_IOC_DESTROY:
                   1003:        case PPS_IOC_GETPARAMS:
                   1004:        case PPS_IOC_SETPARAMS:
                   1005:        case PPS_IOC_GETCAP:
                   1006:        case PPS_IOC_FETCH:
                   1007: #ifdef PPS_SYNC
                   1008:        case PPS_IOC_KCBIND:
                   1009: #endif
                   1010:                mutex_spin_enter(&timecounter_lock);
                   1011:                error = pps_ioctl(cmd, data, &sc->sc_pps_state);
                   1012:                mutex_spin_exit(&timecounter_lock);
                   1013:                break;
                   1014:
1.12      augustss 1015:        default:
1.42      atatat   1016:                error = EPASSTHROUGH;
1.12      augustss 1017:                break;
                   1018:        }
                   1019:
1.111     skrll    1020:        return error;
1.12      augustss 1021: }
                   1022:
1.82      martin   1023: static void
1.29      toshii   1024: tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits)
1.12      augustss 1025: {
                   1026:        u_char combits;
1.3       augustss 1027:
1.12      augustss 1028:        combits = 0;
                   1029:        if (ISSET(ttybits, TIOCM_DTR))
                   1030:                SET(combits, UMCR_DTR);
                   1031:        if (ISSET(ttybits, TIOCM_RTS))
                   1032:                SET(combits, UMCR_RTS);
1.43      augustss 1033:
1.114     skrll    1034:        mutex_enter(&sc->sc_lock);
1.12      augustss 1035:        switch (how) {
                   1036:        case TIOCMBIC:
                   1037:                CLR(sc->sc_mcr, combits);
                   1038:                break;
                   1039:
                   1040:        case TIOCMBIS:
                   1041:                SET(sc->sc_mcr, combits);
                   1042:                break;
                   1043:
                   1044:        case TIOCMSET:
                   1045:                CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS);
                   1046:                SET(sc->sc_mcr, combits);
                   1047:                break;
                   1048:        }
1.115     skrll    1049:        u_char mcr = sc->sc_mcr;
1.114     skrll    1050:        mutex_exit(&sc->sc_lock);
1.12      augustss 1051:
1.27      toshii   1052:        if (how == TIOCMSET || ISSET(combits, UMCR_DTR))
1.115     skrll    1053:                ucom_dtr(sc, (mcr & UMCR_DTR) != 0);
1.27      toshii   1054:        if (how == TIOCMSET || ISSET(combits, UMCR_RTS))
1.115     skrll    1055:                ucom_rts(sc, (mcr & UMCR_RTS) != 0);
1.12      augustss 1056: }
                   1057:
1.82      martin   1058: static int
1.24      augustss 1059: ucom_to_tiocm(struct ucom_softc *sc)
1.12      augustss 1060: {
                   1061:        u_char combits;
                   1062:        int ttybits = 0;
                   1063:
1.114     skrll    1064:        mutex_enter(&sc->sc_lock);
1.12      augustss 1065:        combits = sc->sc_mcr;
                   1066:        if (ISSET(combits, UMCR_DTR))
                   1067:                SET(ttybits, TIOCM_DTR);
                   1068:        if (ISSET(combits, UMCR_RTS))
                   1069:                SET(ttybits, TIOCM_RTS);
                   1070:
                   1071:        combits = sc->sc_msr;
                   1072:        if (ISSET(combits, UMSR_DCD))
                   1073:                SET(ttybits, TIOCM_CD);
                   1074:        if (ISSET(combits, UMSR_CTS))
                   1075:                SET(ttybits, TIOCM_CTS);
                   1076:        if (ISSET(combits, UMSR_DSR))
                   1077:                SET(ttybits, TIOCM_DSR);
                   1078:        if (ISSET(combits, UMSR_RI | UMSR_TERI))
                   1079:                SET(ttybits, TIOCM_RI);
                   1080:
                   1081: #if 0
                   1082: XXX;
                   1083:        if (sc->sc_ier != 0)
                   1084:                SET(ttybits, TIOCM_LE);
                   1085: #endif
1.114     skrll    1086:        mutex_exit(&sc->sc_lock);
1.12      augustss 1087:
1.111     skrll    1088:        return ttybits;
1.12      augustss 1089: }
                   1090:
1.82      martin   1091: static void
1.77      cube     1092: ucom_break(struct ucom_softc *sc, int onoff)
1.12      augustss 1093: {
1.111     skrll    1094:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                   1095:
1.118.8.1! snj      1096:        DPRINTF("onoff=%jd", onoff, 0, 0, 0);
1.12      augustss 1097:
1.14      augustss 1098:        if (sc->sc_methods->ucom_set != NULL)
                   1099:                sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
                   1100:                    UCOM_SET_BREAK, onoff);
1.12      augustss 1101: }
                   1102:
1.82      martin   1103: static void
1.24      augustss 1104: ucom_dtr(struct ucom_softc *sc, int onoff)
1.12      augustss 1105: {
1.111     skrll    1106:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                   1107:
1.118.8.1! snj      1108:        DPRINTF("onoff=%jd", onoff, 0, 0, 0);
1.12      augustss 1109:
1.14      augustss 1110:        if (sc->sc_methods->ucom_set != NULL)
1.43      augustss 1111:                sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1.14      augustss 1112:                    UCOM_SET_DTR, onoff);
1.12      augustss 1113: }
                   1114:
1.82      martin   1115: static void
1.24      augustss 1116: ucom_rts(struct ucom_softc *sc, int onoff)
1.12      augustss 1117: {
1.111     skrll    1118:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                   1119:
1.118.8.1! snj      1120:        DPRINTF("onoff=%jd", onoff, 0, 0, 0);
1.12      augustss 1121:
1.14      augustss 1122:        if (sc->sc_methods->ucom_set != NULL)
1.43      augustss 1123:                sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
1.14      augustss 1124:                    UCOM_SET_RTS, onoff);
1.12      augustss 1125: }
                   1126:
1.22      augustss 1127: void
1.24      augustss 1128: ucom_status_change(struct ucom_softc *sc)
1.12      augustss 1129: {
1.27      toshii   1130:        struct tty *tp = sc->sc_tty;
                   1131:
1.14      augustss 1132:        if (sc->sc_methods->ucom_get_status != NULL) {
1.117     skrll    1133:                u_char msr, lsr;
1.115     skrll    1134:
1.14      augustss 1135:                sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno,
1.115     skrll    1136:                    &lsr, &msr);
                   1137:                mutex_enter(&sc->sc_lock);
                   1138:                u_char old_msr = sc->sc_msr;
                   1139:
                   1140:                sc->sc_lsr = lsr;
                   1141:                sc->sc_msr = msr;
                   1142:                mutex_exit(&sc->sc_lock);
                   1143:
                   1144:                if (ISSET((msr ^ old_msr), UMSR_DCD)) {
1.106     gdt      1145:                        mutex_spin_enter(&timecounter_lock);
                   1146:                        pps_capture(&sc->sc_pps_state);
                   1147:                        pps_event(&sc->sc_pps_state,
                   1148:                            (sc->sc_msr & UMSR_DCD) ?
                   1149:                            PPS_CAPTUREASSERT :
                   1150:                            PPS_CAPTURECLEAR);
                   1151:                        mutex_spin_exit(&timecounter_lock);
                   1152:
1.115     skrll    1153:                        (*tp->t_linesw->l_modem)(tp, ISSET(msr, UMSR_DCD));
1.106     gdt      1154:                }
1.14      augustss 1155:        } else {
1.115     skrll    1156:                mutex_enter(&sc->sc_lock);
1.14      augustss 1157:                sc->sc_lsr = 0;
1.54      augustss 1158:                /* Assume DCD is present, if we have no chance to check it. */
                   1159:                sc->sc_msr = UMSR_DCD;
1.115     skrll    1160:                mutex_exit(&sc->sc_lock);
1.14      augustss 1161:        }
1.12      augustss 1162: }
                   1163:
1.82      martin   1164: static int
1.24      augustss 1165: ucomparam(struct tty *tp, struct termios *t)
1.12      augustss 1166: {
1.115     skrll    1167:        const int unit = UCOMUNIT(tp->t_dev);
                   1168:        struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
                   1169:        int error = 0;
1.12      augustss 1170:
1.111     skrll    1171:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                   1172:
1.115     skrll    1173:        if (sc == NULL)
1.111     skrll    1174:                return EIO;
1.12      augustss 1175:
1.115     skrll    1176:        mutex_enter(&sc->sc_lock);
                   1177:        if (sc->sc_dying) {
                   1178:                DPRINTF("... dying", 0, 0, 0, 0);
                   1179:                mutex_exit(&sc->sc_lock);
                   1180:                return EIO;
                   1181:        }
                   1182:
                   1183:        sc->sc_refcnt++;
                   1184:        mutex_exit(&sc->sc_lock);
                   1185:
1.12      augustss 1186:        /* Check requested parameters. */
1.115     skrll    1187:        if (t->c_ispeed && t->c_ispeed != t->c_ospeed) {
                   1188:                error = EINVAL;
                   1189:                goto out;
                   1190:        }
1.12      augustss 1191:
                   1192:        /*
                   1193:         * For the console, always force CLOCAL and !HUPCL, so that the port
                   1194:         * is always active.
                   1195:         */
                   1196:        if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) {
                   1197:                SET(t->c_cflag, CLOCAL);
                   1198:                CLR(t->c_cflag, HUPCL);
                   1199:        }
                   1200:
                   1201:        /*
                   1202:         * If there were no changes, don't do anything.  This avoids dropping
                   1203:         * input and improves performance when all we did was frob things like
                   1204:         * VMIN and VTIME.
                   1205:         */
                   1206:        if (tp->t_ospeed == t->c_ospeed &&
1.115     skrll    1207:            tp->t_cflag == t->c_cflag) {
                   1208:                goto out;
                   1209:        }
1.12      augustss 1210:
1.30      augustss 1211:        /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */
1.12      augustss 1212:
                   1213:        /* And copy to tty. */
                   1214:        tp->t_ispeed = 0;
                   1215:        tp->t_ospeed = t->c_ospeed;
                   1216:        tp->t_cflag = t->c_cflag;
                   1217:
1.14      augustss 1218:        if (sc->sc_methods->ucom_param != NULL) {
                   1219:                error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno,
1.115     skrll    1220:                    t);
1.14      augustss 1221:                if (error)
1.115     skrll    1222:                        goto out;
1.14      augustss 1223:        }
1.12      augustss 1224:
1.30      augustss 1225:        /* XXX worry about CHWFLOW */
1.12      augustss 1226:
                   1227:        /*
                   1228:         * Update the tty layer's idea of the carrier bit, in case we changed
                   1229:         * CLOCAL or MDMBUF.  We don't hang up here; we only do that by
                   1230:         * explicit request.
                   1231:         */
1.111     skrll    1232:        DPRINTF("l_modem", 0, 0, 0, 0);
1.54      augustss 1233:        (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD));
1.12      augustss 1234:
                   1235: #if 0
                   1236: XXX what if the hardware is not open
                   1237:        if (!ISSET(t->c_cflag, CHWFLOW)) {
                   1238:                if (sc->sc_tx_stopped) {
                   1239:                        sc->sc_tx_stopped = 0;
                   1240:                        ucomstart(tp);
                   1241:                }
                   1242:        }
                   1243: #endif
1.115     skrll    1244: out:
                   1245:        mutex_enter(&sc->sc_lock);
                   1246:        if (--sc->sc_refcnt < 0)
                   1247:                cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj      1248:        DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(tp->t_dev), sc->sc_refcnt,
        !          1249:            0, 0);
1.115     skrll    1250:
                   1251:        mutex_exit(&sc->sc_lock);
1.12      augustss 1252:
1.111     skrll    1253:        return 0;
1.12      augustss 1254: }
                   1255:
1.82      martin   1256: static int
                   1257: ucomhwiflow(struct tty *tp, int block)
1.12      augustss 1258: {
1.115     skrll    1259:        const int unit = UCOMUNIT(tp->t_dev);
                   1260:        struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.82      martin   1261:        int old;
1.12      augustss 1262:
1.115     skrll    1263:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                   1264:
1.101     jakllsch 1265:        if (sc == NULL)
1.111     skrll    1266:                return 0;
1.101     jakllsch 1267:
1.111     skrll    1268:        mutex_enter(&sc->sc_lock);
1.82      martin   1269:        old = sc->sc_rx_stopped;
                   1270:        sc->sc_rx_stopped = (u_char)block;
1.12      augustss 1271:
1.82      martin   1272:        if (old && !block) {
                   1273:                sc->sc_rx_unblock = 1;
                   1274:                softint_schedule(sc->sc_si);
1.12      augustss 1275:        }
1.111     skrll    1276:        mutex_exit(&sc->sc_lock);
1.82      martin   1277:
1.111     skrll    1278:        return 1;
1.1       augustss 1279: }
1.3       augustss 1280:
1.82      martin   1281: static void
1.24      augustss 1282: ucomstart(struct tty *tp)
1.12      augustss 1283: {
1.115     skrll    1284:        const int unit = UCOMUNIT(tp->t_dev);
                   1285:        struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.82      martin   1286:        struct ucom_buffer *ub;
1.12      augustss 1287:        u_char *data;
                   1288:        int cnt;
                   1289:
1.115     skrll    1290:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                   1291:
1.111     skrll    1292:        if (sc == NULL)
                   1293:                return;
                   1294:
                   1295:        KASSERT(&sc->sc_lock);
                   1296:        KASSERT(mutex_owned(&tty_lock));
                   1297:        if (sc->sc_dying) {
1.115     skrll    1298:                DPRINTF("... dying", 0, 0, 0, 0);
1.12      augustss 1299:                return;
1.111     skrll    1300:        }
1.12      augustss 1301:
1.84      christos 1302:        if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
1.12      augustss 1303:                goto out;
                   1304:        if (sc->sc_tx_stopped)
                   1305:                goto out;
                   1306:
1.82      martin   1307:        if (!ttypull(tp))
1.73      ad       1308:                goto out;
1.12      augustss 1309:
                   1310:        /* Grab the first contiguous region of buffer space. */
                   1311:        data = tp->t_outq.c_cf;
                   1312:        cnt = ndqb(&tp->t_outq, 0);
                   1313:
1.84      christos 1314:        if (cnt == 0)
1.12      augustss 1315:                goto out;
                   1316:
1.82      martin   1317:        ub = SIMPLEQ_FIRST(&sc->sc_obuff_free);
1.100     mlelstv  1318:        if (ub == NULL) {
                   1319:                SET(tp->t_state, TS_BUSY);
                   1320:                goto out;
                   1321:        }
1.111     skrll    1322:
1.82      martin   1323:        SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_free, ub_link);
1.12      augustss 1324:
1.82      martin   1325:        if (SIMPLEQ_FIRST(&sc->sc_obuff_free) == NULL)
                   1326:                SET(tp->t_state, TS_BUSY);
                   1327:
                   1328:        if (cnt > sc->sc_obufsize)
1.19      augustss 1329:                cnt = sc->sc_obufsize;
1.82      martin   1330:
1.22      augustss 1331:        if (sc->sc_methods->ucom_write != NULL)
                   1332:                sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno,
1.115     skrll    1333:                    ub->ub_data, data, &cnt);
1.22      augustss 1334:        else
1.82      martin   1335:                memcpy(ub->ub_data, data, cnt);
                   1336:
                   1337:        ub->ub_len = cnt;
                   1338:        ub->ub_index = 0;
1.12      augustss 1339:
1.82      martin   1340:        SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_full, ub, ub_link);
                   1341:
                   1342:        softint_schedule(sc->sc_si);
1.3       augustss 1343:
1.82      martin   1344:  out:
1.115     skrll    1345:        DPRINTF("... done", 0, 0, 0, 0);
1.111     skrll    1346:        return;
1.12      augustss 1347: }
                   1348:
1.21      itojun   1349: void
1.69      christos 1350: ucomstop(struct tty *tp, int flag)
1.12      augustss 1351: {
1.19      augustss 1352: #if 0
1.115     skrll    1353:        const int unit = UCOMUNIT(tp->t_dev);
                   1354:        struct ucom_softc * const sc = device_lookup_private(&ucom_cd, unit);
1.12      augustss 1355:
1.111     skrll    1356:        mutex_enter(&sc->sc_lock);
                   1357:        mutex_spin_enter(&tty_lock);
1.12      augustss 1358:        if (ISSET(tp->t_state, TS_BUSY)) {
1.111     skrll    1359:                /* obuff_full -> obuff_free? */
1.19      augustss 1360:                /* sc->sc_tx_stopped = 1; */
1.12      augustss 1361:                if (!ISSET(tp->t_state, TS_TTSTOP))
                   1362:                        SET(tp->t_state, TS_FLUSH);
                   1363:        }
1.111     skrll    1364:        mutex_spin_exit(&tty_lock);
                   1365:        mutex_exit(&sc->sc_lock);
1.19      augustss 1366: #endif
1.12      augustss 1367: }
                   1368:
1.82      martin   1369: static void
                   1370: ucom_write_status(struct ucom_softc *sc, struct ucom_buffer *ub,
                   1371:     usbd_status err)
                   1372: {
                   1373:        struct tty *tp = sc->sc_tty;
                   1374:        uint32_t cc = ub->ub_len;
                   1375:
1.111     skrll    1376:        KASSERT(mutex_owned(&sc->sc_lock));
                   1377:
1.82      martin   1378:        switch (err) {
                   1379:        case USBD_IN_PROGRESS:
                   1380:                ub->ub_index = ub->ub_len;
                   1381:                break;
                   1382:        case USBD_STALLED:
                   1383:                ub->ub_index = 0;
                   1384:                softint_schedule(sc->sc_si);
                   1385:                break;
                   1386:        case USBD_NORMAL_COMPLETION:
                   1387:                usbd_get_xfer_status(ub->ub_xfer, NULL, NULL, &cc, NULL);
                   1388:                rnd_add_uint32(&sc->sc_rndsource, cc);
                   1389:                /*FALLTHROUGH*/
                   1390:        default:
                   1391:                SIMPLEQ_REMOVE_HEAD(&sc->sc_obuff_full, ub_link);
                   1392:                SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
                   1393:                cc -= sc->sc_opkthdrlen;
                   1394:
1.100     mlelstv  1395:                mutex_spin_enter(&tty_lock);
1.82      martin   1396:                CLR(tp->t_state, TS_BUSY);
                   1397:                if (ISSET(tp->t_state, TS_FLUSH))
                   1398:                        CLR(tp->t_state, TS_FLUSH);
                   1399:                else
                   1400:                        ndflush(&tp->t_outq, cc);
1.100     mlelstv  1401:                mutex_spin_exit(&tty_lock);
1.82      martin   1402:
                   1403:                if (err != USBD_CANCELLED && err != USBD_IOERROR &&
                   1404:                    !sc->sc_dying) {
                   1405:                        if ((ub = SIMPLEQ_FIRST(&sc->sc_obuff_full)) != NULL)
                   1406:                                ucom_submit_write(sc, ub);
                   1407:
1.111     skrll    1408:                        mutex_spin_enter(&tty_lock);
1.82      martin   1409:                        (*tp->t_linesw->l_start)(tp);
1.111     skrll    1410:                        mutex_spin_exit(&tty_lock);
1.82      martin   1411:                }
                   1412:                break;
                   1413:        }
                   1414: }
                   1415:
                   1416: static void
                   1417: ucom_submit_write(struct ucom_softc *sc, struct ucom_buffer *ub)
                   1418: {
                   1419:
1.111     skrll    1420:        KASSERT(mutex_owned(&sc->sc_lock));
                   1421:
                   1422:        usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, ub->ub_len,
                   1423:            0, USBD_NO_TIMEOUT, ucomwritecb);
1.82      martin   1424:
                   1425:        ucom_write_status(sc, ub, usbd_transfer(ub->ub_xfer));
                   1426: }
                   1427:
                   1428: static void
1.111     skrll    1429: ucomwritecb(struct usbd_xfer *xfer, void *p, usbd_status status)
1.12      augustss 1430: {
                   1431:        struct ucom_softc *sc = (struct ucom_softc *)p;
1.82      martin   1432:
1.111     skrll    1433:        mutex_enter(&sc->sc_lock);
1.82      martin   1434:        ucom_write_status(sc, SIMPLEQ_FIRST(&sc->sc_obuff_full), status);
1.111     skrll    1435:        mutex_exit(&sc->sc_lock);
1.82      martin   1436:
                   1437: }
                   1438:
                   1439: static void
                   1440: ucom_softintr(void *arg)
                   1441: {
1.115     skrll    1442:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                   1443:
1.82      martin   1444:        struct ucom_softc *sc = arg;
1.12      augustss 1445:
1.111     skrll    1446:        mutex_enter(&sc->sc_lock);
1.115     skrll    1447:        if (sc->sc_dying) {
                   1448:                DPRINTF("... dying", 0, 0, 0, 0);
                   1449:                mutex_exit(&sc->sc_lock);
                   1450:                return;
                   1451:        }
                   1452:
                   1453:        struct tty *tp = sc->sc_tty;
1.111     skrll    1454:        mutex_enter(&tty_lock);
                   1455:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
                   1456:                mutex_exit(&tty_lock);
                   1457:                mutex_exit(&sc->sc_lock);
1.82      martin   1458:                return;
1.111     skrll    1459:        }
                   1460:        mutex_exit(&tty_lock);
1.12      augustss 1461:
1.115     skrll    1462:        struct ucom_buffer *ub = SIMPLEQ_FIRST(&sc->sc_obuff_full);
1.82      martin   1463:
                   1464:        if (ub != NULL && ub->ub_index == 0)
                   1465:                ucom_submit_write(sc, ub);
1.12      augustss 1466:
1.82      martin   1467:        if (sc->sc_rx_unblock)
                   1468:                ucom_read_complete(sc);
1.12      augustss 1469:
1.111     skrll    1470:        mutex_exit(&sc->sc_lock);
1.82      martin   1471: }
                   1472:
                   1473: static void
                   1474: ucom_read_complete(struct ucom_softc *sc)
                   1475: {
                   1476:        int (*rint)(int, struct tty *);
                   1477:        struct ucom_buffer *ub;
                   1478:        struct tty *tp;
1.111     skrll    1479:
                   1480:        KASSERT(mutex_owned(&sc->sc_lock));
1.82      martin   1481:
                   1482:        tp = sc->sc_tty;
                   1483:        rint = tp->t_linesw->l_rint;
                   1484:        ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full);
1.39      augustss 1485:
1.82      martin   1486:        while (ub != NULL && !sc->sc_rx_stopped) {
                   1487:
1.111     skrll    1488:                /* XXX ttyinput takes tty_lock */
1.82      martin   1489:                while (ub->ub_index < ub->ub_len && !sc->sc_rx_stopped) {
                   1490:                        /* Give characters to tty layer. */
                   1491:                        if ((*rint)(ub->ub_data[ub->ub_index], tp) == -1) {
                   1492:                                /* Overflow: drop remainder */
                   1493:                                ub->ub_index = ub->ub_len;
                   1494:                        } else
                   1495:                                ub->ub_index++;
                   1496:                }
                   1497:
                   1498:                if (ub->ub_index == ub->ub_len) {
                   1499:                        SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_full, ub_link);
                   1500:
1.115     skrll    1501:                        sc->sc_refcnt--;
                   1502:                        /* increments sc_refcnt */
1.82      martin   1503:                        ucomsubmitread(sc, ub);
                   1504:
                   1505:                        ub = SIMPLEQ_FIRST(&sc->sc_ibuff_full);
                   1506:                }
                   1507:        }
                   1508:
                   1509:        sc->sc_rx_unblock = (ub != NULL);
1.12      augustss 1510: }
                   1511:
1.115     skrll    1512: static int
1.82      martin   1513: ucomsubmitread(struct ucom_softc *sc, struct ucom_buffer *ub)
1.12      augustss 1514: {
                   1515:        usbd_status err;
                   1516:
1.115     skrll    1517:        KASSERT(mutex_owned(&sc->sc_lock));
                   1518:
1.111     skrll    1519:        usbd_setup_xfer(ub->ub_xfer, sc, ub->ub_data, sc->sc_ibufsize,
                   1520:            USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, ucomreadcb);
1.82      martin   1521:
                   1522:        if ((err = usbd_transfer(ub->ub_xfer)) != USBD_IN_PROGRESS) {
                   1523:                /* XXX: Recover from this, please! */
1.115     skrll    1524:                printf("%s: err=%s\n", __func__, usbd_errstr(err));
                   1525:                return EIO;
1.12      augustss 1526:        }
1.82      martin   1527:
1.115     skrll    1528:        sc->sc_refcnt++;
                   1529:
1.82      martin   1530:        SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_empty, ub, ub_link);
                   1531:
1.115     skrll    1532:        return 0;
1.12      augustss 1533: }
1.43      augustss 1534:
1.82      martin   1535: static void
1.111     skrll    1536: ucomreadcb(struct usbd_xfer *xfer, void *p, usbd_status status)
1.12      augustss 1537: {
                   1538:        struct ucom_softc *sc = (struct ucom_softc *)p;
1.82      martin   1539:        struct ucom_buffer *ub;
1.111     skrll    1540:        uint32_t cc;
1.12      augustss 1541:        u_char *cp;
                   1542:
1.111     skrll    1543:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                   1544:
1.115     skrll    1545:        mutex_enter(&sc->sc_lock);
                   1546:
                   1547:        struct tty *tp = sc->sc_tty;
1.112     skrll    1548:
1.115     skrll    1549:        if (status == USBD_CANCELLED || status == USBD_IOERROR ||
1.34      augustss 1550:            sc->sc_dying) {
1.115     skrll    1551:
1.118.8.1! snj      1552:                DPRINTF("... done (status %jd dying %jd)", status, sc->sc_dying,
1.115     skrll    1553:                    0, 0);
                   1554:
                   1555:                if (status == USBD_IOERROR || sc->sc_dying) {
                   1556:                        /* Send something to wake upper layer */
                   1557:                        (tp->t_linesw->l_rint)('\n', tp);
                   1558:                        mutex_spin_enter(&tty_lock);    /* XXX */
                   1559:                        ttwakeup(tp);
                   1560:                        mutex_spin_exit(&tty_lock);     /* XXX */
                   1561:                }
                   1562:
                   1563:                if (--sc->sc_refcnt < 0)
                   1564:                        cv_broadcast(&sc->sc_detachcv);
1.118.8.1! snj      1565:                DPRINTF("unit=%jd refcnt %jd", UCOMUNIT(tp->t_dev),
        !          1566:                    sc->sc_refcnt, 0, 0);
1.111     skrll    1567:                mutex_exit(&sc->sc_lock);
1.115     skrll    1568:
1.12      augustss 1569:                return;
1.34      augustss 1570:        }
1.12      augustss 1571:
1.112     skrll    1572:        ub = SIMPLEQ_FIRST(&sc->sc_ibuff_empty);
                   1573:        SIMPLEQ_REMOVE_HEAD(&sc->sc_ibuff_empty, ub_link);
                   1574:
1.115     skrll    1575:        if (status != USBD_NORMAL_COMPLETION) {
                   1576:                if (status == USBD_STALLED) {
                   1577:                        usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
                   1578:                } else {
                   1579:                        printf("ucomreadcb: wonky status=%s\n",
                   1580:                            usbd_errstr(status));
                   1581:                }
                   1582:
1.118.8.1! snj      1583:                DPRINTF("... done (status %jd)", status, 0, 0, 0);
1.115     skrll    1584:                sc->sc_refcnt--;
                   1585:                /* re-adds ub to sc_ibuff_empty and increments sc_refcnt */
1.82      martin   1586:                ucomsubmitread(sc, ub);
1.111     skrll    1587:                mutex_exit(&sc->sc_lock);
1.82      martin   1588:                return;
                   1589:        }
                   1590:
1.48      thorpej  1591:        usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL);
1.82      martin   1592:
1.95      jakllsch 1593: #ifdef UCOM_DEBUG
                   1594:        /* This is triggered by uslsa(4) occasionally. */
                   1595:        if ((ucomdebug > 0) && (cc == 0)) {
                   1596:                device_printf(sc->sc_dev, "ucomreadcb: zero length xfer!\n");
1.82      martin   1597:        }
1.95      jakllsch 1598: #endif
1.82      martin   1599:        KDASSERT(cp == ub->ub_data);
                   1600:
1.31      explorer 1601:        rnd_add_uint32(&sc->sc_rndsource, cc);
1.82      martin   1602:
1.115     skrll    1603:        if (sc->sc_state != UCOM_OPEN) {
                   1604:                /* Go around again - we're not quite ready */
                   1605:                sc->sc_refcnt--;
                   1606:                /* re-adds ub to sc_ibuff_empty and increments sc_refcnt */
1.82      martin   1607:                ucomsubmitread(sc, ub);
1.111     skrll    1608:                mutex_exit(&sc->sc_lock);
1.115     skrll    1609:                DPRINTF("... done (not open)", 0, 0, 0, 0);
1.82      martin   1610:                return;
                   1611:        }
                   1612:
1.118     skrll    1613:        mutex_exit(&sc->sc_lock);
1.82      martin   1614:        if (sc->sc_methods->ucom_read != NULL) {
1.22      augustss 1615:                sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno,
1.82      martin   1616:                    &cp, &cc);
                   1617:                ub->ub_index = (u_int)(cp - ub->ub_data);
                   1618:        } else
                   1619:                ub->ub_index = 0;
                   1620:
                   1621:        ub->ub_len = cc;
1.22      augustss 1622:
1.118     skrll    1623:        mutex_enter(&sc->sc_lock);
                   1624:        if (sc->sc_dying) {
                   1625:                if (--sc->sc_refcnt < 0)
                   1626:                        cv_broadcast(&sc->sc_detachcv);
                   1627:                mutex_exit(&sc->sc_lock);
                   1628:                DPRINTF("... dying", 0, 0, 0, 0);
                   1629:                return;
                   1630:        }
                   1631:
1.82      martin   1632:        SIMPLEQ_INSERT_TAIL(&sc->sc_ibuff_full, ub, ub_link);
1.12      augustss 1633:
1.82      martin   1634:        ucom_read_complete(sc);
1.111     skrll    1635:        mutex_exit(&sc->sc_lock);
1.115     skrll    1636:
                   1637:        DPRINTF("... done", 0, 0, 0, 0);
1.12      augustss 1638: }
                   1639:
1.82      martin   1640: static void
1.24      augustss 1641: ucom_cleanup(struct ucom_softc *sc)
1.12      augustss 1642: {
1.82      martin   1643:
1.111     skrll    1644:        UCOMHIST_FUNC(); UCOMHIST_CALLED();
                   1645:
                   1646:        DPRINTF("aborting pipes", 0, 0, 0, 0);
                   1647:
1.115     skrll    1648:        mutex_enter(&sc->sc_lock);
                   1649:
                   1650:        /* If we're dying then the detach routine will abort our pipes, etc */
                   1651:        if (sc->sc_dying) {
                   1652:                DPRINTF("... dying", 0, 0, 0, 0);
                   1653:
                   1654:                mutex_exit(&sc->sc_lock);
                   1655:                return;
                   1656:        }
1.12      augustss 1657:
1.116     skrll    1658:        mutex_exit(&sc->sc_lock);
                   1659:
1.12      augustss 1660:        ucom_shutdown(sc);
1.115     skrll    1661:
1.33      augustss 1662:        if (sc->sc_bulkin_pipe != NULL) {
1.112     skrll    1663:                usbd_abort_pipe(sc->sc_bulkin_pipe);
1.33      augustss 1664:        }
                   1665:        if (sc->sc_bulkout_pipe != NULL) {
1.112     skrll    1666:                usbd_abort_pipe(sc->sc_bulkout_pipe);
1.33      augustss 1667:        }
1.12      augustss 1668: }
1.13      augustss 1669:
                   1670: #endif /* NUCOM > 0 */
1.12      augustss 1671:
1.20      augustss 1672: int
1.24      augustss 1673: ucomprint(void *aux, const char *pnp)
1.12      augustss 1674: {
1.111     skrll    1675:        struct ucom_attach_args *ucaa = aux;
1.12      augustss 1676:
                   1677:        if (pnp)
1.49      thorpej  1678:                aprint_normal("ucom at %s", pnp);
1.111     skrll    1679:        if (ucaa->ucaa_portno != UCOM_UNK_PORTNO)
                   1680:                aprint_normal(" portno %d", ucaa->ucaa_portno);
                   1681:        return UNCONF;
1.12      augustss 1682: }
                   1683:
1.20      augustss 1684: int
1.77      cube     1685: ucomsubmatch(device_t parent, cfdata_t cf,
1.69      christos 1686:             const int *ldesc, void *aux)
1.12      augustss 1687: {
1.111     skrll    1688:        struct ucom_attach_args *ucaa = aux;
1.12      augustss 1689:
1.111     skrll    1690:        if (ucaa->ucaa_portno != UCOM_UNK_PORTNO &&
1.53      drochner 1691:            cf->cf_loc[UCOMBUSCF_PORTNO] != UCOMBUSCF_PORTNO_DEFAULT &&
1.111     skrll    1692:            cf->cf_loc[UCOMBUSCF_PORTNO] != ucaa->ucaa_portno)
                   1693:                return 0;
                   1694:        return config_match(parent, cf, aux);
1.12      augustss 1695: }

CVSweb <webmaster@jp.NetBSD.org>