UARTs (Universal Asynchronous Receiver
Transmitter) are serial chips on your PC motherboard (or on an
internal modem card). The UART function may also be done on a chip
that does other things as well. On older computers like many 486's,
the chips were on the disk IO controller card. Still older computer
have dedicated serial boards.

When PCs all had parallel bus architecture, the UART's purpose was to
convert bytes from the PC's parallel bus to a serial bit-stream. The
cable going out of the serial port is serial and has only one wire for
each direction of flow. The serial port sends out a stream of bits,
one bit at a time. Conversely, the bit stream that enters the serial
port via the external cable was converted to parallel bytes that the
computer can understand. UARTs deal with data in byte sized pieces,
which is conveniently also the size of ASCII characters.

Say you have a terminal hooked up to a serial port on your PC. When
you type a character, the terminal gives that character to its
transmitter (also a UART). The transmitter sends that byte out onto
the serial line, one bit at a time, at a specific rate. On the PC
end, the receiving UART takes all the bits and reconstruct the byte
(parallel on older PCs) and puts it in a buffer. For newer PCs that
might have a PCI-e serial port, the UART doesn't need to convert
parallel-to-serial since the PCI-e "bus" is already a serial line.
But the PCI-e line carries an encoded signal which must be decoded and
then greatly slowed down to the speed of the RS-232 serial line.

Along with converting between serial and parallel, the UART does some
other things as a byproduct (side effect) of its primary task. The
voltage used to represent bits is also converted (changed). Extra
bits (called start and stop bits) are added to each byte before it is
transmitted. See the Serial-HOWTO section
Voltage Waveshapes for details. Also, while the flow rate
(in bytes/sec) on the parallel bus inside the computer is very high,
the flow rate out the UART on the serial port side of it is much
lower. The UART has a fixed set of rates (speeds) which it can use at
its serial port interface.

There are two basic types of UARTs: dumb UARTS and FIFO UARTS.
Dumb UARTs are the 8250, 16450, early 16550, and early 16650. They
are obsolete but if you understand how they work it's easy to
understand how the modern ones work with FIFO UARTS ( late 16550,
16550A, and higher numbers). Note that the driver for all of them is
still labeled a "8250" driver in Linux where you may see it in compile
options if you compile your own kernel, etc.

There is some confusion regarding 16550. Early models had a bug and
worked properly only as 16450's (no FIFO). Later models with the bug
fixed were named 16550A but many manufacturers did not accept the name
change and continued calling it a 16550. Most all 16550's in use
today are like 16550A's. Linux will report it as being a 16550A even
though your hardware manual (or a label note) says it's a 16550. A
similar situation exists for the 16650 (only it's worse since the
manufacturer allegedly didn't admit anything was wrong). Linux will
report a late 16650 as being a 16650V2. If it reports it as 16650 it
is bad news and only is used as if it had a one-byte buffer.

To understand the differences between dumb and FIFO (First In,
First Out queue discipline) first let's examine what happens when a
UART has sent or received a byte. The UART itself can't do anything
with the data passing thru it, it just receives and sends it. For the
obsolete dumb UARTS, the CPU gets an interrupt from the serial device
every time a byte has been sent or received. The CPU then moves the
received byte out of the UART's buffer and into memory somewhere, or
gives the UART another byte to send. The obsolete 8250 and 16450
UARTs only have a 1 byte buffer. That means, that every time 1 byte
is sent or received, the CPU is interrupted. At low transfer rates,
this is OK. But, at high transfer rates, the CPU gets so busy dealing
with the UART, that is doesn't have time to adequately tend to other
tasks. In some cases, the CPU does not get around to servicing the
interrupt in time, and the byte is overwritten, because they are
coming in so fast. This is called an "overrun" or "overflow".

FIFO UARTs help solve this problem. The 16550A (or 16550) FIFO chip
comes with 16 byte FIFO buffers. This means that it can receive up to
14 bytes (or send 16 bytes) before it has to interrupt the CPU. Not
only can it wait for more bytes, but the CPU then can transfer all (14
to 16) bytes at a time. This is a significant advantage over the
obsolete UARTs, which only had 1 byte buffers. The CPU receives less
interrupts, and is free to do other things. Data is rarely lost.
Note that the interrupt threshold of FIFO buffers (trigger level) may
be set at less than 14. 1, 4 and 8 are other possible choices. As of
late 2000 there was no way the Linux user could set these directly
(setserial can't do it). While many PC's only have a 16550 with
16-byte buffers, better UARTS have even larger buffers.

Note that the interrupt is issued slightly before the buffer gets full
(at say a "trigger level" of 14 bytes for a 16-byte buffer). This
allows room for a couple more bytes to be received before the
interrupt service routine is able to actually fetch all these bytes.
The trigger level may be set to various permitted values by kernel
software. A trigger level of 1 will be almost like an obsolete UART
(except that it still has room for 15 more bytes after it issues the
interrupt).

Now consider the case where you're on the Internet. It's just sent
you a short webpage of text. All of this came in thru the serial
port. If you had a 16-byte buffer on the serial port which held back
characters until it had 14 of them, some of the last several
characters on the screen might be missing as the FIFO buffer waited to
get the 14th character. But the 14th character doesn't arrive since
you've been sent the entire page (over the phone line) and there are
no more characters to send to you. It could be that these last
characters are part of the HTML formatting, etc. and are not
characters to display on the screen but you don't want to lose format
either.

There is a "timeout" to prevent the above problem. The "timeout"
works like this for the receive UART buffer: If characters arrive one
after another, then an interrupt is issued only when say the 14th
character reaches the buffer. But if a character arrives and the next
character doesn't arrive soon thereafter, then an interrupt is issued
anyway. This results in fetching all of the characters in the FIFO
buffer, even if only a few (or only one) are present. There is also
"timeout" for the transmit buffer as well.

You may wonder why the FIFO buffers are not larger. After all,
memory is cheap and it wouldn't cost much more to use buffers in the
kilo-byte range. The reason is flow control. Flow control stops the
flow of data (bytes) on serial line when necessary. If a stop signal
is sent to serial port, then the stop request is handled by software
(even if the flow control is "hardware"). The serial port hardware
knows nothing about flow control.

If the serial port buffer contains 64 bytes ready to send when it
receives a flow control signal to stop sending, it will send out the
64 bytes anyway in violation of the stop request. There is no
stopping it since it doesn't know about flow control. If the buffer
was large, then many more bytes would be sent in violation of flow
control's request to stop.

For V.90 56k modems, it may be a several percent faster with a 16650
(especially if you are downloading large uncompressed files). The
main advantage of the 16650 is its larger buffer size as the extra
speed isn't needed unless the modem compression ratio is high. Some
56k internal modems may come with a 16650 ??

Non-UART, and intelligent multiport boards use DSP chips to
do additional buffering and control, thus relieving the CPU
even more. For example, the Cyclades Cyclom, and Stallion
EasyIO boards use a Cirrus Logic CD1400 RISC UART, and many
boards use 80186 CPUs or even special RISC CPUs, to handle the
serial IO.

Many 486 PCs (old) and all Pentiums (or the like) should have at least
16550As (usually called just 16550's) with FIFOs. Some better
motherboards today (2000) even have 16650s. For replacing obsolete
UARTs with newer ones in pre 1990 hardware see the Appendix: Obsolete
...