PERFORCE change 37439 for review
Marcel Moolenaar
marcel at FreeBSD.org
Wed Sep 3 02:46:08 PDT 2003
http://perforce.freebsd.org/chv.cgi?CH=37439
Change 37439 by marcel at 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) {
More information about the p4-projects
mailing list