*BSD News Article 3464


Return to BSD News archive

Newsgroups: comp.unix.bsd
Path: sserve!manuel!munnari.oz.au!mips!mips!sdd.hp.com!wupost!uunet!email!news.univie.ac.at!news.tu-graz.ac.at!fstgds01!chmr
From: chmr@fstgds01.tu-graz.ac.at (Christoph Robitschko)
Subject: com woes
Message-ID: <1992Aug9.085755.6237@news.tu-graz.ac.at>
Summary: select() now working on com ports
Sender: news@news.tu-graz.ac.at (USENET News System)
Nntp-Posting-Host: fstgds01
Organization: Technical University of Graz, Austria
Date: Sun, 9 Aug 92 08:57:55 GMT
Lines: 175

I had the problem with select() not working on com ports. I got no
response from a post regarding this one, so I started to look into it 
myself. I found out that the com driver calculates unit = minor(dev) -1;
This has the following implications:
	/dev/com1 corresponds to COM0, /dev/com2 to COM1 (very confusing
		in kernel messages)
	It is incompatible with the config file entries com1 at..., com2 at...
	Unpredictible results will occur if someone puts a com0 at.. in
		his config file.
	It is incompatible with the DOS usage of COM1, COM2 (But who cares 8-)
	ttselect() calculates unit = minor(dev), and uses this as an index in
		com_tty. Because this index is different from that used
		in the com driver, select() on /dev/com1 looks at
		/dev/com2 and select() on /dev/com2 looks at an undefined
		entry in com_tty and returns always true.
I include a patch to the stock 0.1 com driver. It simply corrects
"unit = minor(dev) - 1" to "unit = minor(dev)"
If you are running cgd's driver and you need select working (I don't think 
this applies to many people, since I got NO response to my request), there
is a *ugly* workaround: In the initialisation of cdevsw in
/sys/i386/i386/conf.c, replace com_tty with (com_tty -1).

To Chris Demetriou:  Please fix your driver. I could not do it because 
I currently have no ftp connection to agate.


Here is the patch to the *stock 0.1* com driver (diff -p com.c.ori com.c)
--- CUT HERE ---
*** /sys/i386/isa/com.c.ori	Wed Jul 29 11:02:48 1992
--- /sys/i386/isa/com.c	Sat Aug  8 21:49:48 1992
*************** extern int kgdb_rate;
*** 108,114 ****
  extern int kgdb_debug_init;
  #endif
  
! #define	UNIT(x)		(minor(x)-1)
  
  comprobe(dev)
  struct isa_device *dev;
--- 108,114 ----
  extern int kgdb_debug_init;
  #endif
  
! #define	UNIT(x)		(minor(x))
  
  comprobe(dev)
  struct isa_device *dev;
*************** struct isa_device *isdp;
*** 131,137 ****
  	u_char		unit;
  	int		port = isdp->id_iobase;
  
! 	unit = isdp->id_unit - 1;
  	if (unit == comconsole)
  		DELAY(1000);
  	com_addr[unit] = port;
--- 131,137 ----
  	u_char		unit;
  	int		port = isdp->id_iobase;
  
! 	unit = isdp->id_unit;
  	if (unit == comconsole)
  		DELAY(1000);
  	com_addr[unit] = port;
*************** struct isa_device *isdp;
*** 149,155 ****
  	outb(port+com_ier, 0);
  	outb(port+com_mcr, 0 | MCR_IENABLE);
  #ifdef KGDB
! 	if (kgdb_dev == makedev(commajor, unit+1)) {
  		if (comconsole == unit)
  			kgdb_dev = -1;	/* can't debug over console port */
  		else {
--- 149,155 ----
  	outb(port+com_ier, 0);
  	outb(port+com_mcr, 0 | MCR_IENABLE);
  #ifdef KGDB
! 	if (kgdb_dev == makedev(commajor, unit)) {
  		if (comconsole == unit)
  			kgdb_dev = -1;	/* can't debug over console port */
  		else {
*************** comclose(dev, flag, mode, p)
*** 239,245 ****
  	outb(com+com_cfcr, inb(com+com_cfcr) & ~CFCR_SBREAK);
  #ifdef KGDB
  	/* do not disable interrupts if debugging */
! 	if (kgdb_dev != makedev(commajor, unit+1))
  #endif
  	outb(com+com_ier, 0);
  	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 
--- 239,245 ----
  	outb(com+com_cfcr, inb(com+com_cfcr) & ~CFCR_SBREAK);
  #ifdef KGDB
  	/* do not disable interrupts if debugging */
! 	if (kgdb_dev != makedev(commajor, unit))
  #endif
  	outb(com+com_ier, 0);
  	if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 
*************** comintr(unit)
*** 283,289 ****
  	register u_char code;
  	register struct tty *tp;
  
! 	unit--;
  	com = com_addr[unit];
  	while (1) {
  		code = inb(com+com_iir);
--- 283,289 ----
  	register u_char code;
  	register struct tty *tp;
  
! 	unit;
  	com = com_addr[unit];
  	while (1) {
  		code = inb(com+com_iir);
*************** comintr(unit)
*** 300,306 ****
  #define	RCVBYTE() \
  			code = inb(com+com_data); \
  			if ((tp->t_state & TS_ISOPEN) == 0) { \
! 				if (kgdb_dev == makedev(commajor, unit+1) && \
  				    code == FRAME_END) \
  					kgdb_connect(0); /* trap into kgdb */ \
  			} else \
--- 300,306 ----
  #define	RCVBYTE() \
  			code = inb(com+com_data); \
  			if ((tp->t_state & TS_ISOPEN) == 0) { \
! 				if (kgdb_dev == makedev(commajor, unit) && \
  				    code == FRAME_END) \
  					kgdb_connect(0); /* trap into kgdb */ \
  			} else \
*************** comeint(unit, stat, com)
*** 359,365 ****
  #ifdef KGDB
  		/* we don't care about parity errors */
  		if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
! 		    kgdb_dev == makedev(commajor, unit+1) && c == FRAME_END)
  			kgdb_connect(0); /* trap into kgdb */
  #endif
  		return;
--- 359,365 ----
  #ifdef KGDB
  		/* we don't care about parity errors */
  		if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
! 		    kgdb_dev == makedev(commajor, unit) && c == FRAME_END)
  			kgdb_connect(0); /* trap into kgdb */
  #endif
  		return;
*************** comcnprobe(cp)
*** 616,622 ****
  	/* make sure hardware exists?  XXX */
  
  	/* initialize required fields */
! 	cp->cn_dev = makedev(commajor, unit+1);
  	cp->cn_tp = &com_tty[unit];
  #ifdef	COMCONSOLE
  	cp->cn_pri = CN_REMOTE;		/* Force a serial port console */
--- 616,622 ----
  	/* make sure hardware exists?  XXX */
  
  	/* initialize required fields */
! 	cp->cn_dev = makedev(commajor, unit);
  	cp->cn_tp = &com_tty[unit];
  #ifdef	COMCONSOLE
  	cp->cn_pri = CN_REMOTE;		/* Force a serial port console */
--- CUT HERE ---

As usual, use at your own risk.

							Christoph
-- 
------------------------------------------------------------------------
Christoph M. Robitschko  | "the only man who got his work done by Friday
chmr@edvz.tu-graz.ac.at  |             was Robinson Crusoe."