[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: MiNT 1.11 BETA



In <9408131636.AA00124@jelal.north.de> i wrote:

>there is a #define MDM0_IOCTLS in tty.c, if you leave that in you can
>use the stty that comes with mdm0 to change local mode and hupcl until
>i have patches for mintlib etc.

ok GNU shellutils stty compiles now...  i also patched a few more things
in the kernel, the lib diffs are at the end.  stty still sometimes
complains `unable to perform all requested operations' because mintlibs
termios is only an emulation and some settings cannot be changed without
affecting others, or are only available on some ttys, or not at all.
(like what should brkint do on the console?  and MiNT is so 8-bit-clean
it doesn't even have anything like istrip... etc.)  but i don't think
many other programs will have real problems because of that now, or even
notice it...

first some more bugfixes (sorry :)

Index: biosfs.c
@@ -1700,7 +1739,7 @@
 		}
 	}
 
-	if (t->tty->state & TS_BLIND)
+	if (t && (t->tty->state & TS_BLIND))
 		/* line disconnected... */
 		return 0;
 
@@ -1959,14 +1998,14 @@
 			oflags |= (ucr & 0x2) ? T_EVENP : T_ODDP;
 		}
 		if ((long)flags >= 0) {
-			if ((mask & (T_RTSCTS|T_TANDEM)) == T_RTSCTS|T_TANDEM) {
+			if ((mask & (T_RTSCTS|T_TANDEM)) == (T_RTSCTS|T_TANDEM)) {
 				flow = (flags & (T_RTSCTS|T_TANDEM)) >> 12L;
 			} else {
 				flow = -1;
 				flags = (flags & ~(T_RTSCTS|T_TANDEM)) |
 					(oflags & (T_RTSCTS|T_TANDEM));
 			}
-			if ((mask & (T_EVENP|T_ODDP)) == T_EVENP|T_ODDP) {
+			if ((mask & (T_EVENP|T_ODDP)) == (T_EVENP|T_ODDP)) {
 				if (flags & T_EVENP) {
 					ucr |= 0x6;
 					flags &= ~T_ODDP;
Index: tty.c
@@ -677,6 +680,7 @@
 	    {
 		unsigned long bits[2];
 		static unsigned short v[] = {1, 0};
+		unsigned short oflags = tty->sg.sg_flags;
 
 		sg = (struct sgttyb *)arg;
 		tty->sg = *sg;
@@ -686,6 +690,9 @@
 		} else {
 			tty->state |= TS_COOKED;
 		}
+		if (!(sg->sg_flags & T_XKEY)) {
+			tty->state &= ~TS_ESC;
+		}
 	/* set baud rates */
 		baud = tosbaud(sg->sg_ispeed);
 		(*f->dev->ioctl)(f, TIOCIBAUD, &baud);
@@ -706,12 +713,16 @@
 		if (!(sg->sg_flags & T_RAW) || (sg->sg_flags & T_ECHO))
 			flags |= TF_BRKINT;
 	/* leave local mode bit alone */
-		bits[0] = flags; bits[1] = ~TF_CAR;
+		bits[0] = (unsigned)flags; bits[1] = ~TF_CAR;
 		if ((*f->dev->ioctl)(f, TIOCSFLAGSB, &bits) >= 0)
 			return 0;
 	/* if TIOCSFLAGSB failed clear TF_CAR, assume the device doesn't
 	 * know about carrier anyway... */
-		(*f->dev->ioctl)(f, TIOCSFLAGS, &flags);
+		if ((*f->dev->ioctl)(f, TIOCSFLAGS, &flags) >= 0)
+			return 0;
+	/* cannot set flags, don't save them */
+		tty->sg.sg_flags = (tty->sg.sg_flags & ~TF_FLAGS)|
+						(oflags & TF_FLAGS);
 		return 0;
 	    }
 	case TIOCGETC:
###
improve /dev/midi performance, add a bios_tty struct so reads can
go to sleep and use VMIN etc, allow writes to busy-wait for 2 hz_200
ticks before a yield (BIOS midi writes are not interrupt driven,
only reads...)  fix select for write, always return true unless
TS_HOLD (same reason, there is nothing that would wake them and
since there is no other kind of flow control...)  and inc aux_cnt
in main so a `normal' open /dev/midi gets a re-initialized tty like
on other ports.

of course you'll still never get the full 3125 cps out without a
send buffer, and of course since there is no real flow control and
the ST's mouse interrupt is also still broken (causes midi receiver
overruns) you'll still lose chars if you don't make the receiver
buffer big enough or touch the mouse at the `wrong' moment.  but it
should be good enough for a simple uucp connection or a login, if
your editor understands ^L... :)

Index: bios.c
@@ -33,7 +33,7 @@
 
 /* tty structures for the BIOS devices -- see biosfs.c */
 extern struct tty con_tty, aux_tty, midi_tty, sccb_tty, scca_tty, ttmfp_tty;
-extern struct bios_tty bttys[];
+extern struct bios_tty bttys[], midi_btty;
 extern short btty_max;
 
 extern int tosvers;	/* from main.c */
@@ -340,6 +340,23 @@
 	for (b=bttys;b<bttys+btty_max;b++) {
 		checkbtty(b, 1);
 	}
+	b=&midi_btty;
+	if (!b->vticks || _hz_200 - b->vticks > 0) {
+		long r, *l;
+
+		if ((r = (long)b->tty->vmin - ionread(b->irec)) <= 0) {
+			b->vticks = 0;
+			wake(IO_Q, (long)b);
+			l = b->rsel;
+			if (*l)
+				wakeselect(*l);
+		} else if ((--r, r *= 2000L) > (unsigned long)31250) {
+			b->vticks = _hz_200 + (r/(unsigned long)31250);
+			if (!b->vticks)
+				b->vticks = 1;
+		} else
+			b->vticks = 0;
+	}
 }
 
 void
@@ -457,8 +474,8 @@
 		} else
 			h = dev-SERDEV;
 
-		if ((unsigned)h < btty_max) {
-			if (has_bconmap) {	/* help the compiler... :) */
+		if ((unsigned)h < btty_max || dev == 3) {
+			if (has_bconmap && dev != 3) {	/* help the compiler... :) */
 				long *statc;
 
 				while (!callout1(*(statc=&MAPTAB[dev-SERDEV].bconstat), dev))
@@ -466,7 +483,8 @@
 				return callout1(statc[1], dev);
 			}
 			while (!BCONSTAT(dev))
-				sleep(IO_Q, (long)&bttys[h]);
+				sleep(IO_Q, (long)(dev == 3 ? &midi_btty :
+								&bttys[h]));
 		} else if (dev > 0) {
 			unsigned long tick;
 
Index: biosfs.c
@@ -208,7 +208,7 @@
 		 ((has_bconmap && (unsigned)(f)->fc.aux-6 < btty_max) ? \
 		    bttys+(f)->fc.aux-6 : 0))
 
-struct bios_tty bttys[MAX_BTTY];
+struct bios_tty bttys[MAX_BTTY], midi_btty;
 short	btty_max;
 
 /* RSVF cookie value (read in main.c) */
@@ -403,6 +403,15 @@
 	}
 	btty_max = i;
 
+	midi_btty.irec = Iorec(2);
+	midi_btty.rsel = &midi_tty.rsel;
+	midi_btty.wsel = &midi_tty.wsel;
+	midi_btty.tty = &midi_tty;
+	midi_tty = default_tty;
+	midi_btty.clocal = 1;
+	midi_btty.tosfd = EUNDEV;
+	midi_btty.bdev = 3;
+
 	defaultaux = new_fileptr();
 	defaultaux->links = 1;		/* so it never gets freed */
 	defaultaux->flags = O_RDWR;
@@ -1462,6 +1471,34 @@
 	const char *p = buf;
 	int slept = 0;
 
+#if 1
+#define _hz_200 (*((long *)0x4baL))
+
+	if (bdev == 3 && tosvers >= 0x0102) {
+		/* midi */
+		long ret = 0, tick = _hz_200 + 1;
+
+		cout = &xconout[3];
+		while (bytes > 0) {
+			while (!(int)callout1(xcostat[4], 4)) {
+				if (ndelay)
+					break;
+				if (_hz_200 - tick > 0) {
+					yield();
+					tick = _hz_200 + 1;
+				}
+			}
+			(void) callout2(*cout, bdev, (unsigned char) *p++);
+			bytes--;
+		}
+		if (ret > 0) {
+			b->xattr.mtime = b->xattr.atime = timestamp;
+			b->xattr.mdate = b->xattr.adate = datestamp;
+		}
+		return p - buf;
+	}
+#endif
+
 	if (has_bconmap) {
 		if ((unsigned)bdev-6 < btty_max) {
 			ior = MAPTAB[bdev-6].iorec + 1;
@@ -1662,7 +1699,8 @@
 
 	if (bdev == 3 && tosvers >= 0x0102) {
 		/* midi */
-		ior = (IOREC_T *) uiorec(2);
+		t = &midi_btty;
+		ior = t->irec;
 		cin = &xconin[3];
 		cinstat = &xconstat[3];
 	} else if (has_bconmap) {
@@ -1691,7 +1729,8 @@
 	 */
 	if (buf && !ndelay) {
 		while (t ? (!(t->tty->state & TS_BLIND) &&
-			    btty_ionread(t) < (long)t->tty->vmin)
+			    (bdev == 3 ? ionread(ior) :
+					btty_ionread(t)) < (long)t->tty->vmin)
 			 : !(int)callout1(*cinstat, bdev)) {
 			if (t)
 				sleep(IO_Q, (long)t);
@@ -2029,6 +2068,8 @@
 	case FIONREAD:
 		if (t)
 			*r = btty_ionread(t);
+		else if (f->fc.aux == 3)
+			*r = ionread(midi_btty.irec);
 		else if (bconstat(f->fc.aux))
 			*r = 1;
 		else
@@ -2084,7 +2125,7 @@
 		} else if (dev == 3 || dev == 2 || dev == 5) {
 			if (dev == 3) {
 				/* midi */
-				ior = (IOREC_T *) uiorec(2);
+				ior = midi_btty.irec;
 			} else {
 				/* ikbd */
 				ior = (IOREC_T *) uiorec(1);
@@ -2248,6 +2289,8 @@
 		unsigned short *v = buf;
 		struct tty *tty = (struct tty *)f->devinfo;
 
+		if (f->fc.aux == 3)
+			t = &midi_btty;
 		if (!tty || !t)
 			return EINVFN;
 		if (mode == TIOCGVMIN) {
@@ -2375,10 +2418,11 @@
 	int dev = f->fc.aux;
 
 	if (mode == O_RDONLY) {
-		struct bios_tty *t;
-		if (tty && ((t = BTTY(f)))) {
+		struct bios_tty *t = &midi_btty;
+		if (tty && (dev == 3 || ((t = BTTY(f))))) {
 			if (!(tty->state & TS_BLIND) &&
-			    btty_ionread(t) >= (long)tty->vmin) {
+			    (dev == 3 ? ionread(t->irec) :
+					btty_ionread(t)) >= (long)tty->vmin) {
 				return 1;
 			}
 		} else if (bconstat(dev)) {
@@ -2394,7 +2438,7 @@
 		return 0;
 	} else if (mode == O_WRONLY) {
 		if ((!tty || !(tty->state & (TS_BLIND|TS_HOLD))) &&
-		    bcostat(dev)) {
+		    (dev == 3 || bcostat(dev))) {
 			TRACE(("bios_select: ready to output on %d", dev));
 			return 1;
 		}
Index: main.c
@@ -852,6 +852,8 @@
 	if (f) {
 		f = do_open("U:\\DEV\\MIDI", O_RDWR, 0, (XATTR *)0);
 		curproc->midiin = curproc->midiout = f;
+		((struct tty *)f->devinfo)->aux_cnt = 1;
+		f->pos = 1;	/* flag for close to --aux_cnt */
 		f->links = 2;
 	}
 
###
and use t_flushc, default ^o. (or should UNDEF still be default i.e. == off?)

Index: tty.c
@@ -56,7 +56,7 @@
 	CTRL('Z'),		/* suspend */
 	CTRL('Y'),		/* suspend after read */
 	CTRL('R'),		/* reprint */
-	UNDEF,			/* flush output */
+	CTRL('O'),		/* flush output */
 	CTRL('W'),		/* erase word */
 	CTRL('V')		/* quote next char */
 	},
@@ -273,6 +273,9 @@
 				}
 				continue;
 			}
+			else if ((char)ch == tty->ltc.t_flushc) {
+				continue;
+			}
 			else if (ch == '\n' || (char)ch == tty->tc.t_brkc) {
 				put(f, '\r');
 				if (!(mode & T_TOS)) {
@@ -1177,6 +1188,11 @@
 				tty_ioctl (f, TIOCSTART, 0);
 				return 4L;
 			}
+			else if (ch == tty->ltc.t_flushc) {
+				long r = 2;
+				tty_ioctl (f, TIOCFLUSH, &r);
+				return 4L;
+			}
 			else if (tty->state & TS_HOLD) {
 				return 0;
 			}
@@ -1224,22 +1240,27 @@
 /* BIOS device definitions */
 #define CONSDEV 2
 			if (f->dev == &bios_tdevice &&
-			    (bdev=f->fc.aux) != CONSDEV && bconstat(bdev)) {
-				long c = bconin(bdev) & 0x7fffffffL;
+			    (bdev=f->fc.aux) != CONSDEV) {
+				long c;
 
-				if (c == UNDEF)
+				if (!bconstat(bdev) ||
+				    (c = bconin(bdev) & 0x7fffffffL) == UNDEF)
 					;	/* do nothing */
 				else if (c == tty->ltc.t_suspc) {
-					tty->state &= ~TS_HOLD;
+					tty_ioctl(f, TIOCSTART, 0);
 					killgroup(tty->pgrp, SIGTSTP);
 				} else if (c == tty->tc.t_intrc) {
-					tty->state &= ~TS_HOLD;
+					tty_ioctl(f, TIOCSTART, 0);
 					killgroup(tty->pgrp, SIGINT);
 				} else if (c == tty->tc.t_quitc) {
-					tty->state &= ~TS_HOLD;
+					tty_ioctl(f, TIOCSTART, 0);
 					killgroup(tty->pgrp, SIGQUIT);
 				} else if (c == tty->tc.t_startc)
-					tty->state &= ~TS_HOLD;
+					tty_ioctl(f, TIOCSTART, 0);
+				else if (c == tty->ltc.t_flushc) {
+					long r = 2;
+					tty_ioctl(f, TIOCFLUSH, &r);
+				}
 			}
 			else
 #endif
###
EOKerneldiffs...

Index: usr/include/ioctl.h
@@ -10,8 +10,7 @@
 #endif
 
 #define TIOCGETP	(('T'<< 8) | 0)
-#define TIOCSETP	(('T'<< 8) | 1)
-#define TIOCSETN	TIOCSETP
+#define TIOCSETN	(('T'<< 8) | 1)
 #define TIOCGETC	(('T'<< 8) | 2)
 #define TIOCSETC	(('T'<< 8) | 3)
 #define TIOCGLTC	(('T'<< 8) | 4)
@@ -40,6 +39,16 @@
 #define TIOCGFLAGS	(('T'<< 8) | 22)
 #define TIOCSFLAGS	(('T'<< 8) | 23)
 #define TIOCOUTQ	(('T'<< 8) | 24)
+#define TIOCSETP	(('T'<< 8) | 25)
+#define TIOCHPCL	(('T'<< 8) | 26)
+#define TIOCCAR		(('T'<< 8) | 27)
+#define TIOCNCAR	(('T'<< 8) | 28)
+#define TIOCWONLINE	(('T'<< 8) | 29)
+#define TIOCSFLAGSB	(('T'<< 8) | 30)
+#define TIOCGSTATE	(('T'<< 8) | 31)
+#define TIOCSSTATEB	(('T'<< 8) | 32)
+#define TIOCGVMIN	(('T'<< 8) | 33)
+#define TIOCSVMIN	(('T'<< 8) | 34)
 
 /* faked by the library */
 #define TIOCLBIS	(('T'<< 8) | 246)
Index: usr/include/termios.h
@@ -14,9 +14,56 @@
 #define VTIME	10
 #define VLNEXT	11		/* <-- Not POSIX */
 #define VWERASE	12		/* <-- Not POSIX */
+#define VDSUSP	13		/* <-- Not POSIX */
+#define VREPRINT 14		/* <-- Not POSIX */
+#define VFLUSHO	15		/* <-- Not POSIX */
+
+#define NCCS	(VFLUSHO + 1)
+
+/* Canonical values for control characters. */
+#ifndef CEOF
+#define	CEOF	('d' & 0x1f)
+#endif
+#ifndef CEOL
+#define	CEOL	('m' & 0x1f)
+#endif
+#ifndef CERASE
+#define	CERASE	('h' & 0x1f)
+#endif
+#ifndef CINTR
+#define	CINTR	('c' & 0x1f)
+#endif
+#ifndef CKILL
+#define	CKILL	('u' & 0x1f)
+#endif
+#ifndef CQUIT
+#define	CQUIT	28
+#endif
+#ifndef CSUSP
+#define	CSUSP	('z' & 0x1f)
+#endif
+#ifndef CSTART
+#define	CSTART	('q' & 0x1f)
+#endif
+#ifndef CSTOP
+#define	CSTOP	('s' & 0x1f)
+#endif
+#ifndef CLNEXT
+#define	CLNEXT	('v' & 0x1f)
+#endif
+#ifndef CWERASE
+#define	CWERASE	('w' & 0x1f)
+#endif
+#ifndef CDSUSP
+#define	CDSUSP	('y' & 0x1f)
+#endif
+#ifndef CRPRNT
+#define	CRPRNT	('r' & 0x1f)
+#endif
+#ifndef CFLUSHO
+#define CFLUSHO	('o' & 0x1f)
+#endif
 
-#define NCCS	(VWERASE + 1)
-
 typedef unsigned short tcflag_t;
 typedef unsigned short speed_t;
 typedef unsigned char cc_t;
@@ -59,6 +106,7 @@
 #define HUPCL	0x0080
 #define PARENB	0x0100
 #define PARODD	0x0200
+#define CRTSCTS	0x2000		/* <-- Not POSIX(?) */
 
 /* local modes */
 #define ECHOE	0x0001
@@ -103,6 +151,13 @@
 #define _TF_7BIT	0x4
 #define _TF_6BIT	0x8
 #define _TF_5BIT	0xC
+#define _TF_CAR		0x800
+#define _TF_BRKINT	0x80
+
+#define _TS_BLIND	0x800
+#define _TS_HOLD	0x1000
+#define _TS_HPCL	0x4000
+#define _TS_COOKED	0x8000
 
 /* baud rate codes */
 #ifndef _IOCTL_H
Index: ioctl.c
@@ -155,6 +167,14 @@
                 return -1;
                 break;
 	      }
+	    case TIOCSETP:
+	      if (__mint <= 0x10a) {
+		r = Fcntl(fd, arg, cmd);
+		if (r != -EINVAL)
+		  break;
+		cmd = TIOCSETN;
+	      }
+	      /*FALLTHRU*/
 	    default:
 	      r = Fcntl(fd, arg, cmd);
 	      break;
Index: tcattr.c
@@ -5,6 +5,7 @@
 
 #include <mintbind.h>
 #include <types.h>
+#include <param.h>
 #include <errno.h>
 #include <file.h>
 #include <ioctl.h>
@@ -12,6 +13,8 @@
 #include <types.h>
 #include <termios.h>
 
+#define VTIME_MS	(1000/HZ)
+
 int
 tcgetattr(fd, stp)
   int fd;
@@ -21,7 +24,8 @@
   struct tchars t;
   struct ltchars lt;
   short flags;
-  long r;
+  unsigned short vmin[2];
+  long state, r;
 
   r = Fcntl((short) fd, (long) &sg, TIOCGETP);
   if (r < 0) {
@@ -42,13 +46,22 @@
   if (r < 0) {
     flags = 0;
   }
-  stp->c_iflag = (tcflag_t) (IGNBRK
+  r = Fcntl((short) fd, (long) &state, TIOCGSTATE);
+  if (r < 0) {
+    state = 0;
+  }
+  stp->c_iflag = (tcflag_t) (((flags & _TF_BRKINT) ? BRKINT : 0)
 			| ((sg.sg_flags & CRMOD) ? ICRNL : 0)
-			| ((sg.sg_flags & (EVENP | ODDP)) ? INPCK : IGNPAR)
-			| ((sg.sg_flags & TANDEM) ? (IXON | IXOFF) : 0));
-  stp->c_oflag = (tcflag_t) OPOST;
-  stp->c_cflag = (tcflag_t) (CLOCAL | CREAD
+			| ((sg.sg_flags & (EVENP | ODDP)) ? INPCK :
+			 ((sg.sg_flags & RAW) ? 0 : IGNPAR)) /*keep stty happy*/
+			| ((sg.sg_flags & TANDEM) ? (IXON | IXOFF) : 0)
+			| ((sg.sg_flags & RAW) ? 0 : IXON));
+  stp->c_oflag = (tcflag_t) (sg.sg_flags & RAW) ? 0 : OPOST;
+  stp->c_cflag = (tcflag_t) (CREAD
+			| ((flags & _TF_CAR) ? 0 : CLOCAL)
+			| ((state & _TS_HPCL) ? HUPCL : 0)
 			| (((flags & _TF_STOPBITS) == _TF_2STOP) ? CSTOPB : 0)
+			| ((sg.sg_flags & RTSCTS) ? CRTSCTS : 0)
 			| ((sg.sg_flags & EVENP) ? PARENB : 0)
 			| ((sg.sg_flags & ODDP) ? (PARENB | PARODD) : 0));
   switch (flags & _TF_CHARBITS)
@@ -84,10 +97,19 @@
   stp->c_cc[VSUSP]	= (cc_t) lt.t_suspc;
   stp->c_cc[VSTART]	= (cc_t) t.t_startc;
   stp->c_cc[VSTOP]	= (cc_t) t.t_stopc;
-  stp->c_cc[VMIN]	= (cc_t) 1;
-  stp->c_cc[VTIME]	= (cc_t) 0;
+  r = Fcntl((short) fd, (long) &vmin, TIOCGVMIN);
+  if (r < 0) {
+    stp->c_cc[VMIN]	= (cc_t) 1;
+    stp->c_cc[VTIME]	= (cc_t) 0;
+  } else {
+    stp->c_cc[VMIN]	= (cc_t) (vmin[0] >= 0xff) ? 0xff : vmin[0];
+    stp->c_cc[VTIME]	= (cc_t) (vmin[1] >= 0xff*VTIME_MS) ? 0xff : vmin[1]/VTIME_MS;
+  }
   stp->c_cc[VLNEXT]	= (cc_t) lt.t_lnextc;
   stp->c_cc[VWERASE]	= (cc_t) lt.t_werasc;
+  stp->c_cc[VDSUSP]	= (cc_t) lt.t_dsuspc;
+  stp->c_cc[VREPRINT]	= (cc_t) lt.t_rprntc;
+  stp->c_cc[VFLUSHO]	= (cc_t) lt.t_flushc;
   return 0;
 }
 
@@ -100,8 +122,9 @@
   struct sgttyb sg;
   struct tchars t;
   struct ltchars lt;
-  short flags;
-  long r;
+  short flags, state;
+  unsigned short vmin[2];
+  long bits[2], r;
 
   r = Fcntl((short) fd, (long) &sg, TIOCGETP);
   if (r < 0) {
@@ -113,16 +136,15 @@
     errno = (int) -r;
     return -1;
   }
-  r = Fcntl((short) fd, (long) &flags, TIOCGFLAGS);
-  if (r < 0) {
-    flags = 0;
-  }
-  sg.sg_flags &= ~(CRMOD | TANDEM | EVENP | ODDP | TOSTOP 
+  sg.sg_flags &= ~(CRMOD | TANDEM | RTSCTS | EVENP | ODDP | TOSTOP 
 			| NOFLSH | RAW | CBREAK | ECHO | XKEY);
-  flags &= ~(_TF_STOPBITS | _TF_CHARBITS);
   sg.sg_flags |= (((stp->c_iflag & ICRNL) ? CRMOD : 0)
-			| ((stp->c_iflag & (IXON | IXOFF)) ? TANDEM : 0));
-  flags |= ((stp->c_cflag & CSTOPB) ? _TF_2STOP : _TF_1STOP);
+			| (((stp->c_iflag & (IXON | IXOFF)) == (IXON | IXOFF)) ? TANDEM : 0)
+			| ((stp->c_cflag & CRTSCTS) ? RTSCTS : 0));
+  flags = ((stp->c_cflag & CSTOPB) ? _TF_2STOP : _TF_1STOP) |
+		((stp->c_cflag & CLOCAL) ? 0 : _TF_CAR) |
+		((stp->c_iflag & BRKINT) ? _TF_BRKINT : 0);
+  state = (stp->c_cflag & HUPCL) ? _TS_HPCL : 0;
   sg.sg_flags |= ((stp->c_cflag & PARENB)
 			? ((stp->c_cflag & PARODD) ? ODDP : EVENP)
 			: 0);
@@ -157,8 +179,13 @@
   lt.t_suspc		= (char) stp->c_cc[VSUSP];
   t.t_startc		= (char) stp->c_cc[VSTART];
   t.t_stopc		= (char) stp->c_cc[VSTOP];
+  vmin[0]		= (unsigned char) stp->c_cc[VMIN] ? stp->c_cc[VMIN] : 1;
+  vmin[1]		= (unsigned short) stp->c_cc[VTIME] * VTIME_MS;
   lt.t_lnextc		= (char) stp->c_cc[VLNEXT];
   lt.t_werasc		= (char) stp->c_cc[VWERASE];
+  lt.t_dsuspc		= (char) stp->c_cc[VDSUSP];
+  lt.t_rprntc		= (char) stp->c_cc[VREPRINT];
+  lt.t_flushc		= (char) stp->c_cc[VFLUSHO];
   switch (action)
   {
     case TCSAFLUSH:
@@ -192,6 +219,19 @@
     errno = (int) -r;
     return -1;
   }
-  (void) Fcntl((short) fd, (long) &flags, TIOCSFLAGS);
+  bits[0] = (unsigned)flags;
+  bits[1] = _TF_STOPBITS | _TF_CHARBITS | _TF_CAR | _TF_BRKINT;
+  r = Fcntl((short) fd, (long) &bits, TIOCSFLAGSB);
+  if (r < 0) {
+    short sflags = 0;
+    (void) Fcntl((short) fd, (long) &sflags, TIOCGFLAGS);
+    sflags &= ~(_TF_STOPBITS | _TF_CHARBITS);
+    sflags |= flags & (_TF_STOPBITS | _TF_CHARBITS);
+    (void) Fcntl((short) fd, (long) &flags, TIOCSFLAGS);
+  }
+  (void) Fcntl((short) fd, (long) &vmin, TIOCSVMIN);
+  bits[0] = (unsigned)state;
+  bits[1] = _TS_HPCL;
+  (void) Fcntl((short) fd, (long) &bits, TIOCSSTATEB);
   return 0;
 }