Subject: kern/1884: Bidirectional support of serial port currently for i386, sparc
To: None <gnats-bugs@gnats.netbsd.org>
From: None <koji@imada.math.human.nagoya-u.ac.jp>
List: netbsd-bugs
Date: 01/03/1996 17:27:50
>Number:         1884
>Category:       kern
>Synopsis:       Bidirectional support of serial port currently for i386, sparc
>Confidential:   yes
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          support
>Submitter-Id:   net
>Arrival-Date:   Wed Jan  3 04:35:00 1996
>Last-Modified:
>Originator:     Koji Imada - je4owb/2
>Organization:
Mathematical group of graduate school of human infomics,
	Nagoya University.
>Release:        1.1
>Environment:
	
System: NetBSD bimota 1.1 NetBSD 1.1 (BIMOTA) #27: Sat Dec 30 21:52:38 JST 1995 koji@bimota:/usr/local/NetBSD/src/sys/arch/i386/compile/BIMOTA i386


>Description:
	
	bidirectional support for serial port. This is consist of 2
	parts. one is device independent, brand-new  and another is
	modification of existing driver. this is based on old cgd's
	patch for 386BSD. I have modified it to fit NetBSD 0.9[a],
	1.0[a]. And now rewrite to be usable for all platform with
	small modification. This is tested on NetBSD/i386 and
	NetBSD/sparc for a few days. port to Sun3 is going slowly for
	unstable hardware and slow CPU :-<.
	This is for NetBSD 1.1. But would be easily ported to 1.1a.
	This bidirectional support is Sun OS style. You need call out
	device and this could be opened without DCD at first(like soft 
	carrier). But once DCD is detected, behaves naormally.
	Of cource, call out or dial in port is used, another port
	could not be used.
>How-To-Repeat:
	
>Fix:
	
cd to /usr/src and apply following patch. This makes
sys/dev/com_bidir.[ch] and modifies sys/arch/{i386,sparc}/conf/files.i386,
sys/dev/isa/com.c and sys/arch/sparc/dev/zs.c.

'options COM_BIDIR' to config file is necessary. and make device to
call out(which minor device number is minor device number of usual
device plus 128). 

