Igloopatch
John Welch
jjw at igloo.UUCP
Thu Oct 20 12:18:43 AEST 1988
#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive. Save this into a file, edit it
# and delete all lines above this comment. Then give this
# file to sh by executing the command "sh file". The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-r--r-- 1 root sys 6344 Oct 18 19:55 16550.c
#
echo 'x - 16550.c'
if test -f 16550.c; then echo 'shar: not overwriting 16550.c'; else
sed 's/^X//' << '________This_Is_The_END________' > 16550.c
X/******************************************************************************
X 16550
X a utility that iturns on the FIFO of a NS 16550 chip
X by John Welch, of Igloo Computers
X Public Domain Software
X Hobbyists, feel free to use, abuse, pirate and re-distribute this program.
X Commercial use prohibited without consent of the author.
X Send fan mail to jjw at igloo
X Send flames to jjw@/dev/null
X******************************************************************************/
X#include <sys/types.h>
X#include <sys/io_op.h>
X#include <fcntl.h>
X
Xint fd;
Xvoid outb();
Xextern int errno;
X
Xmain()
X{
X
X
X/*
X I've waded through the NS 16550 docs for several days now,
X and what follows seems accurate enough.
X At any rate, the basic idea is that a 16550 with FIFO enabled
X has (*FINALLY!*) cured igloo's problems with losing newsfeeds. I
X thought I'd make this available to the net in the hopes that it may
X help other people who've been singing the 'microport lost character
X blues.' As microport has been unable to cure this, we finally fixed
X it ourselves. By the way, if you aren't tech-y, this may bore you
X to death. I've got it written to patch tty0 and tty1, and since on a
X 16450 or earlier this register isn't writable it should cause no
X problems. Just un-shar it by typing
X sh 16550.shar
X and compile this with
X cc -o 16550 -O 16550.c
X It might be a good idea to chmod this to 700, to prevent users from
X flushing the buffers on you. Adding this to the inittab file or some
X such place should be all thats needed. Run it once at boot-up and
X forget it.
X A bit of history here: Microport's serial port drivers are
X brain-dead. Apparently the problem is with the high-water mark in
X the kernel, and so it's *not* fixable with new drivers. What this means
X is that you lose characters sometimes. It is particularly noticable
X while doing a 9600-baud newsfeed on one serial line while another
X user on the other line is cat-ing a text file at 300 baud. Usually
X when this happens, you get many errors during the newsfeed and as
X often as not you lose the feed altogether. Microport has been told of
X this problem many times, and they've piddled and fuddled and moped
X around trying to fix it. At first they said we should get faster
X hardware because an 8Mhz AT couldn't handle 9600 baud. Fine, we found
X a place that loaned us a 20Mhz 0-wait 4Mbyte 386 board for a weekend.
X Guess what??? The problem was just as bad as before. Then they sent
X us new driver to install, which did not help the problem. They then
X suggested that we need a smart serial card, to the tune of around
X $1500 or so. They think that 9600 baud cannot be done on these machines.
X That's bull-squat, folks! XENIX does 9600 baud just fine. Microport is
X unable and unwilling to fix this problem. We had to explore alternate
X ways of doing it ourselves, preferrably without costing us hobbyists
X an arm and a leg. We feel we've found an acceptable solution with the
X 16550 UART chip.
X The 16550 is a half-way step between a 'smart' serial card
X and the usual 16450-type 'dumb' card. Using the FIFOs in the 16550
X can not only prevent lost characters, but can result in more efficient
X CPU utilization, with less time wasted in processor overhead to read
X each character sent. It does this by a device called a FIFO buffer, a
X First-In, First-Out scheme. When receiving characters, the 16550 will
X only interrupt the CPU when one of two events happens: When enough
X characters have been received (you can define 'enough' to be 1, 4, 8
X or 14) or when at least 1 character has been received and there has
X not been another character come through for 4 times the time 'width'
X of a character. In this manner, when the CPU finally gets interrupted,
X much more data can be dumped to the CPU at once, cutting down on all
X the overhead involved in context-swiching and so forth.
X In addition, if the CPU takes too long to read the FIFO, the
X 16550 will send its own flow-control to throttle back the incoming
X data, preventing buffer over-runs that have plagued microport from day
X one.
X The 16550 chip is a drop-in replacement for the 16450, and it
X costs about $25 or so (not much more than the 16450). With this chip
X and a trivial amount of software, you can not only cure microports
X brain-dead serial device driver problems, but you can also enjoy most
X of the benefits of a 'smart' card with very little cost.
X What follows is an explaination of what this program does and
X why it does it. If you have multi-port 'dumb' boards with 8250's,
X 16450's or whatever, you *should* be able to replace those chips with
X 16550s and modify this program to set (base+2) for each port.
X tty0's base address is 3f8. The FIFO control register is at
X base+2 (3fa). The byte written at this address is defined as follows:
X
X Bits 7 & 6 define at what level the 16550 interrupts the CPU. 11 is 14
X bytes deep, 10 is 8 bytes deep, 01 is 4 bytes deep and 00 is 1 byte deep.
X
X Bits 5 & 4 are not used, so I set them to 00.
X
X Bit 3 defines the performance of some pins that are not used on the
X 16450, so it's not likely to be of consequence to anything we do. I've
X chosen to keep them performing the way a 16450 would, setting this bit
X 0.
X Bit 2 clears and resets the transmit FIFO.
X Bit 1 clears and resets the Receive FIFO.
X Bit 0 turns the FIFO buffering on.
X To turn on the FIFO at tty1 to a 4-byte level, one should
X write a 0x47 to port 0x2fa. To set tty0 at the maximum FIFO level,
X send 0xc7 to port 0x3fa. To disable FIFOs at tty1 send 0 to 0x2fa.
X*/
X
X
X if ((fd = open("/dev/mem",O_RDWR)) == -1) /* open memory device for read/write */
X {
X perror("Open /dev/mem");
X exit(1);
X }
X
X
X outb(0x3fa,0x87); /* this turns on tty0's FIFO, 8 characters deep */
X outb(0x2fa,0x87); /* this turns on tty1's FIFO, 8 characters deep */
X
X close(fd); /* all done setting up FIFOs. */
X}
X
X
Xvoid outb(portno, data)
Xint portno;
Xunsigned char data;
X{
X io_op_t iop;
X
X iop.io_port = portno;
X iop.io_byte = data;
X errno = 0; /* clear error indicator */
X ioctl(fd, IOCIOP_WB, &iop); /* write the data to that port */
X if (errno)
X printf("Error setting port %04x\n",portno);
X /* send to stdout so they can re-direct easier */
X}
X
________This_Is_The_END________
if test `wc -l < 16550.c` -ne 138; then
echo 'shar: 16550.c was damaged during transit (should have been 138 bytes)'
fi
fi ; : end of overwriting check
exit 0
--
==========================================================================
John Welch <backbone>!jjw at igloo
"Oh, reality - it's not for me, and it makes me laugh,
but fantasy world, and those Disney girls... I'm coming back!"
More information about the Comp.unix.microport
mailing list