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.