*** /dev/null	Wed Jan  3 02:04:20 1996
--- sys/dev/com_bidir.h	Sun Dec 31 21:34:48 1995
***************
*** 0 ****
--- 1,35 ----
+ /*
+  * bidirectional support for serial port
+  * based on cgd's old patch to 386bsd's com driver
+  */
+ 
+ /* Unit mask  */
+ #define BIDIR_UNITMASK	0x7f
+ /* callout mask */
+ #define BIDIR_CALLOUTMASK	0x80
+ /* get unit number from minor device number */
+ #define BIDIR_COMUNIT(x)	(minor(x) & BIDIR_UNITMASK)
+ /* Is this device for callout? */
+ #define BIDIR_CALLOUT(x)	(minor(x) & BIDIR_CALLOUTMASK)
+ 
+ 
+ /* operation for com_io */
+ #define BD_GET_DCD	0	/* Get DCD, zero: down, non zero: up */
+ #define BD_DIALIN_OK	1	/* Check DCD up or SOFTCARRIER or CLOCAL */
+ #define BD_ENABLE	2	/* enable serial port for waiting carrier */
+ #define BD_DISABLE	3	/* disable serial port when waiting carrier */
+ 
+ struct com_bidir {
+ 	int bd_dtrwait;		/* how long to hold DTR down on close (* 1/HZ) */
+ #define BIDIR_DEFAULT_WAIT	50
+ 	int bd_bidir;		/* is this unit bidirectional? */
+ 	int bd_active;		/* is the port active ? */
+ 	int bd_active_in;	/* is the incoming port in use? */
+ 	int bd_active_out;	/* is the outgoing port in use? */
+ 	int bd_fake_dcd;	/* should we fake DCD for now? */
+ };
+ 
+ int bidir_init __P((struct com_bidir *bd, int sw));
+ int bidir_open __P((struct com_bidir *bd, int flag, int callout, void *arg, int (*com_io)(int op, void *arg)));
+ int bidir_close __P((struct com_bidir *bd));
+ int bidir_dcd_up __P((struct com_bidir *bd));
*** /dev/null	Wed Jan  3 02:04:20 1996
--- sys/dev/com_bidir.c	Sun Dec 31 21:34:42 1995
***************
*** 0 ****
--- 1,204 ----
+ /*
+  * bidirectional support for serial port
+  * based on cgd's old patch to 386bsd's com driver
+  */
+ 
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/ioctl.h>
+ #include <sys/select.h>
+ #include <sys/tty.h>
+ #include <sys/proc.h>
+ #include <sys/user.h>
+ #include <sys/conf.h>
+ #include <sys/file.h>
+ #include <sys/uio.h>
+ #include <sys/kernel.h>
+ #include <sys/syslog.h>
+ #include <sys/types.h>
+ #include <sys/device.h>
+ 
+ #if 0
+ #include <machine/cpu.h>
+ #include <machine/pio.h>
+ #endif
+ 
+ #include <dev/com_bidir.h>
+ 
+ int
+ bidir_init(bd, sw)
+ 	struct com_bidir *bd;
+ 	int sw;
+ {
+ 	if (bd == NULL)
+ 	    return -1;
+ 
+ 	if (sw) {
+ 	  bd->bd_bidir = 1;
+ 	  bd->bd_dtrwait = BIDIR_DEFAULT_WAIT;
+ 	  bd->bd_active = 0;
+ 	  bd->bd_active_in = bd->bd_active_out = 0;
+ 	  bd->bd_fake_dcd = 0;
+ 	} else {
+ 	  bd->bd_bidir = 0;
+ 	  bd->bd_dtrwait = 0;
+ 	  bd->bd_active = 0;
+ 	  bd->bd_active_in = bd->bd_active_out = 0;
+ 	  bd->bd_fake_dcd = 0;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ 
+ int
+ bidir_open(bd, flag, callout, arg, com_io)
+ 	struct com_bidir *bd;
+ 	int flag;
+ 	int callout;
+ 	void *arg;
+ 	int (*com_io)(int op, void *arg);
+ {
+ 	int s;
+ 	int error;
+ 
+ 	if (bd->bd_bidir == 0) {
+ 	  if (callout == 0)
+ 	    return 0;
+ 	  else
+ 	    return ENXIO;
+ 	}
+ 
+ 	s = spltty();
+ 
+ 	for (;;) {
+ 		if (callout) {
+ 			if (bd->bd_active_out)
+ 				break;
+ 			if (bd->bd_active_in) {
+ 				splx(s);
+ 				return EBUSY;
+ 			} else {
+ 				/* it's ours. look it down and set it up */
+ 				bd->bd_active_out = 1;
+ 				bd->bd_fake_dcd = 1;
+ 				break;
+ 			}
+ 		} else {
+ 			if (bd->bd_active_in)
+ 				break;
+ 			if (bd->bd_active_out) {
+ 				/* it's busy, outgoing, wait, if possible */
+ 				if ((flag & O_NONBLOCK) != 0) {
+ 					/* can't wait; fall */
+ 					splx(s);
+ 					return EBUSY;
+ 				} else {
+ 					/* wait for it... */
+ 					error = tsleep((caddr_t)&bd->bd_active_out, TTIPRI|PCATCH, "bidir_open", 0);
+ 					/* if there was an error, take off. */
+ 					if (error != 0) {
+ 						splx(s);
+ 						return (error);
+ 					}
+ 					/* else take it from top. */
+ 					continue;
+ 				}
+ 			} else if (com_io(BD_DIALIN_OK, arg)) {
+ 				/* there's a carrier on the line; we win */
+ 				bd->bd_active_in = 1;
+ 				bd->bd_fake_dcd = 0;
+ 				break;
+ 			} else {
+ 				/* there is no carrier on the line */
+ 				if (flag & O_NONBLOCK) {
+ 					/* can't wait; let it open */
+ 					bd->bd_active_in = 1;
+ 					bd->bd_fake_dcd = 0;
+ 					break;
+ 				} else {
+ 					com_io(BD_ENABLE, arg);
+ 					error = tsleep((caddr_t)&bd->bd_active_in, TTIPRI|PCATCH, "comdcd", 0);
+ 					/* if not active, turn DTR & RTS off */
+ 					if (!bd->bd_active && !com_io(BD_GET_DCD, arg))
+ 					    com_io(BD_DISABLE, arg);
+ 					if (error != 0) {
+ 						splx(s);
+ 						return error;
+ 					}
+ 					/* else take it from top */
+ 					continue;
+ 				}
+ 			}
+ 		}
+ 	}
+ 	bd->bd_active = 1;
+ 	splx(s);
+ 
+ 	return 0;
+ }
+ 	
+ 
+ static void bidir_close_wakeup __P((void *arg));
+ 
+ static void
+ bidir_close_wakeup(arg)
+ 	void *arg;
+ {
+ 	wakeup(arg);
+ }
+ 
+ int
+ bidir_close(bd)
+ 	struct com_bidir *bd;
+ {
+ 	int s;
+ 	int error;
+ 
+ 	if (bd == NULL || bd->bd_active == 0)
+ 	    return -1;
+ 
+ 	if (bd->bd_bidir == 0)
+ 	  return 0;
+ 
+ 	if (bd->bd_dtrwait) {
+ 		do {
+ 			timeout(bidir_close_wakeup, (caddr_t)&bd->bd_dtrwait, bd->bd_dtrwait);
+ 			error = tsleep((caddr_t)&bd->bd_dtrwait, TTIPRI|PCATCH, "bidir_close", 0);
+ 		} while (error == ERESTART);
+ 	}
+ 
+ 	/* up spl, claen in, out, fake_dcd, lower spl */
+ 	s = spltty();
+ 	bd->bd_active = 0;
+ 	bd->bd_active_in = bd->bd_active_out = 0;
+ 	bd->bd_fake_dcd = 0;
+ 
+ 	/* wake up sleepers who are waiting for out to finish */
+ 	wakeup((caddr_t)&bd->bd_active_out);
+ 	/* wake up sleepers who are waiting for in to start */
+ 	wakeup((caddr_t)&bd->bd_active_in);
+ 
+ 	splx(s);
+ 	
+ 	return 0;
+ }
+ 
+ int
+ bidir_dcd_up(bd)
+ 	struct com_bidir *bd;
+ {
+ 	if (bd == NULL)
+ 	    return -1;
+ 
+ 	if (bd->bd_bidir == 0)
+ 	  return 0;
+ 
+ 	/* tty layer has ack'ed carrier up, so stop faking. */
+ 	bd->bd_fake_dcd = 0;
+ 
+ 	/* wake up sleepsers on active_in, who are waiting for DCD */
+ 	wakeup((caddr_t)&bd->bd_active_in);
+ 
+ 	return 0;
+ }
*** sys/dev/isa/com.c.orig	Fri Dec 29 18:03:02 1995
--- sys/dev/isa/com.c	Sun Dec 31 21:41:10 1995
***************
*** 62,67 ****
--- 62,71 ----
  #include <dev/isa/comreg.h>
  #include <dev/ic/ns16550reg.h>
  
+ #ifdef COM_BIDIR
+ #include <dev/com_bidir.h>
+ #endif /* COM_BIDIR */
+ 
  #define	COM_IBUFSIZE	(2 * 256)
  #define	COM_IHIGHWATER	((3 * COM_IBUFSIZE) / 4)
  
***************
*** 89,94 ****
--- 93,101 ----
  
  	u_char *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend;
  	u_char sc_ibufs[2][COM_IBUFSIZE];
+ #ifdef COM_BIDIR
+ 	struct com_bidir bd;
+ #endif /* COM_BIDIR */
  };
  
  int comprobe __P((struct device *, void *, void *));
***************
*** 100,105 ****
--- 107,115 ----
  void compoll __P((void *));
  int comparam __P((struct tty *, struct termios *));
  void comstart __P((struct tty *));
+ #ifdef COM_BIDIR
+ static int comio __P((int op, void *arg));
+ #endif /* COM_BIDIR */
  
  struct cfdriver comcd = {
  	NULL, "com", comprobe, comattach, DV_TTY, sizeof(struct com_softc)
***************
*** 123,129 ****
--- 133,143 ----
  extern int kgdb_debug_init;
  #endif
  
+ #ifndef COM_BIDIR
  #define	COMUNIT(x)	(minor(x))
+ #else /* COM_BIDIR */
+ #define COMUNIT(x)	BIDIR_COMUNIT(x)
+ #endif /* COM_BIDIR */
  
  #define	bis(c, b)	do { const register int com_ad = (c); \
  			     outb(com_ad, inb(com_ad) | (b)); } while(0)
***************
*** 155,160 ****
--- 169,175 ----
  #undef	divrnd(n, q)
  }
  
