Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Aug 2008 18:54:14 GMT
From:      Ed Schouten <ed@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 148734 for review
Message-ID:  <200808281854.m7SIsEwR054477@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=148734

Change 148734 by ed@ed_dull on 2008/08/28 18:53:25

	Already add a first prototype of the packet mode code. This
	means we can now happily use ^S and ^Q while inside screen.

Affected files ...

.. //depot/projects/mpsafetty/sys/kern/tty.c#34 edit
.. //depot/projects/mpsafetty/sys/kern/tty_pts.c#18 edit
.. //depot/projects/mpsafetty/sys/sys/ttydevsw.h#6 edit

Differences ...

==== //depot/projects/mpsafetty/sys/kern/tty.c#34 (text+ko) ====

@@ -818,7 +818,7 @@
 }
 
 static void
-ttydevsw_defpktnotify(struct tty *tp, int event)
+ttydevsw_defpktnotify(struct tty *tp, char event)
 {
 }
 
@@ -1382,6 +1382,17 @@
 			ttyinq_canonicalize(&tp->t_inq);
 			tty_wakeup(tp, FREAD);
 		}
+
+		/*
+		 * For packet mode: notify the PTY consumer that VSTOP
+		 * and VSTART may have been changed.
+		 */
+		if (tp->t_termios.c_iflag & IXON &&
+		    tp->t_termios.c_cc[VSTOP] == CTRL('S') &&
+		    tp->t_termios.c_cc[VSTART] == CTRL('Q'))
+			ttydevsw_pktnotify(tp, TIOCPKT_DOSTOP);
+		else
+			ttydevsw_pktnotify(tp, TIOCPKT_NOSTOP);
 		return (0);
 	}
 	case TIOCGETD:

==== //depot/projects/mpsafetty/sys/kern/tty_pts.c#18 (text+ko) ====

@@ -82,6 +82,7 @@
 	int		pts_unit;	/* (c) Device unit number. */
 	unsigned int	pts_flags;	/* (t) Device flags. */
 #define PTS_PKT		0x1	/* Packet mode. */
+	char		pts_pkt;	/* (t) Unread packet mode data. */
 
 	struct cv	pts_inwait;	/* (t) Blocking write() on master. */
 	struct selinfo	pts_inpoll;	/* (t) Select queue for write(). */
@@ -105,34 +106,54 @@
 {
 	struct tty *tp = fp->f_data;
 	struct pts_softc *psc = tty_softc(tp);
-	int error, oresid;
+	int error = 0;
+	char pkt;
 
 	if (uio->uio_resid == 0)
 		return (0);
-	
-	/*
-	 * Implement packet mode. When packet mode is turned on, the
-	 * first byte contains a bitmask of events that occured (start,
-	 * stop, flush, window size, etc).
-	 */
+
+	tty_lock(tp);
+
+	for (;;) {
+		/*
+		 * Implement packet mode. When packet mode is turned on,
+		 * the first byte contains a bitmask of events that
+		 * occured (start, stop, flush, window size, etc).
+		 */
+		if (psc->pts_flags & PTS_PKT && psc->pts_pkt) {
+			pkt = psc->pts_pkt;
+			psc->pts_pkt = 0;
+			tty_unlock(tp);
 
-	if (psc->pts_flags & PTS_PKT) {
-		/* XXX: return proper bits. */
-		error = ureadc(0, uio);
-		if (error != 0)
+			error = ureadc(pkt, uio);
 			return (error);
-		if (uio->uio_resid == 0)
-			return (0);
-	}
+		}
+
+		/*
+		 * Transmit regular data.
+		 *
+		 * XXX: We shouldn't use ttydisc_getc_poll()! Even
+		 * though in this implementation, there is likely going
+		 * to be data, we should just call ttydisc_getc_uio()
+		 * and use its return value to sleep.
+		 */
+		if (ttydisc_getc_poll(tp)) {
+			if (psc->pts_flags & PTS_PKT) {
+				/*
+				 * XXX: Small race. Fortunately PTY
+				 * consumers aren't multithreaded.
+				 */
 
-	oresid = uio->uio_resid;
+				tty_unlock(tp);
+				error = ureadc(TIOCPKT_DATA, uio);
+				if (error)
+					return (error);
+				tty_lock(tp);
+			}
 
-	tty_lock(tp);
-	for (;;) {
-		error = ttydisc_getc_uio(tp, uio);
-		/* We've got data (or an error). */
-		if (error != 0 || uio->uio_resid != oresid)
+			error = ttydisc_getc_uio(tp, uio);
 			break;
+		}
 
 		/* Maybe the device isn't used anyway. */
 		if (tty_opened(tp) == 0)
@@ -147,6 +168,7 @@
 		if (error != 0)
 			break;
 	}
+
 	tty_unlock(tp);
 
 	return (error);
@@ -367,7 +389,8 @@
 
 	if (events & (POLLIN|POLLRDNORM)) {
 		/* See if we can getc something. */
-		if (ttydisc_getc_poll(tp))
+		if (ttydisc_getc_poll(tp) ||
+		    (psc->pts_flags & PTS_PKT && psc->pts_pkt))
 			revents |= events & (POLLIN|POLLRDNORM);
 	}
 	if (events & (POLLOUT|POLLWRNORM)) {
@@ -486,8 +509,31 @@
 }
 
 static void
-ptsdrv_pktnotify(struct tty *tp, int event)
+ptsdrv_pktnotify(struct tty *tp, char event)
 {
+	struct pts_softc *psc = tty_softc(tp);
+
+	/*
+	 * Clear conflicting flags.
+	 */
+
+	switch (event) {
+	case TIOCPKT_STOP:
+		psc->pts_pkt &= ~TIOCPKT_START;
+		break;
+	case TIOCPKT_START:
+		psc->pts_pkt &= ~TIOCPKT_STOP;
+		break;
+	case TIOCPKT_NOSTOP:
+		psc->pts_pkt &= ~TIOCPKT_DOSTOP;
+		break;
+	case TIOCPKT_DOSTOP:
+		psc->pts_pkt &= ~TIOCPKT_NOSTOP;
+		break;
+	}
+
+	psc->pts_pkt |= event;
+	ptsdrv_outwakeup(tp);
 }
 
 static void

==== //depot/projects/mpsafetty/sys/sys/ttydevsw.h#6 (text+ko) ====

@@ -48,7 +48,7 @@
 typedef int tsw_param_t(struct tty *, struct termios *);
 typedef int tsw_modem_t(struct tty *, int, int);
 typedef int tsw_mmap_t(struct tty *, vm_offset_t, vm_paddr_t *, int);
-typedef void tsw_pktnotify_t(struct tty *, int);
+typedef void tsw_pktnotify_t(struct tty *, char);
 typedef void tsw_free_t(void *);
 
 struct ttydevsw {
@@ -150,7 +150,7 @@
 }
 
 static __inline void
-ttydevsw_pktnotify(struct tty *tp, int event)
+ttydevsw_pktnotify(struct tty *tp, char event)
 {
 	tty_lock_assert(tp, MA_OWNED);
 	MPASS(!tty_gone(tp));



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200808281854.m7SIsEwR054477>