Hi everyone,
I'd like to follow up a post I made to bugs last year entitled "5.4 with
Digi serial board drops characters (silo overflow)". Link
http://openbsd-archive.7691.n7.nabble.com/5-4-with-Digi-serial-board-drops-characters-silo-overflow-td244124.html
I have since had a chance to re-visit the issue under OpenBSD 5.7 (I
suspect 5.8 still has the same issue) and made some progress wrt what's
going on. It would appear that it's simply a matter of the serial FIFO
buffer length being zero when it should be much larger. Here is a
snippet of relevant dmesg output:
com4 at puc0 port 0 apic 8 int 16: ns16550a, 16 byte fifo
com4: probed fifo depth: 0 bytes
Now there are a number of problems as I see it. The first line shows a
16550a and a 16 byte FIFO. The Digi we are using is the 8 port Neo
PCIe. It claims to be 16C850 compatible from which we can infer a 128
byte FIFO. So first thing is the correct chip isn't being detected.
Still, I'm guessing the Digi chip is 16550a backwards compatible so in
any case this should still work.
The second line shows the probed FIFO depth being zero. Looking through
the kernel code (/usr/src/sys/dev/ic/com.c - I'm actually looking at 5.7
but from a quick look it appears that 5.8 might be identical) if the
probed depth (zero) is less than the 16 byte above value the shorter of
the two is used, ie. zero.
/* For safety, always use the smaller value. */
if (sc->sc_fifolen > len) {
printf("%s: probed fifo depth: %d bytes\n",
sc->sc_dev.dv_xname, len);
sc->sc_fifolen = len;
}
A 'zero' FIFO explains why I'm getting dropped characters when I run a
couple of ports up at speeds of 19k2 or more.
Looking through the com.c file there is mention of the 16850 chip, but
that code appears to be commented out with the comment /* until com
works with large FIFOs */ Hmm... Google shows the OpenBSD 2.3 release
changes including "Add support for the XR16850 serial chip (128 byte
fifos)". So I guess something has happened between OpenBSD 2.3 and
OpenBSD 5.7 to warrant its removal.
Assuming for now that we can make do with just 16 byte FIFOs I thought
I'd try a hack to see if I could get it to work. Here is my hack:
/* For safety, always use the smaller value. */
if (sc->sc_fifolen > len) {
printf("%s: probed fifo depth: %d bytes\n",
sc->sc_dev.dv_xname, len);
/* MJV modification 17-Dec-2015 */
/* Probe doesn't work on Digi Neo 8 PCIe so */
/* don't rely on it */
if (len == 0)
printf("%s: override, using %d byte FIFO\n",
sc->sc_dev.dv_xname, sc->sc_fifolen);
else
sc->sc_fifolen = len;
}
Well I tried it out and it works; no more missing serial characters.
Unfortunately this code change is a real hack and would potentially mess
up your system if you had other serial boards that don't have a FIFO
(but are somehow detected as having a FIFO).
I would think a better fix would be to fix the 16850 sections (and make
large FIFOs work???) but this sounds like a potential can of worms
otherwise I would have tried it.
So maybe this hack is useful to anyone out there with the same Digi
Neo-8 PCIe card and who is also having problems with dropped characters.
If anyone is maintaining the serial code, and wishes to fix it properly
I'm happy to test out the changes on the card here.
Also thoughts for a more elegant hack would be welcome.
Regards,
-Martin
--
R A Ward Ltd. | We take the privacy of our customers seriously.
Christchurch | All sensitive E-Mail attachments MUST be encrypted.
New Zealand