+ 
  int
  comprobe1(iobase)
  	int iobase;
***************
*** 254,259 ****
--- 269,278 ----
  		sc->sc_hwflags |= COM_HW_CONSOLE;
  		sc->sc_swflags |= COM_SW_SOFTCAR;
  	}
+ #ifdef COM_BIDIR
+ #define COM_SW_NOBIDIR	0x1000
+ 	bidir_init(&sc->bd, (cf->cf_flags & COM_SW_NOBIDIR) == 0);
+ #endif /* COM_BIDIR */
  }
  
  int
***************
*** 280,285 ****
--- 299,310 ----
  	else
  		tp = sc->sc_tty;
  
+ #ifdef COM_BIDIR
+ 	error = bidir_open(&sc->bd, flag, BIDIR_CALLOUT(dev), (void*)sc, comio);
+ 	if (error != 0)
+ 	  return error;
+ #endif /* COM_BIDIR */
+ 
  	tp->t_oproc = comstart;
  	tp->t_param = comparam;
  	tp->t_dev = dev;
***************
*** 328,333 ****
--- 353,365 ----
  		    IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC);
  
  		sc->sc_msr = inb(iobase + com_msr);
+ #ifdef COM_BIDIR
+ 		if ((sc->sc_msr & MSR_DCD) != 0)
+ 		  sc->bd.bd_fake_dcd = 0;
+ 		if (BIDIR_CALLOUT(dev) && sc->bd.bd_fake_dcd)
+ 		  tp->t_state |= TS_CARR_ON;
+ 		else
+ #endif /* COM_BIDIR */
  		if (sc->sc_swflags & COM_SW_SOFTCAR || sc->sc_msr & MSR_DCD ||
  		    tp->t_cflag & MDMBUF)
  			tp->t_state |= TS_CARR_ON;
