*BSD News Article 81886


Return to BSD News archive

Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!nntp.coast.net!howland.erols.net!surfnet.nl!news.tue.nl!news.IAEhv.nl!adv.IAEhv.nl!adv.IAEhv.nl!not-for-mail
From: devet@adv.IAEhv.nl (Arjan de Vet)
Newsgroups: comp.unix.bsd.freebsd.misc,alt.comp.periphs.mainboard.asus
Subject: Re: Problem with com ports on ASUS P55T2P4 (solution)
Date: 30 Oct 1996 21:56:57 +0100
Organization: Internet Access Eindhoven, the Netherlands
Lines: 113
Message-ID: <558fep$18l@adv.IAEhv.nl>
References: <5513ro$2i8@bpeters.uucp>
NNTP-Posting-Host: adv.iaehv.nl
Xref: euryale.cc.adfa.oz.au comp.unix.bsd.freebsd.misc:30248 alt.comp.periphs.mainboard.asus:27021

In article <5513ro$2i8@bpeters.uucp>,
Bruce Peterson <peterson@mail.cyberoptics.com> wrote:

>I just purchased an ASUS P55T2P4 motherboard (P120) for use with FreeBSD
>2.1.5.  I connected my modem (28.8kbps, 38400 dte) to a com port on the
>motherboard, but uucp gave up about 100k into each call, with an error
>message saying "Too many protocol 'i' errors."  The received packets arrive
>continuously, and the acks are transmitted regularly, as observed from modem
>LED activity.  The second com port on the motherboard exhibited the same
>problem.  I put an old ISA i/o board (with a 16550 UART) into the system,
>and uucp went for an hour and a half with no errors.  The only other boards
>in the system are an ISA Tseng ET4000 VGA board and an Adaptec 1542 SCSI
>adapter.
>
>Is there a known problem with the UART design on this motherboard, or
>could this be a defective unit?

Yes, I had exactly the same. The following kernel patch for
sys/i386/isa/sio.c fixes it.

Arjan

--- sio.c.2.1.5	Sat Apr 13 17:01:25 1996
+++ sio.c	Tue Oct 15 21:38:27 1996
@@ -443,7 +443,7 @@
 	 * XXX what about the UART bug avoided by waiting in comparam()?
 	 * We don't want to to wait long enough to drain at 2 bps.
 	 */
-	outb(iobase + com_cfcr, CFCR_DLAB);
+	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
 	outb(iobase + com_dlbl, COMBRD(9600) & 0xff);
 	outb(iobase + com_dlbh, (u_int) COMBRD(9600) >> 8);
 	outb(iobase + com_cfcr, CFCR_8BITS);
@@ -1601,6 +1601,8 @@
 	int		cflag;
 	struct com_s	*com;
 	int		divisor;
+	u_char		dlbh;
+	u_char		dlbl;
 	int		error;
 	Port_t		iobase;
 	int		s;
@@ -1712,8 +1714,18 @@
 
 	if (divisor != 0) {
 		outb(iobase + com_cfcr, cfcr | CFCR_DLAB);
-		outb(iobase + com_dlbl, divisor & 0xFF);
-		outb(iobase + com_dlbh, (u_int) divisor >> 8);
+		/*
+		 * Only set the divisor registers if they would change,
+		 * since on some 16550 incompatibles (UMC8669F), setting
+		 * them while input is arriving them loses sync until
+		 * data stops arriving.
+		 */
+		dlbl = divisor & 0xFF;
+		if (inb(iobase + com_dlbl) != dlbl)
+			outb(iobase + com_dlbl, dlbl);
+		dlbh = (u_int) divisor >> 8;
+		if (inb(iobase + com_dlbh) != dlbh)
+			outb(iobase + com_dlbh, dlbh);
 	}
 	outb(iobase + com_cfcr, com->cfcr_image = cfcr);
 	if (!(tp->t_state & TS_TTSTOP))
@@ -2115,6 +2127,8 @@
 	struct siocnstate	*sp;
 {
 	int	divisor;
+	u_char	dlbh;
+	u_char	dlbl;
 	Port_t	iobase;
 
 	/*
@@ -2127,12 +2141,22 @@
 	outb(iobase + com_ier, 0);	/* spltty() doesn't stop siointr() */
 	siocntxwait();
 	sp->cfcr = inb(iobase + com_cfcr);
-	outb(iobase + com_cfcr, CFCR_DLAB);
+	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
 	sp->dlbl = inb(iobase + com_dlbl);
 	sp->dlbh = inb(iobase + com_dlbh);
+	/*
+	 * Only set the divisor registers if they would change, since on
+	 * some 16550 incompatibles (Startech), setting them clears the
+	 * data input register.  This also reduces the effects of the
+	 * UMC8669F bug.
+	 */
 	divisor = ttspeedtab(comdefaultrate, comspeedtab);
-	outb(iobase + com_dlbl, divisor & 0xFF);
-	outb(iobase + com_dlbh, (u_int) divisor >> 8);
+	dlbl = divisor & 0xFF;
+	if (sp->dlbl != dlbl)
+		outb(iobase + com_dlbl, dlbl);
+	dlbh = (u_int) divisor >> 8;
+	if (sp->dlbh != dlbh)
+		outb(iobase + com_dlbh, dlbh);
 	outb(iobase + com_cfcr, CFCR_8BITS);
 	sp->mcr = inb(iobase + com_mcr);
 	/*
@@ -2154,9 +2178,11 @@
 	 */
 	siocntxwait();
 	iobase = siocniobase;
-	outb(iobase + com_cfcr, CFCR_DLAB);
-	outb(iobase + com_dlbl, sp->dlbl);
-	outb(iobase + com_dlbh, sp->dlbh);
+	outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
+	if (sp->dlbl != inb(iobase + com_dlbl))
+		outb(iobase + com_dlbl, sp->dlbl);
+	if (sp->dlbh != inb(iobase + com_dlbh))
+		outb(iobase + com_dlbh, sp->dlbh);
 	outb(iobase + com_cfcr, sp->cfcr);
 	/*
 	 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.