Date: Wed, 28 Nov 2012 18:10:05 +0000 (UTC) From: Hans Petter Selasky <hselasky@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r243656 - in stable/9/sys: dev/usb/serial sys Message-ID: <201211281810.qASIA5E5004369@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hselasky Date: Wed Nov 28 18:10:05 2012 New Revision: 243656 URL: http://svnweb.freebsd.org/changeset/base/243656 Log: MFC r242619, r242695, r242702 and r242703: Implement support for RTS (flow control). Improve USB serial console support. Implement a USB serial jitter buffer in receive direction. Modified: stable/9/sys/dev/usb/serial/usb_serial.c stable/9/sys/dev/usb/serial/usb_serial.h stable/9/sys/sys/param.h Directory Properties: stable/9/sys/ (props changed) stable/9/sys/dev/ (props changed) Modified: stable/9/sys/dev/usb/serial/usb_serial.c ============================================================================== --- stable/9/sys/dev/usb/serial/usb_serial.c Wed Nov 28 17:55:18 2012 (r243655) +++ stable/9/sys/dev/usb/serial/usb_serial.c Wed Nov 28 18:10:05 2012 (r243656) @@ -162,6 +162,7 @@ static tsw_ioctl_t ucom_ioctl; static tsw_modem_t ucom_modem; static tsw_param_t ucom_param; static tsw_outwakeup_t ucom_outwakeup; +static tsw_inwakeup_t ucom_inwakeup; static tsw_free_t ucom_free; static struct ttydevsw ucom_class = { @@ -169,6 +170,7 @@ static struct ttydevsw ucom_class = { .tsw_open = ucom_open, .tsw_close = ucom_close, .tsw_outwakeup = ucom_outwakeup, + .tsw_inwakeup = ucom_inwakeup, .tsw_ioctl = ucom_ioctl, .tsw_param = ucom_param, .tsw_modem = ucom_modem, @@ -423,16 +425,13 @@ ucom_attach_tty(struct ucom_super_softc if ((ucom_cons_softc == NULL) && (ssc->sc_unit == ucom_cons_unit) && (sc->sc_subunit == ucom_cons_subunit)) { - struct termios t; - DPRINTF("unit %d subunit %d is console", ssc->sc_unit, sc->sc_subunit); + DPRINTF("unit %d subunit %d is console", + ssc->sc_unit, sc->sc_subunit); ucom_cons_softc = sc; - memset(&t, 0, sizeof(t)); - t.c_ispeed = ucom_cons_baud; - t.c_ospeed = t.c_ispeed; - t.c_cflag = CS8; + tty_init_console(tp, ucom_cons_baud); UCOM_MTX_LOCK(ucom_cons_softc); ucom_cons_rx_low = 0; @@ -441,7 +440,7 @@ ucom_attach_tty(struct ucom_super_softc ucom_cons_tx_high = 0; sc->sc_flag |= UCOM_FLAG_CONSOLE; ucom_open(ucom_cons_softc->sc_tty); - ucom_param(ucom_cons_softc->sc_tty, &t); + ucom_param(ucom_cons_softc->sc_tty, &tp->t_termios_init_in); UCOM_MTX_UNLOCK(ucom_cons_softc); } @@ -716,6 +715,10 @@ ucom_open(struct tty *tp) sc->sc_pls_set = 0; sc->sc_pls_clr = 0; + /* reset jitter buffer */ + sc->sc_jitterbuf_in = 0; + sc->sc_jitterbuf_out = 0; + ucom_queue_command(sc, ucom_cfg_open, NULL, &sc->sc_open_task[0].hdr, &sc->sc_open_task[1].hdr); @@ -780,6 +783,46 @@ ucom_close(struct tty *tp) } } +static void +ucom_inwakeup(struct tty *tp) +{ + struct ucom_softc *sc = tty_softc(tp); + uint16_t pos; + + if (sc == NULL) + return; + + UCOM_MTX_ASSERT(sc, MA_OWNED); + + DPRINTF("tp=%p\n", tp); + + if (ttydisc_can_bypass(tp) != 0 || + (sc->sc_flag & UCOM_FLAG_HL_READY) == 0) { + return; + } + + pos = sc->sc_jitterbuf_out; + + while (sc->sc_jitterbuf_in != pos) { + int c; + + c = (char)sc->sc_jitterbuf[pos]; + + if (ttydisc_rint(tp, c, 0) == -1) + break; + pos++; + if (pos >= UCOM_JITTERBUF_SIZE) + pos -= UCOM_JITTERBUF_SIZE; + } + + sc->sc_jitterbuf_out = pos; + + /* clear RTS in async fashion */ + if ((sc->sc_jitterbuf_in == pos) && + (sc->sc_flag & UCOM_FLAG_RTS_IFLOW)) + ucom_rts(sc, 0); +} + static int ucom_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) { @@ -1139,17 +1182,22 @@ ucom_param(struct tty *tp, struct termio if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) { /* XXX the TTY layer should call "open()" first! */ - + /* + * Not quite: Its ordering is partly backwards, but + * some parameters must be set early in ttydev_open(), + * possibly before calling ttydevsw_open(). + */ error = ucom_open(tp); - if (error) { + if (error) goto done; - } + opened = 1; } DPRINTF("sc = %p\n", sc); /* Check requested parameters. */ if (t->c_ispeed && (t->c_ispeed != t->c_ospeed)) { + /* XXX c_ospeed == 0 is perfectly valid. */ DPRINTF("mismatch ispeed and ospeed\n"); error = EINVAL; goto done; @@ -1360,6 +1408,11 @@ ucom_put_data(struct ucom_softc *sc, str /* first check if we can pass the buffer directly */ if (ttydisc_can_bypass(tp)) { + + /* clear any jitter buffer */ + sc->sc_jitterbuf_in = 0; + sc->sc_jitterbuf_out = 0; + if (ttydisc_rint_bypass(tp, buf, cnt) != cnt) { DPRINTF("tp=%p, data lost\n", tp); } @@ -1368,8 +1421,31 @@ ucom_put_data(struct ucom_softc *sc, str /* need to loop */ for (cnt = 0; cnt != res.length; cnt++) { - if (ttydisc_rint(tp, buf[cnt], 0) == -1) { - /* XXX what should we do? */ + if (sc->sc_jitterbuf_in != sc->sc_jitterbuf_out || + ttydisc_rint(tp, buf[cnt], 0) == -1) { + uint16_t end; + uint16_t pos; + + pos = sc->sc_jitterbuf_in; + end = sc->sc_jitterbuf_out + + UCOM_JITTERBUF_SIZE - 1; + if (end >= UCOM_JITTERBUF_SIZE) + end -= UCOM_JITTERBUF_SIZE; + + for (; cnt != res.length; cnt++) { + if (pos == end) + break; + sc->sc_jitterbuf[pos] = buf[cnt]; + pos++; + if (pos >= UCOM_JITTERBUF_SIZE) + pos -= UCOM_JITTERBUF_SIZE; + } + + sc->sc_jitterbuf_in = pos; + + /* set RTS in async fashion */ + if (sc->sc_flag & UCOM_FLAG_RTS_IFLOW) + ucom_rts(sc, 1); DPRINTF("tp=%p, lost %d " "chars\n", tp, res.length - cnt); Modified: stable/9/sys/dev/usb/serial/usb_serial.h ============================================================================== --- stable/9/sys/dev/usb/serial/usb_serial.h Wed Nov 28 17:55:18 2012 (r243655) +++ stable/9/sys/dev/usb/serial/usb_serial.h Wed Nov 28 18:10:05 2012 (r243656) @@ -78,6 +78,7 @@ #define UCOM_MINVER 1 #define UCOM_PREFVER UCOM_MODVER #define UCOM_MAXVER 1 +#define UCOM_JITTERBUF_SIZE 128 /* bytes */ struct usb_device; struct ucom_softc; @@ -169,6 +170,8 @@ struct ucom_softc { struct mtx *sc_mtx; void *sc_parent; int sc_subunit; + uint16_t sc_jitterbuf_in; + uint16_t sc_jitterbuf_out; uint16_t sc_portno; uint16_t sc_flag; #define UCOM_FLAG_RTS_IFLOW 0x01 /* use RTS input flow control */ @@ -191,6 +194,7 @@ struct ucom_softc { #define UCOM_LS_RTS 0x02 #define UCOM_LS_BREAK 0x04 #define UCOM_LS_RING 0x08 + uint8_t sc_jitterbuf[UCOM_JITTERBUF_SIZE]; }; #define UCOM_MTX_ASSERT(sc, what) mtx_assert((sc)->sc_mtx, what) Modified: stable/9/sys/sys/param.h ============================================================================== --- stable/9/sys/sys/param.h Wed Nov 28 17:55:18 2012 (r243655) +++ stable/9/sys/sys/param.h Wed Nov 28 18:10:05 2012 (r243656) @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 901501 /* Master, propagated to newvers */ +#define __FreeBSD_version 901502 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211281810.qASIA5E5004369>