***************
*** 354,359 ****
--- 386,396 ----
  		}
  	splx(s);
  
+ #ifdef COM_BIDIR
+        /* wakeup sleepers */
+        wakeup((caddr_t) &sc->bd.bd_active_in);
+ #endif /* COM_BIDIR */
+ 
  	return (*linesw[tp->t_line].l_open)(dev, tp);
  }
   
***************
*** 393,398 ****
--- 430,440 ----
  		sc->sc_tty = 0;
  	}
  #endif
+ 
+ #ifdef COM_BIDIR
+ 	bidir_close(&sc->bd);
+ #endif /* COM_BIDIR */
+ 
  	return 0;
  }
   
***************
*** 864,869 ****
--- 906,917 ----
  		if (msr != sc->sc_msr) {
  			delta = msr ^ sc->sc_msr;
  			sc->sc_msr = msr;
+ #ifdef COM_BIDIR
+ 			if ((delta & MSR_DCD) != 0 &&
+ 			    (sc->sc_swflags & COM_SW_SOFTCAR) == 0 &&
+ 			    (msr & MSR_DCD) != 0)
+ 			  bidir_dcd_up(&sc->bd);
+ #endif /* COM_BIDIR */
  			if ((delta & MSR_DCD) != 0 &&
  			    (sc->sc_swflags & COM_SW_SOFTCAR) == 0 &&
  			    (*linesw[tp->t_line].l_modem)(tp, (msr & MSR_DCD) != 0) == 0) {
***************
*** 994,996 ****
--- 1042,1085 ----
  {
  
  }
+ 
+ #ifdef COM_BIDIR
+ /*
+  * comio do physical io needed by bidir_open
+  */
+ 
+ static int
+ comio(op, arg)
+ 	int op;
+ 	void *arg;
+ {
+ 	int ier;
+ 	int dcd;
+ 	struct com_softc *sc = arg;
+ 	int iobase = sc->sc_iobase;
+ 	struct tty *tp;
+ 
+ 	tp = sc->sc_tty;
+ 
+ 	switch (op) {
+ 	case BD_GET_DCD:
+ 	case BD_DIALIN_OK:
+ 	  dcd = inb(iobase+com_msr) & MSR_DCD;
+ 	  if (dcd == 0 && op == BD_DIALIN_OK) {
+ 	    if ((sc->sc_swflags & COM_SW_SOFTCAR) || (tp != NULL && (tp->t_cflag & CLOCAL) != 0))
+ 	      dcd = 1;
+ 	  }
+ 	  return dcd;
+ 	case BD_ENABLE:
+ 	  ier = inb(iobase);
+ 	  outb(iobase+com_mcr, sc->sc_mcr | MCR_DTR | MCR_RTS);
+ 	  outb(iobase+com_ier, ier | IER_EMSC);
+ 	  break;
+ 	case BD_DISABLE:
+ 	  outb(iobase+com_mcr, sc->sc_mcr & ~(MCR_DTR|MCR_RTS));
+ 	  break;
+ 	}
+ 	return 0;
+ }
+ #endif /* COM_BIDIR
+ 
*** sys/arch/sparc/dev/zs.c.orig	Sat Oct 14 11:20:52 1995
--- sys/arch/sparc/dev/zs.c	Sun Dec 31 21:58:41 1995
***************
*** 75,80 ****
--- 75,84 ----
  #include <dev/ic/z8530reg.h>
  #include <sparc/dev/zsvar.h>
  
+ #ifdef COM_BIDIR
+ #include <dev/com_bidir.h>
+ #endif /* COM_BIDIR */
+ 
  #ifdef KGDB
  #include <machine/remote-sl.h>
  #endif
***************
*** 108,113 ****
--- 112,120 ----
  	struct	device zi_dev;		/* base device */
  	volatile struct zsdevice *zi_zs;/* chip registers */
  	struct	zs_chanstate zi_cs[2];	/* channel A and B software state */
+ #ifdef COM_BIDIR
+ 	struct com_bidir bd[2];
+ #endif /* COM_BIDIR */
  };
  
  /* Definition of the driver for autoconfig. */
***************
*** 130,135 ****
--- 137,145 ----
  static void	zsstart __P((struct tty *));
  void		zsstop __P((struct tty *, int));
  static int	zsparam __P((struct tty *, struct termios *));
+ #ifdef COM_BIDIR
+ static int zsio __P((int op, void *arg));
+ #endif /* COM_BIDIR */
  
  /* Routines purely local to this driver. */
  static int	zs_getspeed __P((volatile struct zschan *));
***************
*** 154,159 ****
--- 164,172 ----
  extern volatile struct zsdevice *findzs(int);
  static volatile struct zsdevice *zsaddr[NZS];	/* XXX, but saves work */
  
+ #ifdef COM_BIDIR
+ static struct com_bidir *bdlist[NZS];		/* XXX, but needs */
+ #endif /* COM_BIDIR */
  /*
   * Console keyboard L1-A processing is done in the hardware interrupt code,
   * so we need to duplicate some of the console keyboard decode state.  (We
***************
*** 313,318 ****
--- 326,337 ----
  		tp->t_cflag = CS8;
  		ms_serial(tp, zsiopen, zsiclose);
  	}
+ #ifdef COM_BIDIR
+ 	bidir_init(&zi->bd[0], unit-1 != ZS_KBD);
+ 	bidir_init(&zi->bd[1], unit != ZS_MOUSE);
+ 
+ 	bdlist[zs] = zi->bd;
+ #endif /* COM_BIDIR */
  }
  
  /*
***************
*** 543,549 ****
--- 562,572 ----
  	register struct tty *tp;
  	register struct zs_chanstate *cs;
  	struct zsinfo *zi;
+ #ifdef COM_BIDIR
+ 	int unit = BIDIR_COMUNIT(dev), zs = unit >> 1, error, s;
+ #else /* !COM_BIDIR */
  	int unit = minor(dev), zs = unit >> 1, error, s;
