*BSD News Article 25848


Return to BSD News archive

Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!agate!howland.reston.ans.net!xlink.net!zib-berlin.de!news.th-darmstadt.de!hotb.RoBIN.de!flinx.RoBIN.de!not-for-mail
From: hannes@flinx.RoBIN.de (Hannes Deeken)
Newsgroups: comp.os.386bsd.questions
Subject: Re: Question about serial driver design in NetBSD
Date: 10 Jan 1994 20:11:50 +0100
Organization: Nosimals & Co.
Lines: 898
Message-ID: <2gs9a4INNb29@flinx.RoBIN.de>
References: <2gne5h$1hq@nwfocus.wa.com>
NNTP-Posting-Host: flinx.robin.de
Keywords: CLOCAL, calling units, carrier detect

sandy@halcyon.com (Jeremy Scofield) writes:

>I'm looking for some info from the *BSD developers, or anyone who
>understands the design of the serial-port driver in NetBSD.  Since this
>may not be the best place to ask, I also solicit suggestions on where I
>might find an answer.

You could try the NetBSD mailing lists (send a 'help' to 
majordomo@sun-lamp.cs.berkeley.edu).


>I've been trying to get a modem attached to my NetBSD 0.9 system, to
>use for dialing in and out.  Unfortunately, the serial-port driver
>isn't making this easy.  The man page termios(4) says that an ordinary
>open() of the device will block until carrier is detected (provided
>that CLOCAL is off).  The driver isn't working that way -- getty gets
>the device open immediately and writes the prompt, causing a hard echo
>loop between the port and the modem.  (I know that I can can fix this
>particular problem by telling the modem not to echo while in command
>mode, but that doesn't solve the other related problems with the
>driver.)

>Reading through the driver code (com.c), I found what appears to be the
>reason -- the line

>	comsoftCAR |= 1 << unit;	/* XXX */

>in the comattach() routine.  This makes the driver act as if CD
>(carrier detect) is always on.

That's the first half of the problem. The second half is in comparam():

>	outb(com+com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS /*| IER_EMSC*/);

The modem status interrupt never gets enabled. That causes the DCD and CTS(!)
lines to be ignored, preventing carrier detection and hardware flowcontrol
from working.

>I have three questions.

>    1.  What is that line doing there?  The XXX suggests that maybe it
>	was added as a temporary fix.  Is there a problem supporting real
>	CD on PC serial ports?

>    2.  I don't see any code in com.c to support Berkeley ``calling
>	units'' (e.g. cu00 corresponding to tty00), that make it
>	possible to dial *out* on a port while getty is blocked waiting
>	for CD.  According to an old comp.unix.bsd article by Terry
>	Lambert, the ``calling unit'' approach is simpler *and* more
>	robust than the uugetty/O_NDELAY/CLOCAL jazz.  So if this is a
>	Berkeleyism, and it was available in some versions of 386BSD,
>	and it's technically superior, why isn't it in the NetBSD code?

I can't speak for the NetBSD developers, but the serial driver for i386
machines is (modulo some changes due to dynamic tty allocation) the same
as in 386BSD 0.1 (as far as I can see).


>    3.  What are the NetBSD developers planning to do about serial
>	ports?  Will CD be supported, at least on those serial cards
>	that can do it?  Will there be ``calling units'', or are they
>	moving away from that idea for some reason?  (I may do some
>	whacking on the driver, but I'd like to avoid going off in a
>	completely different direction.)

I don't know what the NetBSD developers plan, but I did "some whacking
on the driver" :) and got carrier detection, hardware flowcontrol and calling
units working (at least it looks as if :).

Thanks to Chris Demetriou, whose "serial driver hacks" [his words :)] for
386BSD enabled me to create the following patches.

------------------------------ 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 10 20:11:23 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'\" \(5325 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
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) and 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).
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----------
XI'm not sure whether CTS flowcontrol works right.
XSometimes, when using the 'partial open hack' (open port with O_NONBLOCK,
Xset CLOCAL, open port without O_NONBLOCK, close first filedescriptor) on
Xthe port my modem is on, characters sent by the modem get echoed back and
Xforth between the modem and the computer. I was not able to track this down.
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 5325 -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'\" \(15191 characters\)
sed "s/^X//" >'com.c-diff' <<'END_OF_FILE'
X*** /sys/arch/i386/isa/com.c-dist	Thu Aug 26 22:46:23 1993
X--- /sys/arch/i386/isa/com.c	Mon Jan 10 18:42:48 1994
X***************
X*** 65,73 ****
X--- 65,92 ----
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--- 98,104 ----
X  int	commajor;
X  short com_addr[NCOM];
X  struct	tty *com_tty[NCOM];
X+ short com_use[NCOM];
X  
X  struct speedtab comspeedtab[] = {
X  	0,	0,
X***************
X*** 110,116 ****
X--- 130,144 ----
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  comprobe(dev)
X  struct isa_device *dev;
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--- 160,178 ----
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,154 ****
X--- 183,190 ----
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, 0 | MCR_IENABLE);
X  #ifdef KGDB
X  	if (kgdb_dev == makedev(commajor, unit)) {
X***************
X*** 176,181 ****
X--- 212,233 ----
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--- 235,344 ----
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--- 348,356 ----
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,232 ****
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--- 360,405 ----
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***************
X*** 236,241 ****
X--- 409,415 ----
X  	register struct tty *tp;
X  	register com;
X  	register int unit;
X+ 	int s, error;
X   
X  	unit = UNIT(dev);
X  	com = com_addr[unit];
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--- 423,459 ----
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! 
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*** 392,404 ****
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--- 593,616 ----
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! #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! 	} else if ((stat & MSR_DCTS) && (tp != NULL)
X! 		&& (tp->t_state & TS_ISOPEN) && (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***************
X*** 408,413 ****
X--- 620,635 ----
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--- 667,705 ----
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 = commctl(dev, 0, DMGET), bits = 0;
X! 
X! 			if (m & MCR_DTR) bits |= TIOCM_DTR;
X! 			if (m & MCR_RTS) bits |= TIOCM_RTS;
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--- 717,740 ----
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;
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);
END_OF_FILE
if test 15191 -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--- /sys/sys/termios.h	Thu Aug 26 20:13:19 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--- /sys/sys/ttydefaults.h	Thu Jan  6 16:41:58 1994
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 ------------------------------


Have fun,
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