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