+ #endif /* !COM_BIDIR */
  
  	if (zs >= zscd.cd_ndevs || (zi = zscd.cd_devs[zs]) == NULL ||
  	    unit == ZS_KBD || unit == ZS_MOUSE)
***************
*** 552,557 ****
--- 575,585 ----
  	if (cs->cs_consio)
  		return (ENXIO);		/* ??? */
  	tp = cs->cs_ttyp;
+ #ifdef COM_BIDIR
+ 	error = bidir_open(&zi->bd[unit & 1], flags, BIDIR_CALLOUT(dev), (void*)cs, zsio);
+ 	if (error != 0)
+ 	  return error;
+ #endif /* COM_BIDIR */
  	s = spltty();
  	if ((tp->t_state & TS_ISOPEN) == 0) {
  		ttychars(tp);
***************
*** 579,584 ****
--- 607,618 ----
  		ZS_DELAY();
  		if ((rr0 & ZSRR0_DCD) || cs->cs_softcar)
  			tp->t_state |= TS_CARR_ON;
+ #ifdef COM_BIDIR
+ 		if (rr0 & ZSRR0_DCD)
+ 			zi->bd[unit & 1].bd_fake_dcd = 0;
+ 		if (BIDIR_CALLOUT(dev) && zi->bd[unit & 1].bd_fake_dcd)
+ 		  tp->t_state |= TS_CARR_ON;
+ #endif /* COM_BIDIR */
  		if (flags & O_NONBLOCK || tp->t_cflag & CLOCAL ||
  		    tp->t_state & TS_CARR_ON)
  			break;
***************
*** 595,600 ****
--- 629,640 ----
  		}
  	}
  	splx(s);
