ucom.c revision 1.69.10.2
11.69.10.1Sitohy/* $NetBSD: ucom.c,v 1.69.10.2 2007/06/16 04:12:30 itohy Exp $ */ 21.1Saugustss 31.1Saugustss/* 41.22Saugustss * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. 51.1Saugustss * All rights reserved. 61.1Saugustss * 71.1Saugustss * This code is derived from software contributed to The NetBSD Foundation 81.23Saugustss * by Lennart Augustsson (lennart@augustsson.net) at 91.1Saugustss * Carlstedt Research & Technology. 101.1Saugustss * 111.1Saugustss * Redistribution and use in source and binary forms, with or without 121.1Saugustss * modification, are permitted provided that the following conditions 131.1Saugustss * are met: 141.1Saugustss * 1. Redistributions of source code must retain the above copyright 151.1Saugustss * notice, this list of conditions and the following disclaimer. 161.1Saugustss * 2. Redistributions in binary form must reproduce the above copyright 171.1Saugustss * notice, this list of conditions and the following disclaimer in the 181.1Saugustss * documentation and/or other materials provided with the distribution. 191.1Saugustss * 3. All advertising materials mentioning features or use of this software 201.1Saugustss * must display the following acknowledgement: 211.1Saugustss * This product includes software developed by the NetBSD 221.1Saugustss * Foundation, Inc. and its contributors. 231.1Saugustss * 4. Neither the name of The NetBSD Foundation nor the names of its 241.1Saugustss * contributors may be used to endorse or promote products derived 251.1Saugustss * from this software without specific prior written permission. 261.1Saugustss * 271.1Saugustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 281.1Saugustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 291.1Saugustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 301.1Saugustss * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 311.1Saugustss * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 321.1Saugustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 331.1Saugustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 341.1Saugustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 351.1Saugustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 361.1Saugustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 371.1Saugustss * POSSIBILITY OF SUCH DAMAGE. 381.1Saugustss */ 391.22Saugustss/* 401.22Saugustss * This code is very heavily based on the 16550 driver, com.c. 411.22Saugustss */ 421.40Slukem 431.40Slukem#include <sys/cdefs.h> 441.69.10.1Sitohy__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.69.10.2 2007/06/16 04:12:30 itohy Exp $"); 451.1Saugustss 461.1Saugustss#include <sys/param.h> 471.1Saugustss#include <sys/systm.h> 481.1Saugustss#include <sys/kernel.h> 491.1Saugustss#include <sys/ioctl.h> 501.3Saugustss#include <sys/conf.h> 511.1Saugustss#include <sys/tty.h> 521.1Saugustss#include <sys/file.h> 531.1Saugustss#include <sys/select.h> 541.1Saugustss#include <sys/proc.h> 551.1Saugustss#include <sys/vnode.h> 561.12Saugustss#include <sys/device.h> 571.1Saugustss#include <sys/poll.h> 581.63Selad#include <sys/kauth.h> 591.31Sexplorer#if defined(__NetBSD__) 601.31Sexplorer#include "rnd.h" 611.31Sexplorer#if NRND > 0 621.31Sexplorer#include <sys/rnd.h> 631.31Sexplorer#endif 641.31Sexplorer#endif 651.1Saugustss 661.1Saugustss#include <dev/usb/usb.h> 671.1Saugustss 681.1Saugustss#include <dev/usb/usbdi.h> 691.1Saugustss#include <dev/usb/usbdi_util.h> 701.1Saugustss#include <dev/usb/usbdevs.h> 711.1Saugustss#include <dev/usb/usb_quirks.h> 721.1Saugustss 731.12Saugustss#include <dev/usb/ucomvar.h> 741.12Saugustss 751.13Saugustss#include "ucom.h" 761.13Saugustss 771.53Sdrochner#include "locators.h" 781.53Sdrochner 791.13Saugustss#if NUCOM > 0 801.13Saugustss 811.12Saugustss#ifdef UCOM_DEBUG 821.12Saugustss#define DPRINTFN(n, x) if (ucomdebug > (n)) logprintf x 831.12Saugustssint ucomdebug = 0; 841.1Saugustss#else 851.12Saugustss#define DPRINTFN(n, x) 861.1Saugustss#endif 871.12Saugustss#define DPRINTF(x) DPRINTFN(0, x) 881.12Saugustss 891.12Saugustss#define UCOMUNIT_MASK 0x3ffff 901.12Saugustss#define UCOMDIALOUT_MASK 0x80000 911.12Saugustss#define UCOMCALLUNIT_MASK 0x40000 921.12Saugustss 931.12Saugustss#define UCOMUNIT(x) (minor(x) & UCOMUNIT_MASK) 941.12Saugustss#define UCOMDIALOUT(x) (minor(x) & UCOMDIALOUT_MASK) 951.12Saugustss#define UCOMCALLUNIT(x) (minor(x) & UCOMCALLUNIT_MASK) 961.12Saugustss 971.1Saugustssstruct ucom_softc { 981.12Saugustss USBBASEDEVICE sc_dev; /* base device */ 991.12Saugustss 1001.12Saugustss usbd_device_handle sc_udev; /* USB device */ 1011.12Saugustss 1021.12Saugustss usbd_interface_handle sc_iface; /* data interface */ 1031.12Saugustss 1041.12Saugustss int sc_bulkin_no; /* bulk in endpoint address */ 1051.12Saugustss usbd_pipe_handle sc_bulkin_pipe; /* bulk in pipe */ 1061.12Saugustss usbd_xfer_handle sc_ixfer; /* read request */ 1071.12Saugustss u_char *sc_ibuf; /* read buffer */ 1081.19Saugustss u_int sc_ibufsize; /* read buffer size */ 1091.22Saugustss u_int sc_ibufsizepad; /* read buffer size padded */ 1101.12Saugustss 1111.12Saugustss int sc_bulkout_no; /* bulk out endpoint address */ 1121.12Saugustss usbd_pipe_handle sc_bulkout_pipe;/* bulk out pipe */ 1131.12Saugustss usbd_xfer_handle sc_oxfer; /* write request */ 1141.12Saugustss u_char *sc_obuf; /* write buffer */ 1151.19Saugustss u_int sc_obufsize; /* write buffer size */ 1161.25Saugustss u_int sc_opkthdrlen; /* header length of 1171.25Saugustss * output packet */ 1181.12Saugustss 1191.12Saugustss struct ucom_methods *sc_methods; 1201.12Saugustss void *sc_parent; 1211.12Saugustss int sc_portno; 1221.12Saugustss 1231.12Saugustss struct tty *sc_tty; /* our tty */ 1241.12Saugustss u_char sc_lsr; 1251.12Saugustss u_char sc_msr; 1261.12Saugustss u_char sc_mcr; 1271.12Saugustss u_char sc_tx_stopped; 1281.12Saugustss int sc_swflags; 1291.12Saugustss 1301.12Saugustss u_char sc_opening; /* lock during open */ 1311.17Saugustss int sc_refcnt; 1321.12Saugustss u_char sc_dying; /* disconnecting */ 1331.31Sexplorer 1341.31Sexplorer#if defined(__NetBSD__) && NRND > 0 1351.31Sexplorer rndsource_element_t sc_rndsource; /* random source */ 1361.31Sexplorer#endif 1371.1Saugustss}; 1381.1Saugustss 1391.44Sgehennadev_type_open(ucomopen); 1401.44Sgehennadev_type_close(ucomclose); 1411.44Sgehennadev_type_read(ucomread); 1421.44Sgehennadev_type_write(ucomwrite); 1431.44Sgehennadev_type_ioctl(ucomioctl); 1441.44Sgehennadev_type_stop(ucomstop); 1451.44Sgehennadev_type_tty(ucomtty); 1461.44Sgehennadev_type_poll(ucompoll); 1471.44Sgehenna 1481.44Sgehennaconst struct cdevsw ucom_cdevsw = { 1491.44Sgehenna ucomopen, ucomclose, ucomread, ucomwrite, ucomioctl, 1501.47Sjdolecek ucomstop, ucomtty, ucompoll, nommap, ttykqfilter, D_TTY 1511.44Sgehenna}; 1521.12Saugustss 1531.24SaugustssStatic void ucom_cleanup(struct ucom_softc *); 1541.24SaugustssStatic void ucom_hwiflow(struct ucom_softc *); 1551.24SaugustssStatic int ucomparam(struct tty *, struct termios *); 1561.24SaugustssStatic void ucomstart(struct tty *); 1571.24SaugustssStatic void ucom_shutdown(struct ucom_softc *); 1581.24SaugustssStatic int ucom_do_ioctl(struct ucom_softc *, u_long, caddr_t, 1591.69.10.1Sitohy int, usb_proc_ptr); 1601.24SaugustssStatic void ucom_dtr(struct ucom_softc *, int); 1611.24SaugustssStatic void ucom_rts(struct ucom_softc *, int); 1621.24SaugustssStatic void ucom_break(struct ucom_softc *, int); 1631.24SaugustssStatic usbd_status ucomstartread(struct ucom_softc *); 1641.24SaugustssStatic void ucomreadcb(usbd_xfer_handle, usbd_private_handle, usbd_status); 1651.24SaugustssStatic void ucomwritecb(usbd_xfer_handle, usbd_private_handle, usbd_status); 1661.29StoshiiStatic void tiocm_to_ucom(struct ucom_softc *, u_long, int); 1671.24SaugustssStatic int ucom_to_tiocm(struct ucom_softc *); 1681.1Saugustss 1691.3SaugustssUSB_DECLARE_DRIVER(ucom); 1701.1Saugustss 1711.3SaugustssUSB_MATCH(ucom) 1721.1Saugustss{ 1731.12Saugustss return (1); 1741.1Saugustss} 1751.1Saugustss 1761.3SaugustssUSB_ATTACH(ucom) 1771.1Saugustss{ 1781.12Saugustss struct ucom_softc *sc = (struct ucom_softc *)self; 1791.12Saugustss struct ucom_attach_args *uca = aux; 1801.12Saugustss struct tty *tp; 1811.12Saugustss 1821.35Saugustss if (uca->info != NULL) 1831.59Sitohy printf(": %s", uca->info); 1841.12Saugustss printf("\n"); 1851.12Saugustss 1861.12Saugustss sc->sc_udev = uca->device; 1871.12Saugustss sc->sc_iface = uca->iface; 1881.12Saugustss sc->sc_bulkout_no = uca->bulkout; 1891.12Saugustss sc->sc_bulkin_no = uca->bulkin; 1901.19Saugustss sc->sc_ibufsize = uca->ibufsize; 1911.22Saugustss sc->sc_ibufsizepad = uca->ibufsizepad; 1921.19Saugustss sc->sc_obufsize = uca->obufsize; 1931.25Saugustss sc->sc_opkthdrlen = uca->opkthdrlen; 1941.12Saugustss sc->sc_methods = uca->methods; 1951.12Saugustss sc->sc_parent = uca->arg; 1961.12Saugustss sc->sc_portno = uca->portno; 1971.12Saugustss 1981.12Saugustss tp = ttymalloc(); 1991.12Saugustss tp->t_oproc = ucomstart; 2001.12Saugustss tp->t_param = ucomparam; 2011.12Saugustss sc->sc_tty = tp; 2021.12Saugustss 2031.12Saugustss DPRINTF(("ucom_attach: tty_attach %p\n", tp)); 2041.12Saugustss tty_attach(tp); 2051.12Saugustss 2061.31Sexplorer#if defined(__NetBSD__) && NRND > 0 2071.31Sexplorer rnd_attach_source(&sc->sc_rndsource, USBDEVNAME(sc->sc_dev), 2081.31Sexplorer RND_TYPE_TTY, 0); 2091.31Sexplorer#endif 2101.31Sexplorer 2111.12Saugustss USB_ATTACH_SUCCESS_RETURN; 2121.12Saugustss} 2131.12Saugustss 2141.12SaugustssUSB_DETACH(ucom) 2151.12Saugustss{ 2161.12Saugustss struct ucom_softc *sc = (struct ucom_softc *)self; 2171.36Saugustss struct tty *tp = sc->sc_tty; 2181.12Saugustss int maj, mn; 2191.17Saugustss int s; 2201.12Saugustss 2211.43Saugustss DPRINTF(("ucom_detach: sc=%p flags=%d tp=%p, pipe=%d,%d\n", 2221.36Saugustss sc, flags, tp, sc->sc_bulkin_no, sc->sc_bulkout_no)); 2231.12Saugustss 2241.12Saugustss sc->sc_dying = 1; 2251.12Saugustss 2261.33Saugustss if (sc->sc_bulkin_pipe != NULL) 2271.33Saugustss usbd_abort_pipe(sc->sc_bulkin_pipe); 2281.33Saugustss if (sc->sc_bulkout_pipe != NULL) 2291.33Saugustss usbd_abort_pipe(sc->sc_bulkout_pipe); 2301.12Saugustss 2311.17Saugustss s = splusb(); 2321.17Saugustss if (--sc->sc_refcnt >= 0) { 2331.35Saugustss /* Wake up anyone waiting */ 2341.36Saugustss if (tp != NULL) { 2351.36Saugustss CLR(tp->t_state, TS_CARR_ON); 2361.36Saugustss CLR(tp->t_cflag, CLOCAL | MDMBUF); 2371.36Saugustss ttyflush(tp, FREAD|FWRITE); 2381.36Saugustss } 2391.17Saugustss /* Wait for processes to go away. */ 2401.17Saugustss usb_detach_wait(USBDEV(sc->sc_dev)); 2411.17Saugustss } 2421.17Saugustss splx(s); 2431.12Saugustss 2441.12Saugustss /* locate the major number */ 2451.44Sgehenna maj = cdevsw_lookup_major(&ucom_cdevsw); 2461.12Saugustss 2471.12Saugustss /* Nuke the vnodes for any open instances. */ 2481.62Sthorpej mn = device_unit(self); 2491.17Saugustss DPRINTF(("ucom_detach: maj=%d mn=%d\n", maj, mn)); 2501.12Saugustss vdevgone(maj, mn, mn, VCHR); 2511.22Saugustss vdevgone(maj, mn | UCOMDIALOUT_MASK, mn | UCOMDIALOUT_MASK, VCHR); 2521.22Saugustss vdevgone(maj, mn | UCOMCALLUNIT_MASK, mn | UCOMCALLUNIT_MASK, VCHR); 2531.12Saugustss 2541.12Saugustss /* Detach and free the tty. */ 2551.36Saugustss if (tp != NULL) { 2561.36Saugustss tty_detach(tp); 2571.36Saugustss ttyfree(tp); 2581.33Saugustss sc->sc_tty = NULL; 2591.33Saugustss } 2601.12Saugustss 2611.31Sexplorer /* Detach the random source */ 2621.31Sexplorer#if defined(__NetBSD__) && NRND > 0 2631.31Sexplorer rnd_detach_source(&sc->sc_rndsource); 2641.31Sexplorer#endif 2651.31Sexplorer 2661.12Saugustss return (0); 2671.12Saugustss} 2681.12Saugustss 2691.12Saugustssint 2701.24Saugustssucom_activate(device_ptr_t self, enum devact act) 2711.12Saugustss{ 2721.12Saugustss struct ucom_softc *sc = (struct ucom_softc *)self; 2731.12Saugustss 2741.34Saugustss DPRINTFN(5,("ucom_activate: %d\n", act)); 2751.34Saugustss 2761.12Saugustss switch (act) { 2771.12Saugustss case DVACT_ACTIVATE: 2781.12Saugustss return (EOPNOTSUPP); 2791.12Saugustss 2801.12Saugustss case DVACT_DEACTIVATE: 2811.12Saugustss sc->sc_dying = 1; 2821.12Saugustss break; 2831.12Saugustss } 2841.12Saugustss return (0); 2851.12Saugustss} 2861.12Saugustss 2871.12Saugustssvoid 2881.24Saugustssucom_shutdown(struct ucom_softc *sc) 2891.12Saugustss{ 2901.12Saugustss struct tty *tp = sc->sc_tty; 2911.12Saugustss 2921.12Saugustss DPRINTF(("ucom_shutdown\n")); 2931.12Saugustss /* 2941.12Saugustss * Hang up if necessary. Wait a bit, so the other side has time to 2951.12Saugustss * notice even if we immediately open the port again. 2961.12Saugustss */ 2971.12Saugustss if (ISSET(tp->t_cflag, HUPCL)) { 2981.12Saugustss ucom_dtr(sc, 0); 2991.12Saugustss (void)tsleep(sc, TTIPRI, ttclos, hz); 3001.12Saugustss } 3011.12Saugustss} 3021.12Saugustss 3031.12Saugustssint 3041.69.10.1Sitohyucomopen(dev_t dev, int flag, int mode, usb_proc_ptr l) 3051.12Saugustss{ 3061.12Saugustss int unit = UCOMUNIT(dev); 3071.12Saugustss usbd_status err; 3081.12Saugustss struct ucom_softc *sc; 3091.12Saugustss struct tty *tp; 3101.12Saugustss int s; 3111.12Saugustss int error; 3121.43Saugustss 3131.12Saugustss if (unit >= ucom_cd.cd_ndevs) 3141.12Saugustss return (ENXIO); 3151.12Saugustss sc = ucom_cd.cd_devs[unit]; 3161.12Saugustss if (sc == NULL) 3171.12Saugustss return (ENXIO); 3181.12Saugustss 3191.12Saugustss if (sc->sc_dying) 3201.12Saugustss return (EIO); 3211.12Saugustss 3221.61Sthorpej if (!device_is_active(&sc->sc_dev)) 3231.12Saugustss return (ENXIO); 3241.12Saugustss 3251.12Saugustss tp = sc->sc_tty; 3261.12Saugustss 3271.12Saugustss DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp)); 3281.12Saugustss 3291.66Selad if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp)) 3301.12Saugustss return (EBUSY); 3311.12Saugustss 3321.12Saugustss s = spltty(); 3331.12Saugustss 3341.12Saugustss /* 3351.12Saugustss * Do the following iff this is a first open. 3361.12Saugustss */ 3371.12Saugustss while (sc->sc_opening) 3381.12Saugustss tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0); 3391.17Saugustss 3401.17Saugustss if (sc->sc_dying) { 3411.17Saugustss splx(s); 3421.17Saugustss return (EIO); 3431.17Saugustss } 3441.12Saugustss sc->sc_opening = 1; 3451.43Saugustss 3461.12Saugustss if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 3471.12Saugustss struct termios t; 3481.12Saugustss 3491.12Saugustss tp->t_dev = dev; 3501.12Saugustss 3511.22Saugustss if (sc->sc_methods->ucom_open != NULL) { 3521.22Saugustss error = sc->sc_methods->ucom_open(sc->sc_parent, 3531.22Saugustss sc->sc_portno); 3541.22Saugustss if (error) { 3551.22Saugustss ucom_cleanup(sc); 3561.26Stoshii sc->sc_opening = 0; 3571.26Stoshii wakeup(&sc->sc_opening); 3581.26Stoshii splx(s); 3591.22Saugustss return (error); 3601.22Saugustss } 3611.22Saugustss } 3621.22Saugustss 3631.12Saugustss ucom_status_change(sc); 3641.12Saugustss 3651.12Saugustss /* 3661.12Saugustss * Initialize the termios status to the defaults. Add in the 3671.12Saugustss * sticky bits from TIOCSFLAGS. 3681.12Saugustss */ 3691.12Saugustss t.c_ispeed = 0; 3701.12Saugustss t.c_ospeed = TTYDEF_SPEED; 3711.12Saugustss t.c_cflag = TTYDEF_CFLAG; 3721.12Saugustss if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL)) 3731.12Saugustss SET(t.c_cflag, CLOCAL); 3741.12Saugustss if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS)) 3751.12Saugustss SET(t.c_cflag, CRTSCTS); 3761.12Saugustss if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF)) 3771.12Saugustss SET(t.c_cflag, MDMBUF); 3781.12Saugustss /* Make sure ucomparam() will do something. */ 3791.12Saugustss tp->t_ospeed = 0; 3801.12Saugustss (void) ucomparam(tp, &t); 3811.12Saugustss tp->t_iflag = TTYDEF_IFLAG; 3821.12Saugustss tp->t_oflag = TTYDEF_OFLAG; 3831.12Saugustss tp->t_lflag = TTYDEF_LFLAG; 3841.12Saugustss ttychars(tp); 3851.12Saugustss ttsetwater(tp); 3861.12Saugustss 3871.12Saugustss /* 3881.12Saugustss * Turn on DTR. We must always do this, even if carrier is not 3891.12Saugustss * present, because otherwise we'd have to use TIOCSDTR 3901.12Saugustss * immediately after setting CLOCAL, which applications do not 3911.12Saugustss * expect. We always assert DTR while the device is open 3921.64Sgson * unless explicitly requested to deassert it. Ditto RTS. 3931.12Saugustss */ 3941.12Saugustss ucom_dtr(sc, 1); 3951.64Sgson ucom_rts(sc, 1); 3961.12Saugustss 3971.30Saugustss /* XXX CLR(sc->sc_rx_flags, RX_ANY_BLOCK);*/ 3981.12Saugustss ucom_hwiflow(sc); 3991.12Saugustss 4001.12Saugustss DPRINTF(("ucomopen: open pipes in=%d out=%d\n", 4011.12Saugustss sc->sc_bulkin_no, sc->sc_bulkout_no)); 4021.12Saugustss 4031.12Saugustss /* Open the bulk pipes */ 4041.12Saugustss err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0, 4051.12Saugustss &sc->sc_bulkin_pipe); 4061.12Saugustss if (err) { 4071.52Snathanw DPRINTF(("%s: open bulk in error (addr %d), err=%s\n", 4081.43Saugustss USBDEVNAME(sc->sc_dev), sc->sc_bulkin_no, 4091.12Saugustss usbd_errstr(err))); 4101.28Stoshii error = EIO; 4111.26Stoshii goto fail_0; 4121.12Saugustss } 4131.12Saugustss err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no, 4141.12Saugustss USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); 4151.12Saugustss if (err) { 4161.52Snathanw DPRINTF(("%s: open bulk out error (addr %d), err=%s\n", 4171.12Saugustss USBDEVNAME(sc->sc_dev), sc->sc_bulkout_no, 4181.12Saugustss usbd_errstr(err))); 4191.28Stoshii error = EIO; 4201.26Stoshii goto fail_1; 4211.12Saugustss } 4221.43Saugustss 4231.12Saugustss /* Allocate a request and an input buffer and start reading. */ 4241.69.10.1Sitohy sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev, sc->sc_bulkin_pipe); 4251.28Stoshii if (sc->sc_ixfer == NULL) { 4261.28Stoshii error = ENOMEM; 4271.26Stoshii goto fail_2; 4281.28Stoshii } 4291.26Stoshii 4301.22Saugustss sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer, 4311.22Saugustss sc->sc_ibufsizepad); 4321.28Stoshii if (sc->sc_ibuf == NULL) { 4331.28Stoshii error = ENOMEM; 4341.26Stoshii goto fail_3; 4351.28Stoshii } 4361.12Saugustss 4371.69.10.1Sitohy sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev, 4381.69.10.1Sitohy sc->sc_bulkout_pipe); 4391.28Stoshii if (sc->sc_oxfer == NULL) { 4401.28Stoshii error = ENOMEM; 4411.26Stoshii goto fail_3; 4421.28Stoshii } 4431.26Stoshii 4441.22Saugustss sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer, 4451.25Saugustss sc->sc_obufsize + 4461.25Saugustss sc->sc_opkthdrlen); 4471.28Stoshii if (sc->sc_obuf == NULL) { 4481.28Stoshii error = ENOMEM; 4491.26Stoshii goto fail_4; 4501.28Stoshii } 4511.12Saugustss 4521.12Saugustss ucomstartread(sc); 4531.12Saugustss } 4541.12Saugustss sc->sc_opening = 0; 4551.12Saugustss wakeup(&sc->sc_opening); 4561.12Saugustss splx(s); 4571.12Saugustss 4581.12Saugustss error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK)); 4591.12Saugustss if (error) 4601.12Saugustss goto bad; 4611.12Saugustss 4621.32Seeh error = (*tp->t_linesw->l_open)(dev, tp); 4631.12Saugustss if (error) 4641.12Saugustss goto bad; 4651.12Saugustss 4661.12Saugustss return (0); 4671.26Stoshii 4681.26Stoshiifail_4: 4691.26Stoshii usbd_free_xfer(sc->sc_oxfer); 4701.34Saugustss sc->sc_oxfer = NULL; 4711.26Stoshiifail_3: 4721.26Stoshii usbd_free_xfer(sc->sc_ixfer); 4731.34Saugustss sc->sc_ixfer = NULL; 4741.26Stoshiifail_2: 4751.26Stoshii usbd_close_pipe(sc->sc_bulkout_pipe); 4761.34Saugustss sc->sc_bulkout_pipe = NULL; 4771.26Stoshiifail_1: 4781.26Stoshii usbd_close_pipe(sc->sc_bulkin_pipe); 4791.34Saugustss sc->sc_bulkin_pipe = NULL; 4801.26Stoshiifail_0: 4811.26Stoshii sc->sc_opening = 0; 4821.26Stoshii wakeup(&sc->sc_opening); 4831.26Stoshii splx(s); 4841.28Stoshii return (error); 4851.12Saugustss 4861.12Saugustssbad: 4871.12Saugustss if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 4881.12Saugustss /* 4891.12Saugustss * We failed to open the device, and nobody else had it opened. 4901.12Saugustss * Clean up the state as appropriate. 4911.12Saugustss */ 4921.12Saugustss ucom_cleanup(sc); 4931.12Saugustss } 4941.12Saugustss 4951.12Saugustss return (error); 4961.12Saugustss} 4971.12Saugustss 4981.12Saugustssint 4991.69.10.1Sitohyucomclose(dev_t dev, int flag, int mode, usb_proc_ptr l) 5001.12Saugustss{ 5011.12Saugustss struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 5021.12Saugustss struct tty *tp = sc->sc_tty; 5031.12Saugustss 5041.12Saugustss DPRINTF(("ucomclose: unit=%d\n", UCOMUNIT(dev))); 5051.12Saugustss if (!ISSET(tp->t_state, TS_ISOPEN)) 5061.12Saugustss return (0); 5071.12Saugustss 5081.17Saugustss sc->sc_refcnt++; 5091.17Saugustss 5101.32Seeh (*tp->t_linesw->l_close)(tp, flag); 5111.12Saugustss ttyclose(tp); 5121.12Saugustss 5131.12Saugustss if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) { 5141.12Saugustss /* 5151.12Saugustss * Although we got a last close, the device may still be in 5161.12Saugustss * use; e.g. if this was the dialout node, and there are still 5171.12Saugustss * processes waiting for carrier on the non-dialout node. 5181.12Saugustss */ 5191.12Saugustss ucom_cleanup(sc); 5201.12Saugustss } 5211.12Saugustss 5221.14Saugustss if (sc->sc_methods->ucom_close != NULL) 5231.14Saugustss sc->sc_methods->ucom_close(sc->sc_parent, sc->sc_portno); 5241.14Saugustss 5251.17Saugustss if (--sc->sc_refcnt < 0) 5261.17Saugustss usb_detach_wakeup(USBDEV(sc->sc_dev)); 5271.17Saugustss 5281.12Saugustss return (0); 5291.12Saugustss} 5301.43Saugustss 5311.12Saugustssint 5321.24Saugustssucomread(dev_t dev, struct uio *uio, int flag) 5331.12Saugustss{ 5341.12Saugustss struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 5351.12Saugustss struct tty *tp = sc->sc_tty; 5361.17Saugustss int error; 5371.12Saugustss 5381.12Saugustss if (sc->sc_dying) 5391.12Saugustss return (EIO); 5401.43Saugustss 5411.17Saugustss sc->sc_refcnt++; 5421.32Seeh error = ((*tp->t_linesw->l_read)(tp, uio, flag)); 5431.17Saugustss if (--sc->sc_refcnt < 0) 5441.17Saugustss usb_detach_wakeup(USBDEV(sc->sc_dev)); 5451.17Saugustss return (error); 5461.12Saugustss} 5471.43Saugustss 5481.12Saugustssint 5491.24Saugustssucomwrite(dev_t dev, struct uio *uio, int flag) 5501.12Saugustss{ 5511.12Saugustss struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 5521.12Saugustss struct tty *tp = sc->sc_tty; 5531.17Saugustss int error; 5541.12Saugustss 5551.12Saugustss if (sc->sc_dying) 5561.12Saugustss return (EIO); 5571.43Saugustss 5581.17Saugustss sc->sc_refcnt++; 5591.32Seeh error = ((*tp->t_linesw->l_write)(tp, uio, flag)); 5601.38Sscw if (--sc->sc_refcnt < 0) 5611.38Sscw usb_detach_wakeup(USBDEV(sc->sc_dev)); 5621.38Sscw return (error); 5631.38Sscw} 5641.38Sscw 5651.38Sscwint 5661.69.10.1Sitohyucompoll(dev_t dev, int events, usb_proc_ptr l) 5671.38Sscw{ 5681.38Sscw struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 5691.38Sscw struct tty *tp = sc->sc_tty; 5701.56Sws int revents; 5711.38Sscw 5721.38Sscw if (sc->sc_dying) 5731.56Sws return (POLLHUP); 5741.43Saugustss 5751.38Sscw sc->sc_refcnt++; 5761.60Schristos revents = ((*tp->t_linesw->l_poll)(tp, events, l)); 5771.17Saugustss if (--sc->sc_refcnt < 0) 5781.17Saugustss usb_detach_wakeup(USBDEV(sc->sc_dev)); 5791.56Sws return (revents); 5801.12Saugustss} 5811.12Saugustss 5821.12Saugustssstruct tty * 5831.24Saugustssucomtty(dev_t dev) 5841.12Saugustss{ 5851.12Saugustss struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 5861.12Saugustss struct tty *tp = sc->sc_tty; 5871.12Saugustss 5881.12Saugustss return (tp); 5891.12Saugustss} 5901.12Saugustss 5911.12Saugustssint 5921.69.10.1Sitohyucomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, usb_proc_ptr l) 5931.12Saugustss{ 5941.12Saugustss struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(dev)]; 5951.17Saugustss int error; 5961.17Saugustss 5971.17Saugustss sc->sc_refcnt++; 5981.60Schristos error = ucom_do_ioctl(sc, cmd, data, flag, l); 5991.17Saugustss if (--sc->sc_refcnt < 0) 6001.17Saugustss usb_detach_wakeup(USBDEV(sc->sc_dev)); 6011.17Saugustss return (error); 6021.17Saugustss} 6031.17Saugustss 6041.17SaugustssStatic int 6051.24Saugustssucom_do_ioctl(struct ucom_softc *sc, u_long cmd, caddr_t data, 6061.69.10.1Sitohy int flag, usb_proc_ptr l) 6071.17Saugustss{ 6081.12Saugustss struct tty *tp = sc->sc_tty; 6091.12Saugustss int error; 6101.12Saugustss int s; 6111.12Saugustss 6121.12Saugustss if (sc->sc_dying) 6131.12Saugustss return (EIO); 6141.43Saugustss 6151.12Saugustss DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd)); 6161.12Saugustss 6171.60Schristos error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l); 6181.42Satatat if (error != EPASSTHROUGH) 6191.12Saugustss return (error); 6201.12Saugustss 6211.60Schristos error = ttioctl(tp, cmd, data, flag, l); 6221.42Satatat if (error != EPASSTHROUGH) 6231.12Saugustss return (error); 6241.12Saugustss 6251.12Saugustss if (sc->sc_methods->ucom_ioctl != NULL) { 6261.12Saugustss error = sc->sc_methods->ucom_ioctl(sc->sc_parent, 6271.69.10.1Sitohy sc->sc_portno, cmd, data, flag, l); 6281.42Satatat if (error != EPASSTHROUGH) 6291.12Saugustss return (error); 6301.12Saugustss } 6311.12Saugustss 6321.12Saugustss error = 0; 6331.12Saugustss 6341.12Saugustss DPRINTF(("ucomioctl: our cmd=0x%08lx\n", cmd)); 6351.12Saugustss s = spltty(); 6361.12Saugustss 6371.12Saugustss switch (cmd) { 6381.12Saugustss case TIOCSBRK: 6391.12Saugustss ucom_break(sc, 1); 6401.12Saugustss break; 6411.12Saugustss 6421.12Saugustss case TIOCCBRK: 6431.12Saugustss ucom_break(sc, 0); 6441.12Saugustss break; 6451.12Saugustss 6461.12Saugustss case TIOCSDTR: 6471.12Saugustss ucom_dtr(sc, 1); 6481.12Saugustss break; 6491.12Saugustss 6501.12Saugustss case TIOCCDTR: 6511.12Saugustss ucom_dtr(sc, 0); 6521.12Saugustss break; 6531.12Saugustss 6541.12Saugustss case TIOCGFLAGS: 6551.12Saugustss *(int *)data = sc->sc_swflags; 6561.12Saugustss break; 6571.12Saugustss 6581.12Saugustss case TIOCSFLAGS: 6591.67Selad error = kauth_authorize_device_tty(l->l_cred, 6601.67Selad KAUTH_DEVICE_TTY_PRIVSET, tp); 6611.12Saugustss if (error) 6621.12Saugustss break; 6631.12Saugustss sc->sc_swflags = *(int *)data; 6641.12Saugustss break; 6651.12Saugustss 6661.12Saugustss case TIOCMSET: 6671.12Saugustss case TIOCMBIS: 6681.12Saugustss case TIOCMBIC: 6691.12Saugustss tiocm_to_ucom(sc, cmd, *(int *)data); 6701.12Saugustss break; 6711.12Saugustss 6721.12Saugustss case TIOCMGET: 6731.12Saugustss *(int *)data = ucom_to_tiocm(sc); 6741.12Saugustss break; 6751.12Saugustss 6761.12Saugustss default: 6771.42Satatat error = EPASSTHROUGH; 6781.12Saugustss break; 6791.12Saugustss } 6801.12Saugustss 6811.12Saugustss splx(s); 6821.12Saugustss 6831.12Saugustss return (error); 6841.12Saugustss} 6851.12Saugustss 6861.17SaugustssStatic void 6871.29Stoshiitiocm_to_ucom(struct ucom_softc *sc, u_long how, int ttybits) 6881.12Saugustss{ 6891.12Saugustss u_char combits; 6901.3Saugustss 6911.12Saugustss combits = 0; 6921.12Saugustss if (ISSET(ttybits, TIOCM_DTR)) 6931.12Saugustss SET(combits, UMCR_DTR); 6941.12Saugustss if (ISSET(ttybits, TIOCM_RTS)) 6951.12Saugustss SET(combits, UMCR_RTS); 6961.43Saugustss 6971.12Saugustss switch (how) { 6981.12Saugustss case TIOCMBIC: 6991.12Saugustss CLR(sc->sc_mcr, combits); 7001.12Saugustss break; 7011.12Saugustss 7021.12Saugustss case TIOCMBIS: 7031.12Saugustss SET(sc->sc_mcr, combits); 7041.12Saugustss break; 7051.12Saugustss 7061.12Saugustss case TIOCMSET: 7071.12Saugustss CLR(sc->sc_mcr, UMCR_DTR | UMCR_RTS); 7081.12Saugustss SET(sc->sc_mcr, combits); 7091.12Saugustss break; 7101.12Saugustss } 7111.12Saugustss 7121.27Stoshii if (how == TIOCMSET || ISSET(combits, UMCR_DTR)) 7131.27Stoshii ucom_dtr(sc, (sc->sc_mcr & UMCR_DTR) != 0); 7141.27Stoshii if (how == TIOCMSET || ISSET(combits, UMCR_RTS)) 7151.27Stoshii ucom_rts(sc, (sc->sc_mcr & UMCR_RTS) != 0); 7161.12Saugustss} 7171.12Saugustss 7181.17SaugustssStatic int 7191.24Saugustssucom_to_tiocm(struct ucom_softc *sc) 7201.12Saugustss{ 7211.12Saugustss u_char combits; 7221.12Saugustss int ttybits = 0; 7231.12Saugustss 7241.12Saugustss combits = sc->sc_mcr; 7251.12Saugustss if (ISSET(combits, UMCR_DTR)) 7261.12Saugustss SET(ttybits, TIOCM_DTR); 7271.12Saugustss if (ISSET(combits, UMCR_RTS)) 7281.12Saugustss SET(ttybits, TIOCM_RTS); 7291.12Saugustss 7301.12Saugustss combits = sc->sc_msr; 7311.12Saugustss if (ISSET(combits, UMSR_DCD)) 7321.12Saugustss SET(ttybits, TIOCM_CD); 7331.12Saugustss if (ISSET(combits, UMSR_CTS)) 7341.12Saugustss SET(ttybits, TIOCM_CTS); 7351.12Saugustss if (ISSET(combits, UMSR_DSR)) 7361.12Saugustss SET(ttybits, TIOCM_DSR); 7371.12Saugustss if (ISSET(combits, UMSR_RI | UMSR_TERI)) 7381.12Saugustss SET(ttybits, TIOCM_RI); 7391.12Saugustss 7401.12Saugustss#if 0 7411.12SaugustssXXX; 7421.12Saugustss if (sc->sc_ier != 0) 7431.12Saugustss SET(ttybits, TIOCM_LE); 7441.12Saugustss#endif 7451.12Saugustss 7461.12Saugustss return (ttybits); 7471.12Saugustss} 7481.12Saugustss 7491.17SaugustssStatic void 7501.12Saugustssucom_break(sc, onoff) 7511.12Saugustss struct ucom_softc *sc; 7521.12Saugustss int onoff; 7531.12Saugustss{ 7541.12Saugustss DPRINTF(("ucom_break: onoff=%d\n", onoff)); 7551.12Saugustss 7561.14Saugustss if (sc->sc_methods->ucom_set != NULL) 7571.14Saugustss sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 7581.14Saugustss UCOM_SET_BREAK, onoff); 7591.12Saugustss} 7601.12Saugustss 7611.17SaugustssStatic void 7621.24Saugustssucom_dtr(struct ucom_softc *sc, int onoff) 7631.12Saugustss{ 7641.12Saugustss DPRINTF(("ucom_dtr: onoff=%d\n", onoff)); 7651.12Saugustss 7661.14Saugustss if (sc->sc_methods->ucom_set != NULL) 7671.43Saugustss sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 7681.14Saugustss UCOM_SET_DTR, onoff); 7691.12Saugustss} 7701.12Saugustss 7711.17SaugustssStatic void 7721.24Saugustssucom_rts(struct ucom_softc *sc, int onoff) 7731.12Saugustss{ 7741.12Saugustss DPRINTF(("ucom_rts: onoff=%d\n", onoff)); 7751.12Saugustss 7761.14Saugustss if (sc->sc_methods->ucom_set != NULL) 7771.43Saugustss sc->sc_methods->ucom_set(sc->sc_parent, sc->sc_portno, 7781.14Saugustss UCOM_SET_RTS, onoff); 7791.12Saugustss} 7801.12Saugustss 7811.22Saugustssvoid 7821.24Saugustssucom_status_change(struct ucom_softc *sc) 7831.12Saugustss{ 7841.27Stoshii struct tty *tp = sc->sc_tty; 7851.27Stoshii u_char old_msr; 7861.27Stoshii 7871.14Saugustss if (sc->sc_methods->ucom_get_status != NULL) { 7881.27Stoshii old_msr = sc->sc_msr; 7891.14Saugustss sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno, 7901.14Saugustss &sc->sc_lsr, &sc->sc_msr); 7911.27Stoshii if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) 7921.32Seeh (*tp->t_linesw->l_modem)(tp, 7931.27Stoshii ISSET(sc->sc_msr, UMSR_DCD)); 7941.14Saugustss } else { 7951.14Saugustss sc->sc_lsr = 0; 7961.54Saugustss /* Assume DCD is present, if we have no chance to check it. */ 7971.54Saugustss sc->sc_msr = UMSR_DCD; 7981.14Saugustss } 7991.12Saugustss} 8001.12Saugustss 8011.17SaugustssStatic int 8021.24Saugustssucomparam(struct tty *tp, struct termios *t) 8031.12Saugustss{ 8041.12Saugustss struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)]; 8051.14Saugustss int error; 8061.12Saugustss 8071.12Saugustss if (sc->sc_dying) 8081.12Saugustss return (EIO); 8091.12Saugustss 8101.12Saugustss /* Check requested parameters. */ 8111.12Saugustss if (t->c_ispeed && t->c_ispeed != t->c_ospeed) 8121.12Saugustss return (EINVAL); 8131.12Saugustss 8141.12Saugustss /* 8151.12Saugustss * For the console, always force CLOCAL and !HUPCL, so that the port 8161.12Saugustss * is always active. 8171.12Saugustss */ 8181.12Saugustss if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR)) { 8191.12Saugustss SET(t->c_cflag, CLOCAL); 8201.12Saugustss CLR(t->c_cflag, HUPCL); 8211.12Saugustss } 8221.12Saugustss 8231.12Saugustss /* 8241.12Saugustss * If there were no changes, don't do anything. This avoids dropping 8251.12Saugustss * input and improves performance when all we did was frob things like 8261.12Saugustss * VMIN and VTIME. 8271.12Saugustss */ 8281.12Saugustss if (tp->t_ospeed == t->c_ospeed && 8291.12Saugustss tp->t_cflag == t->c_cflag) 8301.12Saugustss return (0); 8311.12Saugustss 8321.30Saugustss /* XXX lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag); */ 8331.12Saugustss 8341.12Saugustss /* And copy to tty. */ 8351.12Saugustss tp->t_ispeed = 0; 8361.12Saugustss tp->t_ospeed = t->c_ospeed; 8371.12Saugustss tp->t_cflag = t->c_cflag; 8381.12Saugustss 8391.14Saugustss if (sc->sc_methods->ucom_param != NULL) { 8401.14Saugustss error = sc->sc_methods->ucom_param(sc->sc_parent, sc->sc_portno, 8411.14Saugustss t); 8421.14Saugustss if (error) 8431.14Saugustss return (error); 8441.14Saugustss } 8451.12Saugustss 8461.30Saugustss /* XXX worry about CHWFLOW */ 8471.12Saugustss 8481.12Saugustss /* 8491.12Saugustss * Update the tty layer's idea of the carrier bit, in case we changed 8501.12Saugustss * CLOCAL or MDMBUF. We don't hang up here; we only do that by 8511.12Saugustss * explicit request. 8521.12Saugustss */ 8531.12Saugustss DPRINTF(("ucomparam: l_modem\n")); 8541.54Saugustss (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD)); 8551.12Saugustss 8561.12Saugustss#if 0 8571.12SaugustssXXX what if the hardware is not open 8581.12Saugustss if (!ISSET(t->c_cflag, CHWFLOW)) { 8591.12Saugustss if (sc->sc_tx_stopped) { 8601.12Saugustss sc->sc_tx_stopped = 0; 8611.12Saugustss ucomstart(tp); 8621.12Saugustss } 8631.12Saugustss } 8641.12Saugustss#endif 8651.12Saugustss 8661.12Saugustss return (0); 8671.12Saugustss} 8681.12Saugustss 8691.12Saugustss/* 8701.12Saugustss * (un)block input via hw flowcontrol 8711.12Saugustss */ 8721.17SaugustssStatic void 8731.69Schristosucom_hwiflow(struct ucom_softc *sc) 8741.12Saugustss{ 8751.19Saugustss DPRINTF(("ucom_hwiflow:\n")); 8761.12Saugustss#if 0 8771.12SaugustssXXX 8781.12Saugustss bus_space_tag_t iot = sc->sc_iot; 8791.12Saugustss bus_space_handle_t ioh = sc->sc_ioh; 8801.12Saugustss 8811.12Saugustss if (sc->sc_mcr_rts == 0) 8821.12Saugustss return; 8831.12Saugustss 8841.12Saugustss if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) { 8851.12Saugustss CLR(sc->sc_mcr, sc->sc_mcr_rts); 8861.12Saugustss CLR(sc->sc_mcr_active, sc->sc_mcr_rts); 8871.12Saugustss } else { 8881.12Saugustss SET(sc->sc_mcr, sc->sc_mcr_rts); 8891.12Saugustss SET(sc->sc_mcr_active, sc->sc_mcr_rts); 8901.12Saugustss } 8911.12Saugustss bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active); 8921.12Saugustss#endif 8931.1Saugustss} 8941.3Saugustss 8951.17SaugustssStatic void 8961.24Saugustssucomstart(struct tty *tp) 8971.12Saugustss{ 8981.12Saugustss struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)]; 8991.12Saugustss usbd_status err; 9001.12Saugustss int s; 9011.12Saugustss u_char *data; 9021.12Saugustss int cnt; 9031.12Saugustss 9041.12Saugustss if (sc->sc_dying) 9051.12Saugustss return; 9061.12Saugustss 9071.12Saugustss s = spltty(); 9081.12Saugustss if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) { 9091.19Saugustss DPRINTFN(4,("ucomstart: no go, state=0x%x\n", tp->t_state)); 9101.12Saugustss goto out; 9111.12Saugustss } 9121.12Saugustss if (sc->sc_tx_stopped) 9131.12Saugustss goto out; 9141.12Saugustss 9151.12Saugustss if (tp->t_outq.c_cc <= tp->t_lowat) { 9161.12Saugustss if (ISSET(tp->t_state, TS_ASLEEP)) { 9171.12Saugustss CLR(tp->t_state, TS_ASLEEP); 9181.12Saugustss wakeup(&tp->t_outq); 9191.12Saugustss } 9201.12Saugustss selwakeup(&tp->t_wsel); 9211.12Saugustss if (tp->t_outq.c_cc == 0) 9221.12Saugustss goto out; 9231.12Saugustss } 9241.12Saugustss 9251.12Saugustss /* Grab the first contiguous region of buffer space. */ 9261.12Saugustss data = tp->t_outq.c_cf; 9271.12Saugustss cnt = ndqb(&tp->t_outq, 0); 9281.12Saugustss 9291.12Saugustss if (cnt == 0) { 9301.12Saugustss DPRINTF(("ucomstart: cnt==0\n")); 9311.12Saugustss goto out; 9321.12Saugustss } 9331.12Saugustss 9341.12Saugustss SET(tp->t_state, TS_BUSY); 9351.12Saugustss 9361.19Saugustss if (cnt > sc->sc_obufsize) { 9371.12Saugustss DPRINTF(("ucomstart: big buffer %d chars\n", cnt)); 9381.19Saugustss cnt = sc->sc_obufsize; 9391.12Saugustss } 9401.22Saugustss if (sc->sc_methods->ucom_write != NULL) 9411.22Saugustss sc->sc_methods->ucom_write(sc->sc_parent, sc->sc_portno, 9421.22Saugustss sc->sc_obuf, data, &cnt); 9431.22Saugustss else 9441.22Saugustss memcpy(sc->sc_obuf, data, cnt); 9451.12Saugustss 9461.12Saugustss DPRINTFN(4,("ucomstart: %d chars\n", cnt)); 9471.43Saugustss usbd_setup_xfer(sc->sc_oxfer, sc->sc_bulkout_pipe, 9481.12Saugustss (usbd_private_handle)sc, sc->sc_obuf, cnt, 9491.12Saugustss USBD_NO_COPY, USBD_NO_TIMEOUT, ucomwritecb); 9501.12Saugustss /* What can we do on error? */ 9511.12Saugustss err = usbd_transfer(sc->sc_oxfer); 9521.12Saugustss#ifdef DIAGNOSTIC 9531.12Saugustss if (err != USBD_IN_PROGRESS) 9541.12Saugustss printf("ucomstart: err=%s\n", usbd_errstr(err)); 9551.3Saugustss#endif 9561.3Saugustss 9571.12Saugustssout: 9581.12Saugustss splx(s); 9591.12Saugustss} 9601.12Saugustss 9611.21Sitojunvoid 9621.69Schristosucomstop(struct tty *tp, int flag) 9631.12Saugustss{ 9641.19Saugustss DPRINTF(("ucomstop: flag=%d\n", flag)); 9651.19Saugustss#if 0 9661.19Saugustss /*struct ucom_softc *sc = ucom_cd.cd_devs[UCOMUNIT(tp->t_dev)];*/ 9671.12Saugustss int s; 9681.12Saugustss 9691.12Saugustss s = spltty(); 9701.12Saugustss if (ISSET(tp->t_state, TS_BUSY)) { 9711.12Saugustss DPRINTF(("ucomstop: XXX\n")); 9721.19Saugustss /* sc->sc_tx_stopped = 1; */ 9731.12Saugustss if (!ISSET(tp->t_state, TS_TTSTOP)) 9741.12Saugustss SET(tp->t_state, TS_FLUSH); 9751.12Saugustss } 9761.12Saugustss splx(s); 9771.19Saugustss#endif 9781.12Saugustss} 9791.12Saugustss 9801.17SaugustssStatic void 9811.24Saugustssucomwritecb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) 9821.12Saugustss{ 9831.12Saugustss struct ucom_softc *sc = (struct ucom_softc *)p; 9841.12Saugustss struct tty *tp = sc->sc_tty; 9851.12Saugustss u_int32_t cc; 9861.12Saugustss int s; 9871.12Saugustss 9881.12Saugustss DPRINTFN(5,("ucomwritecb: status=%d\n", status)); 9891.12Saugustss 9901.34Saugustss if (status == USBD_CANCELLED || sc->sc_dying) 9911.39Saugustss goto error; 9921.12Saugustss 9931.12Saugustss if (status) { 9941.12Saugustss DPRINTF(("ucomwritecb: status=%d\n", status)); 9951.12Saugustss usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); 9961.12Saugustss /* XXX we should restart after some delay. */ 9971.39Saugustss goto error; 9981.12Saugustss } 9991.12Saugustss 10001.15Saugustss usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL); 10011.31Sexplorer#if defined(__NetBSD__) && NRND > 0 10021.31Sexplorer rnd_add_uint32(&sc->sc_rndsource, cc); 10031.31Sexplorer#endif 10041.12Saugustss DPRINTFN(5,("ucomwritecb: cc=%d\n", cc)); 10051.25Saugustss /* convert from USB bytes to tty bytes */ 10061.25Saugustss cc -= sc->sc_opkthdrlen; 10071.12Saugustss 10081.12Saugustss s = spltty(); 10091.12Saugustss CLR(tp->t_state, TS_BUSY); 10101.12Saugustss if (ISSET(tp->t_state, TS_FLUSH)) 10111.12Saugustss CLR(tp->t_state, TS_FLUSH); 10121.12Saugustss else 10131.12Saugustss ndflush(&tp->t_outq, cc); 10141.32Seeh (*tp->t_linesw->l_start)(tp); 10151.39Saugustss splx(s); 10161.39Saugustss return; 10171.39Saugustss 10181.39Saugustsserror: 10191.39Saugustss s = spltty(); 10201.39Saugustss CLR(tp->t_state, TS_BUSY); 10211.12Saugustss splx(s); 10221.12Saugustss} 10231.12Saugustss 10241.17SaugustssStatic usbd_status 10251.24Saugustssucomstartread(struct ucom_softc *sc) 10261.12Saugustss{ 10271.12Saugustss usbd_status err; 10281.12Saugustss 10291.12Saugustss DPRINTFN(5,("ucomstartread: start\n")); 10301.43Saugustss usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe, 10311.43Saugustss (usbd_private_handle)sc, 10321.19Saugustss sc->sc_ibuf, sc->sc_ibufsize, 10331.12Saugustss USBD_SHORT_XFER_OK | USBD_NO_COPY, 10341.12Saugustss USBD_NO_TIMEOUT, ucomreadcb); 10351.12Saugustss err = usbd_transfer(sc->sc_ixfer); 10361.12Saugustss if (err != USBD_IN_PROGRESS) { 10371.12Saugustss DPRINTF(("ucomstartread: err=%s\n", usbd_errstr(err))); 10381.12Saugustss return (err); 10391.12Saugustss } 10401.12Saugustss return (USBD_NORMAL_COMPLETION); 10411.12Saugustss} 10421.43Saugustss 10431.17SaugustssStatic void 10441.24Saugustssucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status) 10451.12Saugustss{ 10461.12Saugustss struct ucom_softc *sc = (struct ucom_softc *)p; 10471.12Saugustss struct tty *tp = sc->sc_tty; 10481.55Schristos int (*rint)(int, struct tty *) = tp->t_linesw->l_rint; 10491.12Saugustss usbd_status err; 10501.12Saugustss u_int32_t cc; 10511.12Saugustss u_char *cp; 10521.12Saugustss int s; 10531.12Saugustss 10541.34Saugustss DPRINTFN(5,("ucomreadcb: status=%d\n", status)); 10551.34Saugustss 10561.34Saugustss if (status == USBD_CANCELLED || status == USBD_IOERROR || 10571.34Saugustss sc->sc_dying) { 10581.34Saugustss DPRINTF(("ucomreadcb: dying\n")); 10591.34Saugustss /* Send something to wake upper layer */ 10601.34Saugustss s = spltty(); 10611.34Saugustss (*rint)('\n', tp); 10621.34Saugustss ttwakeup(tp); 10631.34Saugustss splx(s); 10641.12Saugustss return; 10651.34Saugustss } 10661.12Saugustss 10671.12Saugustss if (status) { 10681.12Saugustss usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); 10691.12Saugustss /* XXX we should restart after some delay. */ 10701.12Saugustss return; 10711.12Saugustss } 10721.12Saugustss 10731.48Sthorpej usbd_get_xfer_status(xfer, NULL, (void *)&cp, &cc, NULL); 10741.31Sexplorer#if defined(__NetBSD__) && NRND > 0 10751.31Sexplorer rnd_add_uint32(&sc->sc_rndsource, cc); 10761.31Sexplorer#endif 10771.12Saugustss DPRINTFN(5,("ucomreadcb: got %d chars, tp=%p\n", cc, tp)); 10781.22Saugustss if (sc->sc_methods->ucom_read != NULL) 10791.22Saugustss sc->sc_methods->ucom_read(sc->sc_parent, sc->sc_portno, 10801.22Saugustss &cp, &cc); 10811.22Saugustss 10821.12Saugustss s = spltty(); 10831.12Saugustss /* Give characters to tty layer. */ 10841.12Saugustss while (cc-- > 0) { 10851.12Saugustss DPRINTFN(7,("ucomreadcb: char=0x%02x\n", *cp)); 10861.12Saugustss if ((*rint)(*cp++, tp) == -1) { 10871.12Saugustss /* XXX what should we do? */ 10881.19Saugustss printf("%s: lost %d chars\n", USBDEVNAME(sc->sc_dev), 10891.19Saugustss cc); 10901.12Saugustss break; 10911.12Saugustss } 10921.12Saugustss } 10931.12Saugustss splx(s); 10941.12Saugustss 10951.12Saugustss err = ucomstartread(sc); 10961.12Saugustss if (err) { 10971.12Saugustss printf("%s: read start failed\n", USBDEVNAME(sc->sc_dev)); 10981.12Saugustss /* XXX what should we dow now? */ 10991.12Saugustss } 11001.12Saugustss} 11011.12Saugustss 11021.17SaugustssStatic void 11031.24Saugustssucom_cleanup(struct ucom_softc *sc) 11041.12Saugustss{ 11051.12Saugustss DPRINTF(("ucom_cleanup: closing pipes\n")); 11061.12Saugustss 11071.12Saugustss ucom_shutdown(sc); 11081.69.10.2Sitohy if (sc->sc_bulkin_pipe != NULL) 11091.33Saugustss usbd_abort_pipe(sc->sc_bulkin_pipe); 11101.69.10.2Sitohy if (sc->sc_bulkout_pipe != NULL) 11111.33Saugustss usbd_abort_pipe(sc->sc_bulkout_pipe); 11121.33Saugustss if (sc->sc_ixfer != NULL) { 11131.33Saugustss usbd_free_xfer(sc->sc_ixfer); 11141.33Saugustss sc->sc_ixfer = NULL; 11151.33Saugustss } 11161.33Saugustss if (sc->sc_oxfer != NULL) { 11171.33Saugustss usbd_free_xfer(sc->sc_oxfer); 11181.33Saugustss sc->sc_oxfer = NULL; 11191.33Saugustss } 11201.69.10.2Sitohy if (sc->sc_bulkin_pipe != NULL) { 11211.69.10.2Sitohy usbd_close_pipe(sc->sc_bulkin_pipe); 11221.69.10.2Sitohy sc->sc_bulkin_pipe = NULL; 11231.69.10.2Sitohy } 11241.69.10.2Sitohy if (sc->sc_bulkout_pipe != NULL) { 11251.69.10.2Sitohy usbd_close_pipe(sc->sc_bulkout_pipe); 11261.69.10.2Sitohy sc->sc_bulkout_pipe = NULL; 11271.69.10.2Sitohy } 11281.12Saugustss} 11291.13Saugustss 11301.13Saugustss#endif /* NUCOM > 0 */ 11311.12Saugustss 11321.20Saugustssint 11331.24Saugustssucomprint(void *aux, const char *pnp) 11341.12Saugustss{ 11351.37Saugustss struct ucom_attach_args *uca = aux; 11361.12Saugustss 11371.12Saugustss if (pnp) 11381.49Sthorpej aprint_normal("ucom at %s", pnp); 11391.37Saugustss if (uca->portno != UCOM_UNK_PORTNO) 11401.49Sthorpej aprint_normal(" portno %d", uca->portno); 11411.12Saugustss return (UNCONF); 11421.12Saugustss} 11431.12Saugustss 11441.20Saugustssint 11451.53Sdrochnerucomsubmatch(struct device *parent, struct cfdata *cf, 11461.69Schristos const int *ldesc, void *aux) 11471.12Saugustss{ 11481.12Saugustss struct ucom_attach_args *uca = aux; 11491.12Saugustss 11501.12Saugustss if (uca->portno != UCOM_UNK_PORTNO && 11511.53Sdrochner cf->cf_loc[UCOMBUSCF_PORTNO] != UCOMBUSCF_PORTNO_DEFAULT && 11521.53Sdrochner cf->cf_loc[UCOMBUSCF_PORTNO] != uca->portno) 11531.12Saugustss return (0); 11541.46Sthorpej return (config_match(parent, cf, aux)); 11551.12Saugustss} 1156