root/dev/usb/ucom.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ucom_lock
  2. ucom_unlock
  3. ucom_match
  4. ucom_attach
  5. ucom_detach
  6. ucom_activate
  7. ucom_shutdown
  8. ucomopen
  9. ucomclose
  10. ucomread
  11. ucomwrite
  12. ucomtty
  13. ucomioctl
  14. ucom_do_ioctl
  15. tiocm_to_ucom
  16. ucom_to_tiocm
  17. ucom_break
  18. ucom_dtr
  19. ucom_rts
  20. ucom_status_change
  21. ucomparam
  22. ucom_hwiflow
  23. ucomstart
  24. ucomstop
  25. ucomwritecb
  26. ucomstartread
  27. ucomreadcb
  28. ucom_cleanup
  29. ucomprint
  30. ucomsubmatch

    1 /*      $OpenBSD: ucom.c,v 1.41 2007/06/14 10:11:15 mbalmer Exp $ */
    2 /*      $NetBSD: ucom.c,v 1.49 2003/01/01 00:10:25 thorpej Exp $        */
    3 
    4 /*
    5  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Lennart Augustsson (lennart@augustsson.net) at
   10  * Carlstedt Research & Technology.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *        This product includes software developed by the NetBSD
   23  *        Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 /*
   41  * This code is very heavily based on the 16550 driver, com.c.
   42  */
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/rwlock.h>
   48 #include <sys/ioctl.h>
   49 #include <sys/conf.h>
   50 #include <sys/tty.h>
   51 #include <sys/file.h>
   52 #include <sys/selinfo.h>
   53 #include <sys/proc.h>
   54 #include <sys/vnode.h>
   55 #include <sys/device.h>
   56 #include <sys/poll.h>
   57 
   58 #include <dev/usb/usb.h>
   59 
   60 #include <dev/usb/usbdi.h>
   61 #include <dev/usb/usbdi_util.h>
   62 #include <dev/usb/uhidev.h>
   63 #include <dev/usb/usbdevs.h>
   64 #include <dev/usb/usb_quirks.h>
   65 
   66 #include <dev/usb/ucomvar.h>
   67 
   68 #include "ucom.h"
   69 
   70 #if NUCOM > 0
   71 
   72 #ifdef UCOM_DEBUG
   73 #define DPRINTFN(n, x)  do { if (ucomdebug > (n)) printf x; } while (0)
   74 int ucomdebug = 0;
   75 #else
   76 #define DPRINTFN(n, x)
   77 #endif
   78 #define DPRINTF(x) DPRINTFN(0, x)
   79 
   80 #define UCOMUNIT_MASK           0x7f
   81 #define UCOMCUA_MASK            0x80
   82 
   83 #define LINESW(tp, func)        (linesw[(tp)->t_line].func)
   84 
   85 #define UCOMUNIT(x)             (minor(x) & UCOMUNIT_MASK)
   86 #define UCOMCUA(x)              (minor(x) & UCOMCUA_MASK)
   87 
   88 struct ucom_softc {
   89         struct device           sc_dev;         /* base device */
   90 
   91         usbd_device_handle      sc_udev;        /* USB device */
   92         struct uhidev_softc     *sc_uhidev;     /* hid device (if deeper) */
   93 
   94         usbd_interface_handle   sc_iface;       /* data interface */
   95 
   96         int                     sc_bulkin_no;   /* bulk in endpoint address */
   97         usbd_pipe_handle        sc_bulkin_pipe; /* bulk in pipe */
   98         usbd_xfer_handle        sc_ixfer;       /* read request */
   99         u_char                  *sc_ibuf;       /* read buffer */
  100         u_int                   sc_ibufsize;    /* read buffer size */
  101         u_int                   sc_ibufsizepad; /* read buffer size padded */
  102 
  103         int                     sc_bulkout_no;  /* bulk out endpoint address */
  104         usbd_pipe_handle        sc_bulkout_pipe;/* bulk out pipe */
  105         usbd_xfer_handle        sc_oxfer;       /* write request */
  106         u_char                  *sc_obuf;       /* write buffer */
  107         u_int                   sc_obufsize;    /* write buffer size */
  108         u_int                   sc_opkthdrlen;  /* header length of
  109                                                  * output packet */
  110 
  111         usbd_pipe_handle        sc_ipipe;       /* hid interrupt input pipe */
  112         usbd_pipe_handle        sc_opipe;       /* hid interrupt pipe */
  113 
  114         struct ucom_methods     *sc_methods;
  115         void                    *sc_parent;
  116         int                     sc_portno;
  117 
  118         struct tty              *sc_tty;        /* our tty */
  119         u_char                  sc_lsr;
  120         u_char                  sc_msr;
  121         u_char                  sc_mcr;
  122         u_char                  sc_tx_stopped;
  123         int                     sc_swflags;
  124 
  125         u_char                  sc_cua;
  126 
  127         struct rwlock           sc_lock;        /* lock during open */
  128         int                     sc_open;
  129         int                     sc_refcnt;
  130         u_char                  sc_dying;       /* disconnecting */
  131 };
  132 
  133 void    ucom_cleanup(struct ucom_softc *);
  134 void    ucom_hwiflow(struct ucom_softc *);
  135 int     ucomparam(struct tty *, struct termios *);
  136 void    ucomstart(struct tty *);
  137 void    ucom_shutdown(struct ucom_softc *);
  138 int     ucom_do_ioctl(struct ucom_softc *, u_long, caddr_t,
  139                               int, struct proc *);
  140 void    ucom_dtr(struct ucom_softc *, int);
  141 void    ucom_rts(struct ucom_softc *, int);
  142 void    ucom_break(struct ucom_softc *, int);
  143 usbd_status ucomstartread(struct ucom_softc *);
  144 void    ucomreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status);
  145 void    ucomwritecb(usbd_xfer_handle, usbd_private_handle, usbd_status);
  146 void    tiocm_to_ucom(struct ucom_softc *, u_long, int);
  147 int     ucom_to_tiocm(struct ucom_softc *);
  148 void    ucom_lock(struct ucom_softc *);
  149 void    ucom_unlock(struct ucom_softc *);
  150 
  151 int ucom_match(struct device *, void *, void *); 
  152 void ucom_attach(struct device *, struct device *, void *); 
  153 int ucom_detach(struct device *, int); 
  154 int ucom_activate(struct device *, enum devact); 
  155 
  156 struct cfdriver ucom_cd = { 
  157         NULL, "ucom", DV_DULL 
  158 }; 
  159 
  160 const struct cfattach ucom_ca = { 
  161         sizeof(struct ucom_softc), 
  162         ucom_match, 
  163         ucom_attach, 
  164         ucom_detach, 
  165         ucom_activate, 
  166 };
  167 
  168 void
  169 ucom_lock(struct ucom_softc *sc)
  170 {
  171         sc->sc_refcnt++;
  172         rw_enter_write(&sc->sc_lock);
  173 }
  174 
  175 void
  176 ucom_unlock(struct ucom_softc *sc)
  177 {
  178         rw_exit_write(&sc->sc_lock);
  179         if (--sc->sc_refcnt < 0)
  180                 usb_detach_wakeup(&sc->sc_dev);
  181 }
  182 
  183 int
  184 ucom_match(struct device *parent, void *match, void *aux)
  185 {
  186         return (1);
  187 }
  188 
  189 void
  190 ucom_attach(struct device *parent, struct device *self, void *aux)
  191 {
  192         struct ucom_softc *sc = (struct ucom_softc *)self;
  193         struct ucom_attach_args *uca = aux;
  194         struct tty *tp;
  195 
  196         if (uca->info != NULL)
  197                 printf(", %s", uca->info);
  198         printf("\n");
  199 
  200         sc->sc_udev = uca->device;
  201         sc->sc_iface = uca->iface;
  202         sc->sc_bulkout_no = uca->bulkout;
  203         sc->sc_bulkin_no = uca->bulkin;
  204         sc->sc_uhidev = uca->uhidev;
  205         sc->sc_ibufsize = uca->ibufsize;
  206         sc->sc_ibufsizepad = uca->ibufsizepad;
  207         sc->sc_obufsize = uca->obufsize;
  208         sc->sc_opkthdrlen = uca->opkthdrlen;
  209         sc->sc_methods = uca->methods;
  210         sc->sc_parent = uca->arg;
  211         sc->sc_portno = uca->portno;
  212 
  213         tp = ttymalloc();
  214         tp->t_oproc = ucomstart;
  215         tp->t_param = ucomparam;
  216         sc->sc_tty = tp;
  217         sc->sc_cua = 0;
  218 
  219         rw_init(&sc->sc_lock, "ucomlk");
  220 
  221         sc->sc_open = 0;
  222 }
  223 
  224 int
  225 ucom_detach(struct device *self, int flags)
  226 {
  227         struct ucom_softc *sc = (struct ucom_softc *)self;
  228         struct tty *tp = sc->sc_tty;
  229         int maj, mn;
  230         int s;
  231 
  232         DPRINTF(("ucom_detach: sc=%p flags=%d tp=%p, pipe=%d,%d\n",
  233                  sc, flags, tp, sc->sc_bulkin_no, sc->sc_bulkout_no));
  234 
  235         sc->sc_dying = 1;
  236 
  237         if (sc->sc_bulkin_pipe != NULL)
  238                 usbd_abort_pipe(sc->sc_bulkin_pipe);
  239         if (sc->sc_bulkout_pipe != NULL)
  240                 usbd_abort_pipe(sc->sc_bulkout_pipe);
  241 
  242         s = splusb();
  243         if (--sc->sc_refcnt >= 0) {
  244                 /* Wake up anyone waiting */
  245                 if (tp != NULL) {
  246                         CLR(tp->t_state, TS_CARR_ON);
  247                         CLR(tp->t_cflag, CLOCAL | MDMBUF);
  248                         ttyflush(tp, FREAD|FWRITE);
  249                 }
  250                 /* Wait for processes to go away. */
  251                 usb_detach_wait(&sc->sc_dev);
  252         }
  253         splx(s);
  254 
  255         /* locate the major number */
  256         for (maj = 0; maj < nchrdev; maj++)
  257                 if (cdevsw[maj].d_open == ucomopen)
  258                         break;
  259 
  260         /* Nuke the vnodes for any open instances. */
  261         mn = self->dv_unit;
  262         DPRINTF(("ucom_detach: maj=%d mn=%d\n", maj, mn));
  263         vdevgone(maj, mn, mn, VCHR);
  264         vdevgone(maj, mn | UCOMCUA_MASK, mn | UCOMCUA_MASK, VCHR);
  265 
  266         /* Detach and free the tty. */
  267         if (tp != NULL) {
  268                 ttyfree(tp);
  269                 sc->sc_tty = NULL;
  270         }
  271 
  272         return (0);
  273 }
  274 
  275 int
  276 ucom_activate(struct device *self, enum devact act)
  277 {
  278         struct ucom_softc *sc = (struct ucom_softc *)self;
  279 
  280         DPRINTFN(5,("ucom_activate: %d\n", act));
  281 
  282         switch (act) {
  283         case DVACT_ACTIVATE:
  284                 break;
  285 
  286         case DVACT_DEACTIVATE:
  287                 sc->sc_dying = 1;
  288                 break;
  289         }
  290         return (0);
  291 }
  292 
  293 void
  294 ucom_shutdown(struct ucom_softc *sc)
  295 {
  296         struct tty *tp = sc->sc_tty;
  297 
  298         DPRINTF(("ucom_shutdown\n"));
  299         /*
  300          * Hang up if necessary.  Wait a bit, so the other side has time to
  301          * notice even if we immediately open the port again.
  302          */
  303         if (ISSET(tp->t_cflag, HUPCL)) {
  304                 ucom_dtr(sc, 0);
  305                 (void)tsleep(sc, TTIPRI, ttclos, hz);
  306         }
  307 }
  308 
  309 int
  310 ucomopen(dev_t dev, int flag, int mode, struct proc *p)
  311 {
  312         int unit = UCOMUNIT(dev);
  313         usbd_status err;
  314         struct ucom_softc *sc;
  315         struct tty *tp;
  316         struct termios t;
  317         int s;
  318         int error;
  319 
  320         if (unit >= ucom_cd.cd_ndevs)
  321                 return (ENXIO);
  322         sc = ucom_cd.cd_devs[unit];
  323         if (sc == NULL)
  324                 return (ENXIO);
  325 
  326         if (sc->sc_dying)
  327                 return (EIO);
  328 
  329         if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0)
  330                 return (ENXIO);
  331 
  332         /* open the pipes if this is the first open */
  333         ucom_lock(sc);
  334         if (sc->sc_open++ == 0) {
  335                 s = splusb();
  336 
  337                 DPRINTF(("ucomopen: open pipes in=%d out=%d\n",
  338                     sc->sc_bulkin_no, sc->sc_bulkout_no));
  339                 DPRINTF(("ucomopen: hid %p pipes in=%p out=%p\n",
  340                     sc->sc_uhidev, sc->sc_ipipe, sc->sc_opipe));
  341 
  342                 if (sc->sc_bulkin_no != -1) {
  343 
  344                         /* Open the bulk pipes */
  345                         err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0,
  346                             &sc->sc_bulkin_pipe);
  347                         if (err) {
  348                                 DPRINTF(("%s: open bulk out error (addr %d), err=%s\n",
  349                                     sc->sc_dev.dv_xname, sc->sc_bulkin_no,
  350                                     usbd_errstr(err)));
  351                                 error = EIO;
  352                                 goto fail_0;
  353                         }
  354                         err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
  355                             USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
  356                         if (err) {
  357                                 DPRINTF(("%s: open bulk in error (addr %d), err=%s\n",
  358                                     sc->sc_dev.dv_xname, sc->sc_bulkout_no,
  359                                     usbd_errstr(err)));
  360                                 error = EIO;
  361                                 goto fail_1;
  362                         }
  363 
  364                         /* Allocate a request and an input buffer and start reading. */
  365                         sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev);
  366                         if (sc->sc_ixfer == NULL) {
  367                                 error = ENOMEM;
  368                                 goto fail_2;
  369                         }
  370 
  371                         sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer,
  372                             sc->sc_ibufsizepad);
  373                         if (sc->sc_ibuf == NULL) {
  374                                 error = ENOMEM;
  375                                 goto fail_2;
  376                         }
  377 
  378                         sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev);
  379                         if (sc->sc_oxfer == NULL) {
  380                                 error = ENOMEM;
  381                                 goto fail_3;
  382                         }
  383                 } else {
  384                         /*
  385                          * input/output pipes and xfers already allocated
  386                          * as is the input buffer.
  387                          */
  388                         sc->sc_ipipe = sc->sc_uhidev->sc_ipipe;
  389                         sc->sc_ixfer = sc->sc_uhidev->sc_ixfer;
  390                         sc->sc_opipe = sc->sc_uhidev->sc_opipe;
  391                         sc->sc_oxfer = sc->sc_uhidev->sc_oxfer;
  392                 }
  393 
  394                 sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer,
  395                     sc->sc_obufsize + sc->sc_opkthdrlen);
  396                 if (sc->sc_obuf == NULL) {
  397                         error = ENOMEM;
  398                         goto fail_4;
  399                 }
  400 
  401                 if (sc->sc_methods->ucom_open != NULL) {
  402                         error = sc->sc_methods->ucom_open(sc->sc_parent,
  403                             sc->sc_portno);
  404                         if (error) {
  405                                 ucom_cleanup(sc);
  406                                 splx(s);
  407                                 ucom_unlock(sc);
  408                                 return (error);
  409                         }
  410                 }
  411 
  412                 ucom_status_change(sc);
  413 
  414                 ucomstartread(sc);
  415 
  416                 splx(s);
  417         }
  418         ucom_unlock(sc);
  419 
  420         s = spltty();
  421         tp = sc->sc_tty;
  422         splx(s);
  423 
  424         DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp));
  425 
  426         tp->t_dev = dev;
  427         if (!ISSET(tp->t_state, TS_ISOPEN)) {
  428                 SET(tp->t_state, TS_WOPEN);
  429                 ttychars(tp);
  430 
  431                 /*
  432                  * Initialize the termios status to the defaults.  Add in the
  433                  * sticky bits from TIOCSFLAGS.
  434                  */
  435                 t.c_ispeed = 0;
  436                 t.c_ospeed = TTYDEF_SPEED;
  437                 t.c_cflag = TTYDEF_CFLAG;
  438                 if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
  439                         SET(t.c_cflag, CLOCAL);
  440                 if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
  441                         SET(t.c_cflag, CRTSCTS);
  442                 if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
  443                         SET(t.c_cflag, MDMBUF);
  444 
  445                 /* Make sure ucomparam() will do something. */
  446                 tp->t_ospeed = 0;
  447                 (void) ucomparam(tp, &t);
  448                 tp->t_iflag = TTYDEF_IFLAG;
  449                 tp->t_oflag = TTYDEF_OFLAG;
  450                 tp->t_lflag = TTYDEF_LFLAG;
  451 
  452                 s = spltty();
  453                 ttsetwater(tp);
  454 
  455                 /*
  456                  * Turn on DTR.  We must always do this, even if carrier is not
  457                  * present, because otherwise we'd have to use TIOCSDTR
  458                  * immediately after setting CLOCAL, which applications do not
  459                  * expect.  We always assert DTR while the device is open
  460                  * unless explicitly requested to deassert it.
  461                  */
  462                 ucom_dtr(sc, 1);
  463 
  464                 /* XXX CLR(sc->sc_rx_flags, RX_ANY_BLOCK);*/
  465                 ucom_hwiflow(sc);
  466 
  467                 if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || UCOMCUA(dev) ||
  468                     ISSET(sc->sc_msr, UMSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
  469                         SET(tp->t_state, TS_CARR_ON);
  470                 else
  471                         CLR(tp->t_state, TS_CARR_ON);
  472         } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) {
  473                 error = EBUSY;
  474                 goto bad;
  475         } else
  476                 s = spltty();
  477 
  478         if (UCOMCUA(dev)) {
  479                 if (ISSET(tp->t_state, TS_ISOPEN)) {
  480                         /* Someone is already dialed in */
  481                         error = EBUSY;
  482                         goto bad1;
  483                 }
  484                 sc->sc_cua = 1;
  485         } else {
  486                 /* tty (not cua) device, wait for carrier */
  487                 if (ISSET(flag, O_NONBLOCK)) {
  488                         if (sc->sc_cua) {
  489                                 error = EBUSY;
  490                                 goto bad1;
  491                         }
  492                 } else {
  493                         while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) &&
  494                             !ISSET(tp->t_state, TS_CARR_ON))) {
  495                                 SET(tp->t_state, TS_WOPEN);
  496                                 error = ttysleep(tp, &tp->t_rawq,
  497                                     TTIPRI | PCATCH, ttopen, 0);
  498                                 /*
  499                                  * If TS_WOPEN has been reset, that means the
  500                                  * cua device has been closed.  We don't want
  501                                  * to fail in that case, so just go around
  502                                  * again.
  503                                  */
  504                                 if (error && ISSET(tp->t_state, TS_WOPEN)) {
  505                                         CLR(tp->t_state, TS_WOPEN);
  506                                         goto bad1;
  507                                 }
  508                         }
  509                 }
  510         }
  511         splx(s);
  512 
  513         error = ttyopen(UCOMUNIT(dev), tp);
  514         if (error)
  515                 goto bad;
  516 
  517         error = (*LINESW(tp, l_open))(dev, tp);
  518         if (error)
  519                 goto bad;
  520 
  521         return (0);
  522 
  523 fail_4:
  524         if (sc->sc_uhidev == NULL)
  525                 usbd_free_xfer(sc->sc_oxfer);
  526         sc->sc_oxfer = NULL;
  527 fail_3:
  528         usbd_free_xfer(sc->sc_ixfer);
  529         sc->sc_ixfer = NULL;
  530 fail_2:
  531         usbd_close_pipe(sc->sc_bulkout_pipe);
  532         sc->sc_bulkout_pipe = NULL;
  533 fail_1:
  534         usbd_close_pipe(sc->sc_bulkin_pipe);
  535         sc->sc_bulkin_pipe = NULL;
  536 fail_0:
  537         splx(s);
  538         ucom_unlock(sc);
  539         return (error);
  540 
  541 bad1:
  542         splx(s);
  543 bad:
  544         ucom_lock(sc);
  545         ucom_cleanup(sc);
  546         ucom_unlock(sc);
  547 
  548         return (error);
  549 }
  550 
  551 int
  552 ucomclose(dev_t dev, int flag, int mode, struct proc *p)
  553 {
  554         struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
  555         struct tty *tp = sc->sc_tty;
  556         int s;
  557 
  558         if (!ISSET(tp->t_state, TS_ISOPEN))
  559                 return (0);
  560 
  561         DPRINTF(("ucomclose: unit=%d\n", UCOMUNIT(dev)));
  562         ucom_lock(sc);
  563 
  564         (*LINESW(tp, l_close))(tp, flag);
  565         s = spltty();
  566         CLR(tp->t_state, TS_BUSY | TS_FLUSH);
  567         sc->sc_cua = 0;
  568         ttyclose(tp);
  569         ucom_cleanup(sc);
  570         splx(s);
  571 
  572         if (sc->sc_methods->ucom_close != NULL)
  573                 sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno);
  574 
  575         ucom_unlock(sc);
  576 
  577         return (0);
  578 }
  579 
  580 int
  581 ucomread(dev_t dev, struct uio *uio, int flag)
  582 {
  583         struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
  584         struct tty *tp = sc->sc_tty;
  585         int error;
  586 
  587         if (sc->sc_dying)
  588                 return (EIO);
  589 
  590         sc->sc_refcnt++;
  591         error = (*LINESW(tp, l_read))(tp, uio, flag);
  592         if (--sc->sc_refcnt < 0)
  593                 usb_detach_wakeup(&sc->sc_dev);
  594         return (error);
  595 }
  596 
  597 int
  598 ucomwrite(dev_t dev, struct uio *uio, int flag)
  599 {
  600         struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
  601         struct tty *tp = sc->sc_tty;
  602         int error;
  603 
  604         if (sc->sc_dying)
  605                 return (EIO);
  606 
  607         sc->sc_refcnt++;
  608         error = (*LINESW(tp, l_write))(tp, uio, flag);
  609         if (--sc->sc_refcnt < 0)
  610                 usb_detach_wakeup(&sc->sc_dev);
  611         return (error);
  612 }
  613 
  614 struct tty *
  615 ucomtty(dev_t dev)
  616 {
  617         struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
  618         struct tty *tp = sc->sc_tty;
  619 
  620         return (tp);
  621 }
  622 
  623 int
  624 ucomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  625 {
  626         struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)];
  627         int error;
  628 
  629         sc->sc_refcnt++;
  630         error = ucom_do_ioctl(sc, cmd, data, flag, p);
  631         if (--sc->sc_refcnt < 0)
  632                 usb_detach_wakeup(&sc->sc_dev);
  633         return (error);
  634 }
  635 
  636 int
  637 ucom_do_ioctl(struct ucom_softc *sc, u_long cmd, caddr_t data,
  638               int flag, struct proc *p)
  639 {
  640         struct tty *tp = sc->sc_tty;
  641         int error;
  642         int s;
  643 
  644         if (sc->sc_dying)
  645                 return (EIO);
  646 
  647         DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd));
  648 
  649         error = (*LINESW(tp, l_ioctl))(tp, cmd, data, flag, p);
  650         if (error >= 0)
  651                 return (error);
  652 
  653         error = ttioctl(tp, cmd, data, flag, p);
  654         if (error >= 0)
  655                 return (error);
  656 
  657         if (sc->sc_methods->ucom_ioctl != NULL) {
  658                 error = sc->sc_methods->ucom_ioctl(sc->sc_parent,
  659                             sc->sc_portno, cmd, data, flag, p);
  660                 if (error >= 0)
  661                         return (error);
  662         }
  663 
  664         error = 0;
  665 
  666         DPRINTF(("ucomioctl: our cmd=0x%08lx\n", cmd));
  667         s = spltty();
  668 
  669         switch (cmd) {
  670         case TIOCSBRK:
  671                 ucom_break(sc, 1);
  672                 break;
  673 
  674         case TIOCCBRK:
  675                 ucom_break(sc, 0);
  676                 break;
  677 
  678         case TIOCSDTR:
  679                 ucom_dtr(sc, 1);
  680                 break;
  681 
  682         case TIOCCDTR:
  683                 ucom_dtr(sc, 0);
  684                 break;
  685 
  686         case TIOCGFLAGS:
  687                 *(int *)data = sc->sc_swflags;
  688                 break;
  689 
  690         case TIOCSFLAGS:
  691                 error = suser(p, 0);
  692                 if (error)
  693                         break;
  694                 sc->sc_swflags = *(int *)data;
  695                 break;
  696 
  697         case TIOCMSET:
  698         case TIOCMBIS:
  699         case TIOCMBIC:
  700                 tiocm_to_ucom(sc, cmd, *(int *)data);
  701                 break;
  702 
  703         case TIOCMGET:
  704                 *(int *)data = ucom_to_tiocm(sc);
  705                 break;
  706 
  707         default:
  708                 error = ENOTTY;
  709                 break;
  710         }
  711 
  712         splx(s);
  713 
  714         return (error);
  715 }
  716 
  717 void
  718 tiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits)
  719 {
  720         u_char combits;
  721 
  722         combits = 0;
  723         if (ISSET(ttybits, TIOCM_DTR))
  724                 SET(combits, UMCR_DTR);
  725         if (ISSET(ttybits, TIOCM_RTS))
  726                 SET(combits, UMCR_RTS);
  727 
  728         switch (how) {
  729         case TIOCMBIC:
  730                 CLR(sc->sc_mcr, combits);
  731                 break;
  732 
  733         case TIOCMBIS:
  734                 SET(sc->sc_mcr, combits);
  735                 break;
  736 
  737         case TIOCMSET:
  738                 CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS);
  739                 SET(sc->sc_mcr, combits);
  740                 break;
  741         }
  742 
  743         if (how == TIOCMSET || ISSET(combits, UMCR_DTR))
  744                 ucom_dtr(sc, (sc->sc_mcr & UMCR_DTR) != 0);
  745         if (how == TIOCMSET || ISSET(combits, UMCR_RTS))
  746                 ucom_rts(sc, (sc->sc_mcr & UMCR_RTS) != 0);
  747 }
  748 
  749 int
  750 ucom_to_tiocm(struct ucom_softc *sc)
  751 {
  752         u_char combits;
  753         int ttybits = 0;
  754 
  755         combits = sc->sc_mcr;
  756         if (ISSET(combits, UMCR_DTR))
  757                 SET(ttybits, TIOCM_DTR);
  758         if (ISSET(combits, UMCR_RTS))
  759                 SET(ttybits, TIOCM_RTS);
  760 
  761         combits = sc->sc_msr;
  762         if (ISSET(combits, UMSR_DCD))
  763                 SET(ttybits, TIOCM_CD);
  764         if (ISSET(combits, UMSR_CTS))
  765                 SET(ttybits, TIOCM_CTS);
  766         if (ISSET(combits, UMSR_DSR))
  767                 SET(ttybits, TIOCM_DSR);
  768         if (ISSET(combits, UMSR_RI | UMSR_TERI))
  769                 SET(ttybits, TIOCM_RI);
  770 
  771 #if 0
  772 XXX;
  773         if (sc->sc_ier != 0)
  774                 SET(ttybits, TIOCM_LE);
  775 #endif
  776 
  777         return (ttybits);
  778 }
  779 
  780 void
  781 ucom_break(sc, onoff)
  782         struct ucom_softc *sc;
  783         int onoff;
  784 {
  785         DPRINTF(("ucom_break: onoff=%d\n", onoff));
  786 
  787         if (sc->sc_methods->ucom_set != NULL)
  788                 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
  789                     UCOM_SET_BREAK, onoff);
  790 }
  791 
  792 void
  793 ucom_dtr(struct ucom_softc *sc, int onoff)
  794 {
  795         DPRINTF(("ucom_dtr: onoff=%d\n", onoff));
  796 
  797         if (sc->sc_methods->ucom_set != NULL) {
  798                 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
  799                     UCOM_SET_DTR, onoff);
  800                 /* When not using CRTSCTS, RTS follows DTR. */
  801                 if (!(sc->sc_swflags & TIOCFLAG_CRTSCTS))
  802                         ucom_rts(sc, onoff);
  803         }
  804 }
  805 
  806 void
  807 ucom_rts(struct ucom_softc *sc, int onoff)
  808 {
  809         DPRINTF(("ucom_rts: onoff=%d\n", onoff));
  810 
  811         if (sc->sc_methods->ucom_set != NULL)
  812                 sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno,
  813                     UCOM_SET_RTS, onoff);
  814 }
  815 
  816 void
  817 ucom_status_change(struct ucom_softc *sc)
  818 {
  819         struct tty *tp = sc->sc_tty;
  820         u_char old_msr;
  821 
  822         if (sc->sc_methods->ucom_get_status != NULL) {
  823                 old_msr = sc->sc_msr;
  824                 sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno,
  825                     &sc->sc_lsr, &sc->sc_msr);
  826 
  827                 ttytstamp(tp, old_msr & UMSR_CTS, sc->sc_msr & UMSR_CTS,
  828                     old_msr & UMSR_DCD, sc->sc_msr & UMSR_DCD);
  829 
  830                 if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD))
  831                         (*LINESW(tp, l_modem))(tp,
  832                             ISSET(sc->sc_msr, UMSR_DCD));
  833         } else {
  834                 sc->sc_lsr = 0;
  835                 sc->sc_msr = 0;
  836         }
  837 }
  838 
  839 int
  840 ucomparam(struct tty *tp, struct termios *t)
  841 {
  842         struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];
  843         int error;
  844 
  845         if (sc->sc_dying)
  846                 return (EIO);
  847 
  848         /* Check requested parameters. */
  849         if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
  850                 return (EINVAL);
  851 
  852         /*
  853          * For the console, always force CLOCAL and !HUPCL, so that the port
  854          * is always active.
  855          */
  856         if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) {
  857                 SET(t->c_cflag, CLOCAL);
  858                 CLR(t->c_cflag, HUPCL);
  859         }
  860 
  861         /*
  862          * If there were no changes, don't do anything.  This avoids dropping
  863          * input and improves performance when all we did was frob things like
  864          * VMIN and VTIME.
  865          */
  866         if (tp->t_ospeed == t->c_ospeed &&
  867             tp->t_cflag == t->c_cflag)
  868                 return (0);
  869 
  870         /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */
  871 
  872         /* And copy to tty. */
  873         tp->t_ispeed = 0;
  874         tp->t_ospeed = t->c_ospeed;
  875         tp->t_cflag = t->c_cflag;
  876 
  877         if (sc->sc_methods->ucom_param != NULL) {
  878                 error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno,
  879                             t);
  880                 if (error)
  881                         return (error);
  882         }
  883 
  884         /* XXX worry about CHWFLOW */
  885 
  886         /*
  887          * Update the tty layer's idea of the carrier bit, in case we changed
  888          * CLOCAL or MDMBUF.  We don't hang up here; we only do that by
  889          * explicit request.
  890          */
  891         DPRINTF(("ucomparam: l_modem\n"));
  892         (void) (*LINESW(tp, l_modem))(tp, 1 /* XXX carrier */ );
  893 
  894 #if 0
  895 XXX what if the hardware is not open
  896         if (!ISSET(t->c_cflag, CHWFLOW)) {
  897                 if (sc->sc_tx_stopped) {
  898                         sc->sc_tx_stopped = 0;
  899                         ucomstart(tp);
  900                 }
  901         }
  902 #endif
  903 
  904         return (0);
  905 }
  906 
  907 /*
  908  * (un)block input via hw flowcontrol
  909  */
  910 void
  911 ucom_hwiflow(struct ucom_softc *sc)
  912 {
  913         DPRINTF(("ucom_hwiflow:\n"));
  914 #if 0
  915 XXX
  916         bus_space_tag_t iot = sc->sc_iot;
  917         bus_space_handle_t ioh = sc->sc_ioh;
  918 
  919         if (sc->sc_mcr_rts == 0)
  920                 return;
  921 
  922         if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) {
  923                 CLR(sc->sc_mcr, sc->sc_mcr_rts);
  924                 CLR(sc->sc_mcr_active, sc->sc_mcr_rts);
  925         } else {
  926                 SET(sc->sc_mcr, sc->sc_mcr_rts);
  927                 SET(sc->sc_mcr_active, sc->sc_mcr_rts);
  928         }
  929         bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active);
  930 #endif
  931 }
  932 
  933 void
  934 ucomstart(struct tty *tp)
  935 {
  936         struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];
  937         usbd_status err;
  938         int s;
  939         u_char *data;
  940         int cnt;
  941 
  942         if (sc->sc_dying)
  943                 return;
  944 
  945         s = spltty();
  946         if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) {
  947                 DPRINTFN(4,("ucomstart: no go, state=0x%x\n", tp->t_state));
  948                 goto out;
  949         }
  950         if (sc->sc_tx_stopped)
  951                 goto out;
  952 
  953         if (tp->t_outq.c_cc <= tp->t_lowat) {
  954                 if (ISSET(tp->t_state, TS_ASLEEP)) {
  955                         CLR(tp->t_state, TS_ASLEEP);
  956                         wakeup(&tp->t_outq);
  957                 }
  958                 selwakeup(&tp->t_wsel);
  959                 if (tp->t_outq.c_cc == 0)
  960                         goto out;
  961         }
  962 
  963         /* Grab the first contiguous region of buffer space. */
  964         data = tp->t_outq.c_cf;
  965         cnt = ndqb(&tp->t_outq, 0);
  966 
  967         if (cnt == 0) {
  968                 DPRINTF(("ucomstart: cnt==0\n"));
  969                 goto out;
  970         }
  971 
  972         SET(tp->t_state, TS_BUSY);
  973 
  974         if (cnt > sc->sc_obufsize) {
  975                 DPRINTF(("ucomstart: big buffer %d chars\n", cnt));
  976                 cnt = sc->sc_obufsize;
  977         }
  978         if (sc->sc_methods->ucom_write != NULL)
  979                 sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno,
  980                                            sc->sc_obuf, data, &cnt);
  981         else
  982                 memcpy(sc->sc_obuf, data, cnt);
  983 
  984         DPRINTFN(4,("ucomstart: %d chars\n", cnt));
  985 #ifdef DIAGNOSTIC
  986         if (sc->sc_oxfer == NULL) {
  987                 printf("ucomstart: null oxfer\n");
  988                 goto out;
  989         }
  990 #endif
  991         if (sc->sc_bulkout_pipe != NULL) {
  992                 usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe,
  993                     (usbd_private_handle)sc, sc->sc_obuf, cnt,
  994                     USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb);
  995         } else {
  996                 usbd_setup_xfer(sc->sc_oxfer, sc->sc_opipe,
  997                     (usbd_private_handle)sc, sc->sc_obuf, cnt,
  998                     USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb);
  999         }
 1000         /* What can we do on error? */
 1001         err = usbd_transfer(sc->sc_oxfer);
 1002 #ifdef DIAGNOSTIC
 1003         if (err != USBD_IN_PROGRESS)
 1004                 printf("ucomstart: err=%s\n", usbd_errstr(err));
 1005 #endif
 1006 
 1007 out:
 1008         splx(s);
 1009 }
 1010 
 1011 int
 1012 ucomstop(struct tty *tp, int flag)
 1013 {
 1014         DPRINTF(("ucomstop: flag=%d\n", flag));
 1015 #if 0
 1016         /*struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];*/
 1017         int s;
 1018 
 1019         s = spltty();
 1020         if (ISSET(tp->t_state, TS_BUSY)) {
 1021                 DPRINTF(("ucomstop: XXX\n"));
 1022                 /* sc->sc_tx_stopped = 1; */
 1023                 if (!ISSET(tp->t_state, TS_TTSTOP))
 1024                         SET(tp->t_state, TS_FLUSH);
 1025         }
 1026         splx(s);
 1027 #endif
 1028         return (0);
 1029 }
 1030 
 1031 void
 1032 ucomwritecb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
 1033 {
 1034         struct ucom_softc *sc = (struct ucom_softc *)p;
 1035         struct tty *tp = sc->sc_tty;
 1036         u_int32_t cc;
 1037         int s;
 1038 
 1039         DPRINTFN(5,("ucomwritecb: %p %p status=%d\n", xfer, p, status));
 1040 
 1041         if (status == USBD_CANCELLED || sc->sc_dying)
 1042                 goto error;
 1043 
 1044         if (sc->sc_bulkin_pipe != NULL) {
 1045                 if (status) {
 1046                         usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
 1047                         /* XXX we should restart after some delay. */
 1048                         goto error;
 1049                 }
 1050                 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
 1051         } else {
 1052                 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
 1053                 // XXX above gives me wrong cc, no?
 1054         }
 1055 
 1056         DPRINTFN(5,("ucomwritecb: cc=%d\n", cc));
 1057         /* convert from USB bytes to tty bytes */
 1058         cc -= sc->sc_opkthdrlen;
 1059 
 1060         s = spltty();
 1061         CLR(tp->t_state, TS_BUSY);
 1062         if (ISSET(tp->t_state, TS_FLUSH))
 1063                 CLR(tp->t_state, TS_FLUSH);
 1064         else
 1065                 ndflush(&tp->t_outq, cc);
 1066         (*LINESW(tp, l_start))(tp);
 1067         splx(s);
 1068         return;
 1069 
 1070 error:
 1071         s = spltty();
 1072         CLR(tp->t_state, TS_BUSY);
 1073         splx(s);
 1074 }
 1075 
 1076 usbd_status
 1077 ucomstartread(struct ucom_softc *sc)
 1078 {
 1079         usbd_status err;
 1080 
 1081         DPRINTFN(5,("ucomstartread: start\n"));
 1082 #ifdef DIAGNOSTIC
 1083         if (sc->sc_ixfer == NULL) {
 1084                 DPRINTF(("ucomstartread: null ixfer\n"));
 1085                 return (USBD_INVAL);
 1086         }
 1087 #endif
 1088 
 1089         if (sc->sc_bulkin_pipe != NULL) {
 1090                 usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe,
 1091                         (usbd_private_handle)sc,
 1092                         sc->sc_ibuf, sc->sc_ibufsize,
 1093                         USBD_SHORT_XFER_OK | USBD_NO_COPY,
 1094                         USBD_NO_TIMEOUT, ucomreadcb);
 1095                 err = usbd_transfer(sc->sc_ixfer);
 1096                 if (err != USBD_IN_PROGRESS) {
 1097                         DPRINTF(("ucomstartread: err=%s\n", usbd_errstr(err)));
 1098                         return (err);
 1099                 }
 1100         }
 1101 
 1102         return (USBD_NORMAL_COMPLETION);
 1103 }
 1104 
 1105 void
 1106 ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
 1107 {
 1108         struct ucom_softc *sc = (struct ucom_softc *)p;
 1109         struct tty *tp = sc->sc_tty;
 1110         int (*rint)(int c, struct tty *tp) = LINESW(tp, l_rint);
 1111         usbd_status err;
 1112         u_int32_t cc;
 1113         u_char *cp;
 1114         int s;
 1115 
 1116         DPRINTFN(5,("ucomreadcb: status=%d\n", status));
 1117 
 1118         if (status == USBD_CANCELLED || status == USBD_IOERROR ||
 1119             sc->sc_dying) {
 1120                 DPRINTF(("ucomreadcb: dying\n"));
 1121                 /* Send something to wake upper layer */
 1122                 s = spltty();
 1123                 (*rint)('\n', tp);
 1124                 ttwakeup(tp);
 1125                 splx(s);
 1126                 return;
 1127         }
 1128 
 1129         if (status) {
 1130                 if (sc->sc_bulkin_pipe != NULL) {
 1131                         usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
 1132                         /* XXX we should restart after some delay. */
 1133                         return;
 1134                 }
 1135         }
 1136 
 1137         usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL);
 1138         DPRINTFN(5,("ucomreadcb: got %d chars, tp=%p\n", cc, tp));
 1139         if (sc->sc_methods->ucom_read != NULL)
 1140                 sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno,
 1141                                           &cp, &cc);
 1142 
 1143         s = spltty();
 1144         /* Give characters to tty layer. */
 1145         while (cc-- > 0) {
 1146                 DPRINTFN(7,("ucomreadcb: char=0x%02x\n", *cp));
 1147                 if ((*rint)(*cp++, tp) == -1) {
 1148                         /* XXX what should we do? */
 1149                         printf("%s: lost %d chars\n", sc->sc_dev.dv_xname,
 1150                                cc);
 1151                         break;
 1152                 }
 1153         }
 1154         splx(s);
 1155 
 1156         err = ucomstartread(sc);
 1157         if (err) {
 1158                 printf("%s: read start failed\n", sc->sc_dev.dv_xname);
 1159                 /* XXX what should we dow now? */
 1160         }
 1161 }
 1162 
 1163 void
 1164 ucom_cleanup(struct ucom_softc *sc)
 1165 {
 1166         if (--sc->sc_open == 0) {
 1167                 DPRINTF(("ucom_cleanup: closing pipes\n"));
 1168 
 1169                 ucom_shutdown(sc);
 1170                 if (sc->sc_bulkin_pipe != NULL) {
 1171                         usbd_abort_pipe(sc->sc_bulkin_pipe);
 1172                         usbd_close_pipe(sc->sc_bulkin_pipe);
 1173                         sc->sc_bulkin_pipe = NULL;
 1174                 }
 1175                 if (sc->sc_bulkout_pipe != NULL) {
 1176                         usbd_abort_pipe(sc->sc_bulkout_pipe);
 1177                         usbd_close_pipe(sc->sc_bulkout_pipe);
 1178                         sc->sc_bulkout_pipe = NULL;
 1179                 }
 1180                 if (sc->sc_ixfer != NULL) {
 1181                         if (sc->sc_uhidev == NULL)
 1182                                 usbd_free_xfer(sc->sc_ixfer);
 1183                         sc->sc_ixfer = NULL;
 1184                 }
 1185                 if (sc->sc_oxfer != NULL) {
 1186                         usbd_free_buffer(sc->sc_oxfer);
 1187                         if (sc->sc_uhidev == NULL)
 1188                                 usbd_free_xfer(sc->sc_oxfer);
 1189                         sc->sc_oxfer = NULL;
 1190                 }
 1191         }
 1192 }
 1193 
 1194 #endif /* NUCOM > 0 */
 1195 
 1196 int
 1197 ucomprint(void *aux, const char *pnp)
 1198 {
 1199         struct ucom_attach_args *uca = aux;
 1200 
 1201         if (pnp)
 1202                 printf("ucom at %s", pnp);
 1203         if (uca->portno != UCOM_UNK_PORTNO)
 1204                 printf(" portno %d", uca->portno);
 1205         return (UNCONF);
 1206 }
 1207 
 1208 int
 1209 ucomsubmatch(struct device *parent, void *match, void *aux)
 1210 {
 1211         struct ucom_attach_args *uca = aux;
 1212         struct cfdata *cf = match;
 1213 
 1214         if (uca->portno != UCOM_UNK_PORTNO &&
 1215             cf->ucomcf_portno != UCOM_UNK_PORTNO &&
 1216             cf->ucomcf_portno != uca->portno)
 1217                 return (0);
 1218         return ((*cf->cf_attach->ca_match)(parent, cf, aux));
 1219 }

/* [<][>][^][v][top][bottom][index][help] */