+ 
+ #ifdef COM_BIDIR
+        /* wakeup sleepers */
+        wakeup((caddr_t) &zi->bd[unit & 1].bd_active_in);
+ #endif /* COM_BIDIR */
+ 
  	if (error == 0)
  		error = linesw[tp->t_line].l_open(dev, tp);
  	if (error)
***************
*** 615,621 ****
--- 655,665 ----
  	register struct zs_chanstate *cs;
  	register struct tty *tp;
  	struct zsinfo *zi;
+ #ifdef COM_BIDIR
+ 	int unit = BIDIR_COMUNIT(dev), s;
+ #else /* !COM_BIDIR */
  	int unit = minor(dev), s;
+ #endif /* !COM_BIDIR */
  
  	zi = zscd.cd_devs[unit >> 1];
  	cs = &zi->zi_cs[unit & 1];
***************
*** 643,648 ****
--- 687,696 ----
  		(void) zsparam(tp, &tp->t_termios);
  	}
  #endif
+ #ifdef COM_BIDIR
+ 	bidir_close(&zi->bd[unit & 1]);
+ #endif /* COM_BIDIR */
+ 
  	return (0);
  }
  
***************
*** 658,664 ****
--- 706,716 ----
  	register struct zs_chanstate *cs;
  	register struct zsinfo *zi;
  	register struct tty *tp;
