[comp.sys.ibm.pc.programmer] talking to a com port with C

JRD@cc.usu.edu (Joe Doupnik) (06/12/90)

	One major factor, not yet mentioned, about using the Bios serial
port interrupt (14h) for communications is the loss of characters occurring
whenever the screen scrolls one or more lines. The fault lies in the video
bios routines for keeping taking a long time. But then a manual, fast,
assembler procedure to do the same thing also takes a long time. Deep down
then the access rate into video memory is at fault. Thus, expect to lose
two or three characters after a LF which scrolls the screen, on a 4.77MHz
PC and a very swift 33MHz 386 box. (Hint, the video does not run at the
cpu speed.) Without that scrolling part one can easily poll the Bios
for 9600 baud operation on AT's and above.
	As was mentioned a few messages ago on the network, disk activity
also produces major comms outages.
	Here is an assistance but not a total cure. Replace the typical
8250 (and equivalent on AT's and above) with a National Semiconductor
16550A UART chip (please, note that A!). This chip is essentially plug
replaceable. The benefits acrue if the comms program can put the chip
into receiver-FIFO mode so it can buffer up to 16 characters before being
accessed. The Bios runs the chip without the FIFO. And a plain 16550 is
no help at all because it has bugs in the FIFO mode.
	I put one of these chips in my 8MHz AT and with MS-DOS Kermit
the loss of characters at very high baud rates (38,400 and up) from disk
activity dropped way way down. Kermit puts the chip into FIFO mode and
uses interrupt driven i/o, naturally. Other comms programs are beginning to
do the same.
	Finally, one might reasonably ask if the serial port Bios pathway
is intrinsically too slow and thus ought to be abandoned at first glance.
Surprizingly, the answer is no! I run Kermit over serveral packages which
communicate with Kermit via that selfsame Int 14, one character at a time,
have to poll the darned thing, pathway. A typical throughput on a 20MHz 386
is over 15,000 baud (including overhead for Kermit packet work). An interrupt
on a PC is basically a very slow instruction. Even so this path can go fast.
	Joe D.

david@csource.OZ.AU (david nugent) (06/15/90)

In <26067@cc.usu.edu> JRD@cc.usu.edu (Joe Doupnik) writes:


 >	Here is an assistance but not a total cure. Replace the typical
 > 8250 (and equivalent on AT's and above) with a National Semiconductor
 > 16550A UART chip (please, note that A!). This chip is essentially plug
 > replaceable. The benefits acrue if the comms program can put the chip
 > into receiver-FIFO mode so it can buffer up to 16 characters before being
 > accessed. The Bios runs the chip without the FIFO. And a plain 16550 is
 > no help at all because it has bugs in the FIFO mode.
 

There's a lot of misconception about 16550's of all types, but in general
it is true that the BIOS runs it in 16450 mode - ie. without the FIFO's,
but only because that's the default power-on state of these chips.  If
you're not interrupt driving these chips, then you can easily enable the
FIFO's and have the BIOS use them immediately.  You'll still get severe
receiver overruns at high speeds (9600+ baud), but a LOT less.  At least
it should make non-interrupt driven comms via INT 14H at 1200-2400 baud
possible.

The other misconception about them is that while you can change the
trigger levels on them to 1, 4, 8 or 14 bytes, you ALWAYS have a 
16-byte buffer both ways once the FIFO's are enabled.  It's just that
a receiver interrupt gets generated when the receiver FIFO gets occupied
up to that many bytes.

You'll also find that the majority of PC, AT and AT386 BIOS sets will
not even recognise a 16550 series UART.  The result is that several
popular programs no longer seem to work, since the BIOS data area is
not "patched" by POST to include the port addresses, and the hardware
bits returned by INT 11H don't reflect their presence - there are
various fixes available, but someone not knowing that or having not
having access to those fixes can be completely frustrated by the fact
that his favourite communications programs now longer function....

Here's a little code to turn the FIFO's on, to really get the most
from the system's BIOS.  As to how hard you can then drive the BIOS,
I can't give any specific figures, since it's too dependent on your
own system's speed and what other interrupt driven devices are in use
(such as network cards etc.).

This may be entered using DOS's DEBUG, and in this case switches on
FIFO's for COM1 (I specifically use the port's base address here so
that you can easily replace 3f8 with whatever base address you need
to use, such as 2f8 for COM2):

	C>DEBUG
	-a
	xxxx:0100	mov	DX,3f8
	xxxx:0103	add	DX,2
	xxxx:0106	mov	AL,01
	xxxx:0108	out	DX,AL
	xxxx:0109	int	20
	xxxx:010B
	-rcx
	:b
	-nfifo.com
	-w
	Writing 000B bytes
	-q
	C>

BTW, there's no harm done at all by running this with an 8250, 16450
or similar UART present.  It just doesn't have any effect, since the
register you're writing to in that case is 'write-only' on those
chips.

To enable the various trigger levels (and as I implied above, there's
no real advantage in using more than 1 byte unless you start using an
interrupt driven driver, since you ALWAYS get full 16-byte buffers no
matter how many bytes the trigger is set to), you can substitute the
following values into the "mov AL,xx" statement above:

	1 byte		=	01
	4 bytes		=	41
	8 bytes		=	81
	14 bytes	=	C1

To disable the FIFO's, just substitute that same value for 0.

A better solution is, of course, to use an interrupt driven INT 14H
replacement, but if that's not available, the above certainly should
help.

david

-- 
         * Unique Computing Pty Ltd, Melbourne, Australia. *
       david@csource.oz.au  3:632/348@fidonet  28:4100/1@signet