Date: Wed, 3 Sep 2003 02:46:06 -0700 (PDT) From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 37439 for review Message-ID: <200309030946.h839k6VT068477@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=37439 Change 37439 by marcel@marcel_nfs on 2003/09/03 02:45:48 Implement flow control. Note that none of the hardware drivers report that they have hardware support for flow control, so it's all software based for now. The logic is there to set hardware flow control... Affected files ... .. //depot/projects/uart/dev/uart/uart_tty.c#12 edit Differences ... ==== //depot/projects/uart/dev/uart/uart_tty.c#12 (text+ko) ==== @@ -160,22 +160,36 @@ if (sc == NULL || sc->sc_leaving) return; - if (tp->t_state & TS_TBLOCK) - UART_SETSIG(sc, UART_SIG_DRTS); - else - UART_SETSIG(sc, UART_SIG_DRTS|UART_SIG_RTS); + /* + * Handle input flow control. Note that if we have hardware support, + * we don't do anything here. We continue to receive until our buffer + * is full. At that time we cannot empty the UART itself and it will + * de-assert RTS for us. In that situation we're completely stuffed. + * Without hardware support, we need to toggle RTS ourselves. + */ + if ((tp->t_cflag & CRTS_IFLOW) && !sc->sc_hwiflow) { + if ((tp->t_state & TS_TBLOCK) && + (sc->sc_hwsig & UART_SIG_RTS)) + UART_SETSIG(sc, UART_SIG_DRTS); + else if (!(tp->t_state & TS_TBLOCK) && + !(sc->sc_hwsig & UART_SIG_RTS)) + UART_SETSIG(sc, UART_SIG_DRTS|UART_SIG_RTS); + } + + if (tp->t_state & TS_TTSTOP) + return; + + if ((tp->t_state & TS_BUSY) || sc->sc_txbusy) + return; - if (tp->t_state & (TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) { + if (tp->t_outq.c_cc == 0) { ttwwakeup(tp); return; } - if (tp->t_outq.c_cc > 0 && !sc->sc_txbusy) { - sc->sc_txdatasz = q_to_b(&tp->t_outq, sc->sc_txbuf, - sc->sc_txfifosz); - tp->t_state |= TS_BUSY; - UART_TRANSMIT(sc); - } + sc->sc_txdatasz = q_to_b(&tp->t_outq, sc->sc_txbuf, sc->sc_txfifosz); + tp->t_state |= TS_BUSY; + UART_TRANSMIT(sc); ttwwakeup(tp); } @@ -215,8 +229,17 @@ parity = UART_PARITY_NONE; UART_PARAM(sc, t->c_ospeed, databits, stopbits, parity); UART_SETSIG(sc, UART_SIG_DDTR | UART_SIG_DTR); - if ((t->c_cflag & CRTS_IFLOW) == 0) - UART_SETSIG(sc, UART_SIG_DRTS | UART_SIG_RTS); + /* Set input flow control state. */ + if (!sc->sc_hwiflow) { + if ((t->c_cflag & CRTS_IFLOW) && (tp->t_state & TS_TBLOCK)) + UART_SETSIG(sc, UART_SIG_DRTS); + else + UART_SETSIG(sc, UART_SIG_DRTS | UART_SIG_RTS); + } else + UART_IOCTL(sc, UART_IOCTL_IFLOW, (t->c_cflag & CRTS_IFLOW)); + /* Set output flow control state. */ + if (sc->sc_hwoflow) + UART_IOCTL(sc, UART_IOCTL_OFLOW, (t->c_cflag & CCTS_OFLOW)); ttsetwater(tp); return (0); } @@ -260,7 +283,7 @@ tp = sc->sc_u.u_tty.tp; if (pend & UART_IPEND_RXREADY) { - while (!uart_rx_empty(sc)) { + while (!uart_rx_empty(sc) && !(tp->t_state & TS_TBLOCK)) { xc = uart_rx_get(sc); c = xc & 0xff; if (xc & UART_STAT_FRAMERR) @@ -280,6 +303,14 @@ sig = pend & UART_IPEND_SIGMASK; if (sig & UART_SIG_DDCD) (*linesw[tp->t_line].l_modem)(tp, sig & UART_SIG_DCD); + if ((sig & UART_SIG_DCTS) && (tp->t_cflag & CCTS_OFLOW) && + !sc->sc_hwoflow) { + if (sig & UART_SIG_CTS) { + tp->t_state &= ~TS_TTSTOP; + (*linesw[tp->t_line].l_start)(tp); + } else + tp->t_state |= TS_TTSTOP; + } } if (pend & UART_IPEND_TXIDLE) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200309030946.h839k6VT068477>