+ #ifdef COM_BIDIR
+ 	int unit = BIDIR_COMUNIT(dev);
+ #else /* !COM_BIDIR */
  	int unit = minor(dev);
+ #endif /* !COM_BIDIR */
  
  	zi = zscd.cd_devs[unit >> 1];
  	cs = &zi->zi_cs[unit & 1];
***************
*** 677,683 ****
--- 729,739 ----
  	register struct zs_chanstate *cs;
  	register struct zsinfo *zi;
  	register struct tty *tp;
+ #ifdef COM_BIDIR
+ 	int unit = BIDIR_COMUNIT(dev);
+ #else /* !COM_BIDIR */
  	int unit = minor(dev);
+ #endif /* !COM_BIDIR */
  
  	zi = zscd.cd_devs[unit >> 1];
  	cs = &zi->zi_cs[unit & 1];
***************
*** 692,698 ****
--- 748,758 ----
  {
  	register struct zs_chanstate *cs;
  	register struct zsinfo *zi;
+ #ifdef COM_BIDIR
+ 	int unit = BIDIR_COMUNIT(dev);
+ #else /* !COM_BIDIR */
  	int unit = minor(dev);
+ #endif /* !COM_BIDIR */
  
  	zi = zscd.cd_devs[unit >> 1];
  	cs = &zi->zi_cs[unit & 1];
***************
*** 1066,1071 ****
--- 1126,1135 ----
  				 */
  				c = ZRING_VALUE(c);
  				if ((c ^ cs->cs_rr0) & ZSRR0_DCD) {
+ #ifdef COM_BIDIR
+ 					if (c & ZSRR0_DCD)
+ 					  bidir_dcd_up(&bdlist[(unit & BIDIR_UNITMASK) >> 1][unit & 1]);
+ #endif /* COM_BIDIR */
  					cc = (c & ZSRR0_DCD) != 0;
  					if (line->l_modem(tp, cc) == 0)
  						zs_modem(cs, cc);
***************
*** 1093,1099 ****
--- 1157,1167 ----
  	int flag;
  	struct proc *p;
  {
+ #ifdef COM_BIDIR
+ 	int unit = BIDIR_COMUNIT(dev);
+ #else /* !COM_BIDIR */
  	int unit = minor(dev);
+ #endif /* !COM_BIDIR */
  	struct zsinfo *zi = zscd.cd_devs[unit >> 1];
  	register struct zs_chanstate *cs = &zi->zi_cs[unit & 1];
  	register struct tty *tp = cs->cs_ttyp;
***************
*** 1210,1216 ****
--- 1278,1288 ----
  {
  	register struct zs_chanstate *cs;
  	register int s, nch;
+ #ifdef COM_BIDIR
+ 	int unit = BIDIR_COMUNIT(tp->t_dev);
+ #else /* !COM_BIDIR */
  	int unit = minor(tp->t_dev);
+ #endif /* !COM_BIDIR */
  	struct zsinfo *zi = zscd.cd_devs[unit >> 1];
  
  	cs = &zi->zi_cs[unit & 1];
***************
*** 1271,1277 ****
--- 1343,1353 ----
  	int flag;
  {
  	register struct zs_chanstate *cs;
+ #ifdef COM_BIDIR
+ 	register int s, unit = BIDIR_COMUNIT(tp->t_dev);
+ #else /* !COM_BIDIR */
  	register int s, unit = minor(tp->t_dev);
+ #endif /* !COM_BIDIR */
  	struct zsinfo *zi = zscd.cd_devs[unit >> 1];
  
  	cs = &zi->zi_cs[unit & 1];
***************
*** 1298,1304 ****
--- 1374,1384 ----
  	register struct tty *tp;
  	register struct termios *t;
  {
+ #ifdef COM_BIDIR
+ 	int unit = BIDIR_COMUNIT(tp->t_dev);
+ #else /* !COM_BIDIR */
  	int unit = minor(tp->t_dev);
+ #endif /* !COM_BIDIR */
  	struct zsinfo *zi = zscd.cd_devs[unit >> 1];
  	register struct zs_chanstate *cs = &zi->zi_cs[unit & 1];
  	register int tmp, tmp5, cflag, s;
***************
*** 1509,1515 ****
--- 1589,1599 ----
  
  	if (major(kgdb_dev) != ZSMAJOR)
  		return;
+ #ifdef COM_BIDIR
+ 	unit = BIDIR_COMUNIT(kgdb_dev);
+ #else /* !COM_BIDIR */
  	unit = minor(kgdb_dev);
+ #endif /* !COM_BIDIR */
  	/*
  	 * Unit must be 0 or 1 (zs0).
  	 */
***************
*** 1529,1531 ****
--- 1613,1653 ----
  	kgdb_attach(zs_kgdb_getc, zs_kgdb_putc, (void *)zc);
  }
  #endif /* KGDB */
+ 
+ #ifdef COM_BIDIR
+ /*
+  * comio do physical io needed by bidir_open
+  */
+ 
+ static int
+ zsio(op, arg)
+ 	int op;
+ 	void *arg;
+ {
+ 	struct zs_chanstate *cs = (struct zs_chanstate *)arg;
+ 	int dcd;
+ 	struct tty *tp;
+ 
+ 	tp = cs->cs_ttyp;
+ 
+ 	switch (op) {
+ 	case BD_GET_DCD:
+ 	case BD_DIALIN_OK:
+ 	  zs_modem(cs, 1);
+ 	  dcd = cs->cs_zc->zc_csr & ZSRR0_DCD;
+ 	  if (dcd == 0 && op == BD_DIALIN_OK) {
+ 	    if (cs->cs_softcar || (tp != NULL && (tp->t_cflag & CLOCAL) != 0))
+ 	      dcd = 1;
+ 	  }
+ 	  return dcd;
+ 	case BD_ENABLE:
+ 	  zs_modem(cs, 1);
+ 	  break;
+ 	case BD_DISABLE:
+ 	  zs_modem(cs, 0);
+ 	  break;
+ 	}
+ 	return 0;
+ }
+ 
+ #endif /* COM_BIDIR */
*** sys/arch/sparc/conf/files.sparc.orig	Sat Oct 14 11:19:33 1995
--- sys/arch/sparc/conf/files.sparc	Wed Jan  3 16:19:19 1996
***************
*** 35,40 ****
--- 35,41 ----
  
  device zs at mainbus, obio
  file	arch/sparc/dev/zs.c			zs needs-count
+ file	dev/com_bidir.c				zs com_bidir
  
  device fdc at mainbus {}
  device fd at fdc: disk
*** sys/arch/i386/conf/files.i386.orig	Wed Jan  3 16:25:31 1996
--- sys/arch/i386/conf/files.i386	Sat Dec 30 14:40:24 1995
***************
*** 83,88 ****
--- 83,90 ----
  file	arch/i386/isa/pcvt/pcvt_sup.c	vt needs-flag
  file	arch/i386/isa/pcvt/pcvt_vtf.c	vt needs-flag
  
+ file	dev/com_bidir.c			com com_bidir
+ 
  # PC Mice; Logitech-style, Microsoft-style, and PS/2-style
  device	lms at isa
  file	arch/i386/isa/lms.c		lms needs-flag
>Audit-Trail:
>Unformatted: