Subject: com driver patches and enhancements
To: None <netbsd-bugs@sun-lamp.cs.berkeley.edu>
From: Hannes Deeken <hannes@flinx.RoBIN.de>
List: netbsd-bugs
Date: 01/24/1994 23:03:50
Hi!

I've done some hacking on the com driver in NetBSD 0.9, and like to
share the results. The following patches add handling of the DCD and CTS
lines, call units and enabling RTS flowcontrol.
I don't claim these patches to be the latest and greatest in driver design
(they're clearly not), but they provided me with a way to allow people to
dial into my machine and fetch their news and mail. So please route flames to
/dev/null.

------------------------------ snip ------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README com.c-diff termios.h-diff ttydefaults.h-diff
# Wrapped by hannes@flinx.RoBIN.de on Mon Jan 24 22:56:03 1994
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(5177 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XWhat is this?
X-------------
X
XThese patches for the serial driver in NetBSD 0.9 enable carrier detection,
Xhardware flowcontrol (at least a bit :), and separate devices for dialing
Xin and out ("calling units").
X
XThis is the second release of these patches.
X
X
XWarranty
X--------
XNone. Use at your own risk. If this software causes you headache, peptic
Xulcer, loss of money, health or life, don't blame me.
XIt works for me. That doesn't mean that it works for you. But you have
Xa good chance (IMHO).
XThe code may be a hack, ugly and buggy as hell, but in my eyes it is
Xat least more functional than the original serial driver in NetBSD 0.9.
X
X
XHow do I use it?
X----------------
X
XSave the files 
X	/sys/arch/i386/isa/com.c
X	/sys/sys/termios.h
X	/sys/sys/ttydefaults.h
Xso you can later restore these files in case the patches don't work for you.
X(If you want your system to keep 7 databits and even parity as
Xdefault mode on your ttys, don't use the patch for ttydefaults.h)
X
XThen run the patches through 'patch -p0'. If you didn't change the files
Xmentioned above before, there should be no rejects. 
X
XNext, go to /usr/src/include and do a 'make install'. This either copies
Xthe files from /sys/sys to /usr/include/sys or creates the necessary symlinks.
XEither way, the patched header files are accessible in /usr/include/sys 
Xafterwards.
X
XIf you want to enable the added features, go to /sys/arch/i386/conf
Xand edit the config file for your system.
XTo enable the calling unit code, add 'option COM_BIDIR' at the
Xbeginning of the file.
XFeatures are enabled via the 'flags' field on the 'device' line for
Xthe serial ports. The possible values are:
X
X    0x1 -- set CRTSCTS on this port as default (hardware flowcontrol)
X    0x2 -- set CLOCAL on this port as default (open succeeds without carrier)
X    0x4 -- this port is used for dial-in and -out. Enable calling unit.
X
XIf you want several features on one port, add these values. For example,
Xthe configuration for my modem port:
X
X>device		com3	at isa? port 0x3e0 tty irq 5 flags 0x5 vector comintr
X                                                     ^^^^^^^^^ 
XHere we have hardware flowcontrol [= 0x1] and enabled calling unit [= 0x5].
X
X
XAfter changing your config file, do a 'config <YOUR-CONFIG>', rebuild
Xyour kernel, save your old kernel, install the new one and reboot.
X
XIf you enabled calling units, you need to create the devices for them.
XThe major device number is the same as for the regular tty devices (8 on
Xmy system), and the minor number is the minor number for the associated
Xtty plus 128.
X
XExample:
X	If you enabled the calling unit for com3, you need to create
X	/dev/cua03 in addition to your already existing /dev/tty03.
X	Let's take a look at tty03's major and minor number:
X
X	crw-------    1 root       8,   3 Jan  9 18:46 /dev/tty03
X
X	Ok, the major number is 8, and the minor number is 3.
X	So the minor number for /dev/cua03 is 131 (3 + 128).
X	Now you do a 'mknod /dev/cua03 c 8 131' and you're done.
X
X
XNow you can put a getty on /dev/tty03 for dialing in, and dial out
Xvia /dev/cua03, without interferring with getty.
X
XIf you want a 8-bit clean data path into your system, recompile and
Xre-install getty (so it uses the new definitions in ttydefaults.h).
X
X
XWhat are these patches adding/changing?
X---------------------------------------
X
XThe patch to com.c adds separate devices for dial-in and -out, a setable
Xdelay in comclose() to ensure that DTR is low long enough to make a modem
X(at least mine :) hang up the phone and a way to set CRTSCTS and/or CLOCAL
Xon a port permanently (surviving the last close :).
XIt changes the existing code to set DTR and RTS when the port speed is
Xchanged away from 0 (so you can drop DTR by setting the speed to 0 and get
Xit back up when you restore the speed setting), makes the
XTIOCM{GET,SET,BIS,BIC) ioctls use the proper values (TIOCM_{DTR,RTS,CTS,RI,LE})
Xfor getting and setting the port state (as a side effect enabling the RTS
Xflowcontrol) and prevents comstart() from sending anything if hardware
Xflowcontrol is enabled and CTS is not asserted.
X
XThe patch to termios.h changes the definition of CRTSCTS to include _both_
Xdirections of flowcontrol (CCTS_OFLOW | CRTS_IFLOW), so the upper layer of
Xthe tty system knows when to do RTS handling.
X
XThe patch to ttydefaults.h changes the default settings for the system
X(BEWARE: this affects _all_ tty devices, not only serial ports!) from
X7 databits, even parity to 8 databits, no parity. To get a 8-bit clean
Xpath into your system, you have to make a new getty binary (so the new
Xttydefaults.h gets used).
X
X
XKnown bugs
X----------
XNone at the moment. But you surely will tell me ;-)
X
X
XCredits
X-------
X
XThanks go to Chris Demetriou, whose patches to the com driver in 386BSD
Xwere my starting point, and who initially wrote most of the code you find
Xin these patches. Without his work, these patches wouldn't exist.
X
X
XContact
X-------
X
XIf you have questions, criticism, bug reports or fixes, or enhancements,
Xsend me mail.
X
XHave fun,
XHannes
X-- 
XHans-Christoph Deeken | hannes@flinx.{RoBIN.de,hotb.sub.org} (home)
XJungfernstrasse 34    | deeken@iti.informatik.th-darmstadt.de (university)
X64291 Darmstadt       | IRC: Glenlivet
END_OF_FILE
if test 5177 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'com.c-diff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'com.c-diff'\"
else
echo shar: Extracting \"'com.c-diff'\" \(17429 characters\)
sed "s/^X//" >'com.c-diff' <<'END_OF_FILE'
X*** com.c-dist	Thu Aug 26 22:46:23 1993
X***************
X*** 40,45 ****
X--- 40,53 ----
X   * COM driver, based on HP dca driver
X   * uses National Semiconductor NS16450/NS16550AF UART
X   */
X+ 
X+ /*
X+  * Hacked by Hans-Chr. Deeken <hannes@flinx.RoBIN.de>
X+  * to provide DCD & CTS recognition and call units.
X+  * Much of the code for this is taken from Chris G. Demetrious
X+  * patches for the com driver in 386BSD.
X+  */
X+ 
X  #include "param.h"
X  #include "systm.h"
X  #include "ioctl.h"
X***************
X*** 65,73 ****
X--- 73,100 ----
X  	comprobe, comattach, "com"
X  };
X  
X+ /* how long to hold DTR down on close (* 1/HZ) */
X+ #ifndef COM_DTRWAIT
X+ #define COM_DTRWAIT 50
X+ #endif /* COM_DTRWAIT */
X+ 
X+ #ifdef COM_BIDIR
X+ struct com_bidir_info {
X+       int     bidir;      /* is this unit bidirectional? */
X+       int     active;     /* is the port active _at all_? */
X+       int     active_in;  /* is the incoming port in use? */
X+       int     active_out; /* is the outgoing port in use? */
X+       int     fake_dcd;   /* should we fake DCD for now? */
X+ };
X+  
X+ struct com_bidir_info com_bdi[NCOM];
X+ #endif /* COM_BIDIR */
X+ 
X  int	comsoftCAR;
X  int	com_active;
X  int	com_hasfifo;
X+ int	com_setlocal;
X+ int	com_sethwflow;
X  int	ncom = NCOM;
X  #ifdef COMCONSOLE
X  int	comconsole = COMCONSOLE;
X***************
X*** 79,84 ****
X--- 106,113 ----
X  int	commajor;
X  short com_addr[NCOM];
X  struct	tty *com_tty[NCOM];
X+ short com_use[NCOM];	/* usage counter [not really used at the moment] */
X+ u_char com_mstat[NCOM];	/* modem status bits */
X  
X  struct speedtab comspeedtab[] = {
X  	0,	0,
X***************
X*** 110,117 ****
X--- 139,156 ----
X  extern int kgdb_debug_init;
X  #endif
X  
X+ #ifdef COM_BIDIR
X+ #define	COM_UNITMASK	0x7f
X+ #define	COM_CALLOUTMASK	0x80
X+ 
X+ #define	UNIT(x)		(minor(x) & COM_UNITMASK)
X+ #define	CALLOUT(x)	(minor(x) & COM_CALLOUTMASK)
X+ #else
X  #define	UNIT(x)		(minor(x))
X+ #endif /* COM_BIDIR */
X  
X+ #define get_msr(unit,addr) (com_mstat[unit] = inb(addr+com_msr))
X+ 
X  comprobe(dev)
X  struct isa_device *dev;
X  {
X***************
X*** 132,144 ****
X  	struct	tty	*tp;
X  	u_char		unit;
X  	int		port = isdp->id_iobase;
X  
X! 	unit = isdp->id_unit;
X  	if (unit == comconsole)
X  		DELAY(1000);
X  	com_addr[unit] = port;
X  	com_active |= 1 << unit;
X! 	comsoftCAR |= 1 << unit;	/* XXX */
X  
X  	/* look for a NS 16550AF UART with FIFOs */
X  	outb(port+com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4);
X--- 171,189 ----
X  	struct	tty	*tp;
X  	u_char		unit;
X  	int		port = isdp->id_iobase;
X+ 	int		is_bidir = 0;
X  
X! 	unit = UNIT(isdp->id_unit);
X  	if (unit == comconsole)
X  		DELAY(1000);
X  	com_addr[unit] = port;
X  	com_active |= 1 << unit;
X! 	if (isdp->id_flags & 0x1)	/* 0x1 -> CRTSCTS as default */
X! 		com_sethwflow |= 1 << unit;
X! 	if (isdp->id_flags & 0x2)	/* 0x2 -> CLOCAL as default */
X! 		com_setlocal |= 1 << unit;
X! 	if (isdp->id_flags & 0x4)	/* 0x4 -> separate tty/cua devices */
X! 		is_bidir = 1;
X  
X  	/* look for a NS 16550AF UART with FIFOs */
X  	outb(port+com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4);
X***************
X*** 149,156 ****
X  	}
X  
X  	outb(port+com_ier, 0);
X! 	outb(port+com_mcr, 0 | MCR_IENABLE);
X! #ifdef KGDB
X  	if (kgdb_dev == makedev(commajor, unit)) {
X  		if (comconsole == unit)
X  			kgdb_dev = -1;	/* can't debug over console port */
X--- 194,203 ----
X  	}
X  
X  	outb(port+com_ier, 0);
X! 	inb(port+com_msr);	/* Clear delta bits in MSR */
X! 	inb(port+com_lsr);	/* Clear error bits in LSR */
X! 	outb(port+com_mcr, MCR_IENABLE);
X! # ifdef KGDB
X  	if (kgdb_dev == makedev(commajor, unit)) {
X  		if (comconsole == unit)
X  			kgdb_dev = -1;	/* can't debug over console port */
X***************
X*** 176,181 ****
X--- 223,244 ----
X  		comconsinit = 0;
X  		comsoftCAR |= (1 << unit);
X  	}
X+ 
X+ 	/*
X+ 	 * Reset usage counter 
X+ 	 */
X+ 	com_use[unit] = 0;
X+ 
X+ #ifdef COM_BIDIR
X+ 	/*
X+ 	 * if bidirectional ports possible, initialize the bidir port info;
X+ 	 */
X+ 	com_bdi[unit].bidir = is_bidir;
X+ 	com_bdi[unit].active = 0;
X+ 	com_bdi[unit].active_in = com_bdi[unit].active_out = 0;
X+ 	com_bdi[unit].fake_dcd = 0;
X+ #endif /* COM_BIDIR */
X+ 
X  	return (1);
X  }
X  
X***************
X*** 183,198 ****
X  comopen(dev_t dev, int flag, int mode, struct proc *p)
X  {
X  	register struct tty *tp;
X! 	register int unit;
X  	int error = 0;
X   
X- 	unit = UNIT(dev);
X  	if (unit >= NCOM || (com_active & (1 << unit)) == 0)
X  		return (ENXIO);
X  	if(!com_tty[unit]) {
X  		tp = com_tty[unit] = ttymalloc();
X  	} else
X  		tp = com_tty[unit];
X  	tp->t_oproc = comstart;
X  	tp->t_param = comparam;
X  	tp->t_dev = dev;
X--- 246,355 ----
X  comopen(dev_t dev, int flag, int mode, struct proc *p)
X  {
X  	register struct tty *tp;
X! 	register int unit = UNIT(dev);
X! #ifdef COM_BIDIR
X! 	register int callout = CALLOUT(dev);
X! 	register int com = com_addr[unit];
X! #endif /* COM_BIDIR */
X  	int error = 0;
X   
X  	if (unit >= NCOM || (com_active & (1 << unit)) == 0)
X  		return (ENXIO);
X+ 
X+ #ifdef COM_BIDIR
X+ 	/* if it's a callout device, and bidir not possible on that dev, die */
X+ 	if (callout && !(com_bdi[unit].bidir))
X+ 		return (ENXIO);
X+ #endif /* COM_BIDIR */
X+ 
X  	if(!com_tty[unit]) {
X  		tp = com_tty[unit] = ttymalloc();
X  	} else
X  		tp = com_tty[unit];
X+ 
X+ 	/* increment usage counter */
X+ 	(void) spltty();
X+ 	com_use[unit] ++;
X+ 
X+ #ifdef COM_BIDIR
X+ 
X+  bidir_open_top:
X+ 
X+ 	/* if it's bidirectional, we've gotta deal with it... */
X+ 	if (com_bdi[unit].bidir) {
X+ 		if (callout) {
X+ 			if (com_bdi[unit].active_in) {
X+ 			    /* it's busy. die */
X+ 			    (void) spl0();
X+ 			    return (EBUSY);
X+ 			} else {
X+ 			    /* it's ours.  lock it down, and set it up */
X+ 			    com_bdi[unit].active_out = 1;
X+ 			    com_bdi[unit].fake_dcd = 1;
X+ 			}
X+ 		} else {
X+ 			if (com_bdi[unit].active_out) {
X+ 				/* it's busy, outgoing.  wait, if possible */
X+ 				if (flag & O_NONBLOCK) {
X+ 				    /* can't wait; bail */
X+ 				    (void) spl0();
X+ 				    return (EBUSY);
X+ 				} else {
X+ 				    /* wait for it... */
X+ 				    error = tsleep((caddr_t)&com_bdi[unit].active_out,
X+ 						   TTIPRI|PCATCH,
X+ 						   "comoth",
X+ 						   0);
X+ 				    /* if there was an error, take off. */
X+ 				    if (error != 0) {
X+ 					(void) spl0();
X+ 					return (error);
X+ 				    }
X+ 				    /* else take it from the top */
X+ 				    goto bidir_open_top;
X+ 				}
X+ 			} else if (commctl(dev, 0, DMGET) & MSR_DCD) {
X+ 				/* there's a carrier on the line; we win */
X+ 				com_bdi[unit].active_in = 1;
X+ 				com_bdi[unit].fake_dcd = 0;
X+ 			} else {
X+ 				/* there is no carrier on the line */
X+ 				if (flag & O_NONBLOCK) {
X+ 				    /* can't wait; let it open */
X+ 				    com_bdi[unit].active_in = 1;
X+ 				    com_bdi[unit].fake_dcd = 0;
X+ 				} else {
X+ 				    /* put DTR & RTS up */
X+ 				    commctl(dev, MCR_DTR | MCR_RTS, DMBIS);
X+ 				    outb(com+com_ier,
X+ 						inb(com+com_ier) | IER_EMSC);
X+ 
X+ 				    /* wait for it... */
X+ 				    error = tsleep((caddr_t)&com_bdi[unit].active_in,
X+ 						   TTIPRI|PCATCH,
X+ 						   "comdcd",
X+ 						   0);
X+ 
X+ 				    /* if not active, turn DTR & RTS off */
X+ 				    if (!com_bdi[unit].active)
X+ 					commctl(dev, MCR_DTR | MCR_RTS, DMBIC);
X+ 
X+ 				    /* if there was an error, take off. */
X+ 				    if (error != 0) {
X+ 					(void) spl0();
X+ 					return (error);
X+ 				    }
X+ 				    /* else take it from the top */
X+ 				    goto bidir_open_top;
X+ 				}
X+ 			}
X+ 		}
X+ 	}
X+ 
X+ 	com_bdi[unit].active = 1;
X+ #endif /* COM_BIDIR */
X+ 	(void) spl0();
X+ 
X  	tp->t_oproc = comstart;
X  	tp->t_param = comparam;
X  	tp->t_dev = dev;
X***************
X*** 202,208 ****
X  		if (tp->t_ispeed == 0) {
X  			tp->t_iflag = TTYDEF_IFLAG;
X  			tp->t_oflag = TTYDEF_OFLAG;
X! 			tp->t_cflag = TTYDEF_CFLAG;
X  			tp->t_lflag = TTYDEF_LFLAG;
X  			tp->t_ispeed = tp->t_ospeed = comdefaultrate;
X  		}
X--- 359,367 ----
X  		if (tp->t_ispeed == 0) {
X  			tp->t_iflag = TTYDEF_IFLAG;
X  			tp->t_oflag = TTYDEF_OFLAG;
X! 			tp->t_cflag = TTYDEF_CFLAG
X! 				| (com_sethwflow & (1 << unit) ? CRTSCTS : 0)
X! 				| (com_setlocal & (1 << unit) ? CLOCAL : 0);
X  			tp->t_lflag = TTYDEF_LFLAG;
X  			tp->t_ispeed = tp->t_ospeed = comdefaultrate;
X  		}
X***************
X*** 212,245 ****
X  		return (EBUSY);
X  	(void) spltty();
X  	(void) commctl(dev, MCR_DTR | MCR_RTS, DMSET);
X  	if ((comsoftCAR & (1 << unit)) || (commctl(dev, 0, DMGET) & MSR_DCD))
X  		tp->t_state |= TS_CARR_ON;
X! 	while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
X! 	       (tp->t_state & TS_CARR_ON) == 0) {
X! 		tp->t_state |= TS_WOPEN;
X! 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
X! 		    ttopen, 0))
X! 			break;
X! 	}
X  	(void) spl0();
X  	if (error == 0)
X  		error = (*linesw[tp->t_line].l_open)(dev, tp);
X  	return (error);
X  }
X   
X  /*ARGSUSED*/
X  comclose(dev, flag, mode, p)
X  	dev_t dev;
X  	int flag, mode;
X  	struct proc *p;
X  {
X! 	register struct tty *tp;
X! 	register com;
X! 	register int unit;
X   
X- 	unit = UNIT(dev);
X- 	com = com_addr[unit];
X- 	tp = com_tty[unit];
X  	(*linesw[tp->t_line].l_close)(tp, flag);
X  	outb(com+com_cfcr, inb(com+com_cfcr) & ~CFCR_SBREAK);
X  #ifdef KGDB
X--- 371,427 ----
X  		return (EBUSY);
X  	(void) spltty();
X  	(void) commctl(dev, MCR_DTR | MCR_RTS, DMSET);
X+ #ifdef COM_BIDIR
X+ 	if ((comsoftCAR & (1 << unit))
X+ 		|| com_bdi[unit].fake_dcd
X+ 		|| (commctl(dev, 0, DMGET) & MSR_DCD))
X+ #else /* COM_BIDIR */
X  	if ((comsoftCAR & (1 << unit)) || (commctl(dev, 0, DMGET) & MSR_DCD))
X+ #endif /* COM_BIDIR */
X  		tp->t_state |= TS_CARR_ON;
X! 	else
X! 		tp->t_state &=~ TS_CARR_ON;
X! #ifdef COM_BIDIR
X! 	if (!com_bdi[unit].bidir && !(flag & O_NONBLOCK))
X! #else /* COM_BIDIR */
X! 	if (!(flag & O_NONBLOCK))
X! #endif /* COM_BIDIR */
X! 		while ((tp->t_cflag&CLOCAL) == 0 &&
X! 			(tp->t_state & TS_CARR_ON) == 0) {
X! 			tp->t_state |= TS_WOPEN;
X! 			if (error = ttysleep(tp, (caddr_t)&tp->t_rawq,
X! 					TTIPRI | PCATCH, ttopen, 0))
X! 				break;
X! 		}
X  	(void) spl0();
X+ 
X+ #ifdef COM_BIDIR
X+ 	/* wakeup sleepers */
X+ 	wakeup((caddr_t) &com_bdi[unit].active_in);
X+ #endif /* COM_BIDIR */
X+ 
X  	if (error == 0)
X  		error = (*linesw[tp->t_line].l_open)(dev, tp);
X  	return (error);
X  }
X   
X+ void comclose_wakeup(arg)
X+ 	caddr_t arg;
X+ {
X+ 	wakeup(arg);
X+ }
X+ 
X  /*ARGSUSED*/
X  comclose(dev, flag, mode, p)
X  	dev_t dev;
X  	int flag, mode;
X  	struct proc *p;
X  {
X! 	register int unit = UNIT(dev);
X! 	register struct tty *tp = com_tty[unit];
X! 	register com = com_addr[unit];
X! 	int s, error;
X   
X  	(*linesw[tp->t_line].l_close)(tp, flag);
X  	outb(com+com_cfcr, inb(com+com_cfcr) & ~CFCR_SBREAK);
X  #ifdef KGDB
X***************
X*** 249,258 ****
X  	outb(com+com_ier, 0);
X  	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 
X  	    (tp->t_state&TS_ISOPEN) == 0)
X! 		(void) commctl(dev, 0, DMSET);
X  	ttyclose(tp);
X! 	ttyfree(tp);
X! 	com_tty[unit] = (struct tty *)NULL;
X  	return(0);
X  }
X   
X--- 431,468 ----
X  	outb(com+com_ier, 0);
X  	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 
X  	    (tp->t_state&TS_ISOPEN) == 0)
X! 		(void) commctl(dev, MCR_DTR | MCR_RTS, DMBIC);
X  	ttyclose(tp);
X! 	tp->t_ispeed = 0; /* mark tty for re-initialization */
X! 
X! 	do {
X! 		timeout(comclose_wakeup, (caddr_t)&com_bdi[unit].active,
X! 			COM_DTRWAIT);
X! 		error = tsleep((caddr_t)&com_bdi[unit].active, TTIPRI|PCATCH,
X! 			       "comclose", 0);
X! 	} while (error == ERESTART);
X! 
X!         /* up spl */
X! 	s = spltty();
X! #ifdef COM_BIDIR
X!         /* clear in, out, fake_dcd, lower spl */
X! 	com_bdi[unit].active = com_bdi[unit].active_in =
X! 	    com_bdi[unit].active_out = 0;
X! 	com_bdi[unit].fake_dcd = 0;
X! 
X!         /* wakeup sleepers who are waiting for out to finish */
X! 	wakeup((caddr_t) &com_bdi[unit].active_out);
X! #endif /* COM_BIDIR */
X! 
X! 	/* decrement usage counter, free tty if possible */
X! 	if(--com_use[unit] == 0) {
X! #ifdef broken /* session holds a ref to the tty; can't deallocate */
X! 		ttyfree(tp);
X! 		com_tty[unit] = (struct tty *)NULL;
X! #endif
X! 	}
X! 	(void) splx(s);
X! 
X  	return(0);
X  }
X   
X***************
X*** 390,404 ****
X  	register int stat;
X  
X  	tp = com_tty[unit];
X! 	stat = inb(com+com_msr);
X  	if ((stat & MSR_DDCD) && (comsoftCAR & (1 << unit)) == 0) {
X! 		if (stat & MSR_DCD)
X  			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
X! 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
X  			outb(com+com_mcr,
X  				inb(com+com_mcr) & ~(MCR_DTR | MCR_RTS) | MCR_IENABLE);
X! 	} else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) &&
X! 		   (tp->t_flags & CRTSCTS)) {
X  		/* the line is up and we want to do rts/cts flow control */
X  		if (stat & MSR_CTS) {
X  			tp->t_state &=~ TS_TTSTOP;
X--- 600,627 ----
X  	register int stat;
X  
X  	tp = com_tty[unit];
X! 	stat = get_msr(unit, com);
X  	if ((stat & MSR_DDCD) && (comsoftCAR & (1 << unit)) == 0) {
X! 		if (stat & MSR_DCD) {
X! #ifdef COM_BIDIR
X! 			if ((*linesw[tp->t_line].l_modem)(tp, 1))
X! 			    /* tty layer has ack'd carrier up, so stop faking */
X! 			    com_bdi[unit].fake_dcd = 0;
X! 
X! 			/* wakeup sleepers on active_in, who
X! 			 * are waiting for DCD
X! 			 */
X! 			wakeup((caddr_t) &com_bdi[unit].active_in);
X! #else
X  			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
X! #endif /* COM_BIDIR */
X! 		} else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
X  			outb(com+com_mcr,
X  				inb(com+com_mcr) & ~(MCR_DTR | MCR_RTS) | MCR_IENABLE);
X! 	}
X! 
X! 	if ((stat & MSR_DCTS) && (tp != NULL)
X! 		&& (tp->t_state & TS_ISOPEN) && (tp->t_cflag & CCTS_OFLOW)) {
X  		/* the line is up and we want to do rts/cts flow control */
X  		if (stat & MSR_CTS) {
X  			tp->t_state &=~ TS_TTSTOP;
X***************
X*** 408,413 ****
X--- 631,646 ----
X  	}
X  }
X  
X+ static
X+ int tiocm_xxx2mcr(data)
X+ register data;
X+ {
X+ 	register m = 0;
X+ 	if (data & TIOCM_DTR) m |= MCR_DTR;
X+ 	if (data & TIOCM_RTS) m |= MCR_RTS;
X+ 	return m;
X+ }
X+ 
X  comioctl(dev, cmd, data, flag)
X  	dev_t dev;
X  	caddr_t data;
X***************
X*** 445,464 ****
X  		break;
X  
X  	case TIOCMSET:
X! 		(void) commctl(dev, *(int *)data, DMSET);
X  		break;
X  
X  	case TIOCMBIS:
X! 		(void) commctl(dev, *(int *)data, DMBIS);
X  		break;
X  
X  	case TIOCMBIC:
X! 		(void) commctl(dev, *(int *)data, DMBIC);
X  		break;
X  
X  	case TIOCMGET:
X! 		*(int *)data = commctl(dev, 0, DMGET);
X! 		break;
X  
X  	default:
X  		return (ENOTTY);
X--- 678,718 ----
X  		break;
X  
X  	case TIOCMSET:
X! 	case TIOCMODS:
X! 		(void) commctl(dev, tiocm_xxx2mcr(*(int *)data), DMSET);
X  		break;
X  
X  	case TIOCMBIS:
X! 		(void) commctl(dev, tiocm_xxx2mcr(*(int *)data), DMBIS);
X  		break;
X  
X  	case TIOCMBIC:
X! 		(void) commctl(dev, tiocm_xxx2mcr(*(int *)data), DMBIC);
X  		break;
X  
X  	case TIOCMGET:
X! 	case TIOCMODG:
X! 		{
X! 			register m = inb(com+com_mcr), bits = 0;
X! 
X! 			if (m & MCR_DTR) bits |= TIOCM_DTR;
X! 			if (m & MCR_RTS) bits |= TIOCM_RTS;
X! 
X! 			m = commctl(dev, 0, DMGET);
X! 
X! 			if ((m & MSR_DCD)
X! #ifdef COM_BIDIR
X! 				|| com_bdi[unit].fake_dcd
X! #endif /* COM_BIDIR */
X! 				) bits |= TIOCM_CD;
X! 
X! 			if (m & MSR_CTS) bits |= TIOCM_CTS;
X! 			if (m & MSR_DSR) bits |= TIOCM_DSR;
X! 			if (m & (MSR_RI|MSR_TERI)) bits |= TIOCM_RI;
X! 			if (inb(com+com_ier)) bits |= TIOCM_LE;
X! 			*(int *)data = bits;
X! 			break;
X! 		}
X  
X  	default:
X  		return (ENOTTY);
X***************
X*** 476,494 ****
X  	int ospeed = ttspeedtab(t->c_ospeed, comspeedtab);
X   
X  	/* check requested parameters */
X!         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
X                  return(EINVAL);
X          /* and copy to tty */
X-         tp->t_ispeed = t->c_ispeed;
X          tp->t_ospeed = t->c_ospeed;
X          tp->t_cflag = cflag;
X  
X  	com = com_addr[unit];
X! 	outb(com+com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS /*| IER_EMSC*/);
X  	if (ospeed == 0) {
X! 		(void) commctl(unit, 0, DMSET);	/* hang up line */
X  		return(0);
X! 	}
X  	outb(com+com_cfcr, inb(com+com_cfcr) | CFCR_DLAB);
X  	outb(com+com_data, ospeed & 0xFF);
X  	outb(com+com_ier, ospeed >> 8);
X--- 730,753 ----
X  	int ospeed = ttspeedtab(t->c_ospeed, comspeedtab);
X   
X  	/* check requested parameters */
X!         if (ospeed < 0 || (t->c_ospeed && t->c_ispeed
X! 					&& t->c_ispeed != t->c_ospeed))
X                  return(EINVAL);
X          /* and copy to tty */
X          tp->t_ospeed = t->c_ospeed;
X+         tp->t_ispeed = t->c_ispeed ? t->c_ispeed : t->c_ospeed;
X          tp->t_cflag = cflag;
X  
X  	com = com_addr[unit];
X! 	outb(com+com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC);
X  	if (ospeed == 0) {
X! 		/* hang up line */
X! 		(void) commctl(unit, MCR_DTR | MCR_RTS, DMBIC);
X  		return(0);
X! 	} else
X! 		/* assert DTR and RTS */
X! 		(void) commctl(unit, MCR_DTR | MCR_RTS, DMBIS);
X! 
X  	outb(com+com_cfcr, inb(com+com_cfcr) | CFCR_DLAB);
X  	outb(com+com_data, ospeed & 0xFF);
X  	outb(com+com_ier, ospeed >> 8);
X***************
X*** 526,532 ****
X  	unit = UNIT(tp->t_dev);
X  	com = com_addr[unit];
X  	s = spltty();
X! 	if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
X  		goto out;
X  	if (tp->t_outq.c_cc <= tp->t_lowat) {
X  		if (tp->t_state&TS_ASLEEP) {
X--- 785,793 ----
X  	unit = UNIT(tp->t_dev);
X  	com = com_addr[unit];
X  	s = spltty();
X! 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP) || 
X! 		((tp->t_cflag & CCTS_OFLOW)
X! 			&& (com_mstat[unit] & MSR_CTS) == 0))
X  		goto out;
X  	if (tp->t_outq.c_cc <= tp->t_lowat) {
X  		if (tp->t_state&TS_ASLEEP) {
X***************
X*** 592,598 ****
X  		break;
X  
X  	case DMGET:
X! 		bits = inb(com+com_msr);
X  		break;
X  	}
X  	(void) splx(s);
X--- 853,859 ----
X  		break;
X  
X  	case DMGET:
X! 		bits = get_msr(unit, com);
X  		break;
X  	}
X  	(void) splx(s);
END_OF_FILE
if test 17429 -ne `wc -c <'com.c-diff'`; then
    echo shar: \"'com.c-diff'\" unpacked with wrong size!
fi
# end of 'com.c-diff'
fi
if test -f 'termios.h-diff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'termios.h-diff'\"
else
echo shar: Extracting \"'termios.h-diff'\" \(832 characters\)
sed "s/^X//" >'termios.h-diff' <<'END_OF_FILE'
X*** /sys/sys/termios.h-dist	Sun Jun  6 00:40:26 1993
X***************
X*** 136,143 ****
X  #define CLOCAL		0x00008000	/* ignore modem status lines */
X  #ifndef _POSIX_SOURCE
X  #define CCTS_OFLOW	0x00010000	/* CTS flow control of output */
X- #define CRTSCTS		CCTS_OFLOW	/* ??? */
X  #define CRTS_IFLOW	0x00020000	/* RTS flow control of input */
X  #define	MDMBUF		0x00100000	/* flow control output via Carrier */
X  #endif
X  
X--- 136,143 ----
X  #define CLOCAL		0x00008000	/* ignore modem status lines */
X  #ifndef _POSIX_SOURCE
X  #define CCTS_OFLOW	0x00010000	/* CTS flow control of output */
X  #define CRTS_IFLOW	0x00020000	/* RTS flow control of input */
X+ #define CRTSCTS		(CCTS_OFLOW | CRTS_IFLOW) /* ??? */
X  #define	MDMBUF		0x00100000	/* flow control output via Carrier */
X  #endif
X  
END_OF_FILE
if test 832 -ne `wc -c <'termios.h-diff'`; then
    echo shar: \"'termios.h-diff'\" unpacked with wrong size!
fi
# end of 'termios.h-diff'
fi
if test -f 'ttydefaults.h-diff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ttydefaults.h-diff'\"
else
echo shar: Extracting \"'ttydefaults.h-diff'\" \(807 characters\)
sed "s/^X//" >'ttydefaults.h-diff' <<'END_OF_FILE'
X*** /sys/sys/ttydefaults.h-dist	Thu May 20 18:23:18 1993
X***************
X*** 44,53 ****
X  /*
X   * Defaults on "first" open.
X   */
X! #define	TTYDEF_IFLAG	(BRKINT | ISTRIP | ICRNL | IMAXBEL | IXON | IXANY)
X  #define TTYDEF_OFLAG	(OPOST | ONLCR | OXTABS)
X  #define TTYDEF_LFLAG	(ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL)
X! #define TTYDEF_CFLAG	(CREAD | CS7 | PARENB | HUPCL)
X  #define TTYDEF_SPEED	(B9600)
X  
X  /*
X--- 44,53 ----
X  /*
X   * Defaults on "first" open.
X   */
X! #define	TTYDEF_IFLAG	(BRKINT | ICRNL | IMAXBEL | IXON | IXANY)
X  #define TTYDEF_OFLAG	(OPOST | ONLCR | OXTABS)
X  #define TTYDEF_LFLAG	(ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL)
X! #define TTYDEF_CFLAG	(CREAD | CS8 | HUPCL)
X  #define TTYDEF_SPEED	(B9600)
X  
X  /*
END_OF_FILE
if test 807 -ne `wc -c <'ttydefaults.h-diff'`; then
    echo shar: \"'ttydefaults.h-diff'\" unpacked with wrong size!
fi
# end of 'ttydefaults.h-diff'
fi
echo shar: End of shell archive.
exit 0
------------------------------ snap ------------------------------


Unshar and enjoy,
Hannes
-- 
Hans-Christoph Deeken | hannes@flinx.{RoBIN.de,hotb.sub.org} (home)
Jungfernstrasse 34    | deeken@iti.informatik.th-darmstadt.de (university)
64291 Darmstadt       | IRC: Glenlivet            | "Tuuut." -- Karate Kid 2

------------------------------------------------------------------------------