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