[comp.unix.microport] Igloopatch Revisited

learn@igloo.Scum.COM (william vajk) (02/23/89)

Lots of mail arrived requesting the igloopatch. Lots of mail I sent
in response bounced. So I've elected to post this again.

I note that others have had difficulty invoking the code, with system
freezups.  The mileage we've gotten here at igloo has been excellent.
Some of the problems may be hardware related, I don't know. As far as
serial port problems in general are concerned, there are so many SIO
cards on the marketplace, and so many of them are no-real-brand that
it's difficult to discuss why some work, and others don't. I do know
that of 5 different two port SIO cards that have been plugged into this
motherboard, only three ran with two ports, and two with only 1, under
uport, so there's some funkiness about the mix. Bringing up the system
under ms-dos, all cards worked to both ports.

Recent history (means I still have the manuals) indicates two cards
that worked fine are :

Biostar BS-301AT ( 2 serial, 1 parallel, 1 game )

IOSA (v-3.0) (Brand ???  purchased from Elektech, Chicago)

I recently replaced the Biostar as it had one of the UARTs soldered
in place, and had run for months with only one line FIFO'd. The IOSA
has the advantage of socketed UARTs.

Some time back, igloo's motherboard was replaced with a Suntach (?sp.)

This motherboard didn't like to talk to some of the brand name memory
expansion cards (everex comes to mind immediately) at any speed. I replaced
the crystal for high speed to run the system at 10 MHz and invoked 0 waits.
The only readily available memory expansion card the motherboard would talk
to correctly is the Kouwei KW-518. There may be others, I only looked till
I found one that worked (recognized expansion memory at bootup.)

The kernel is created running the standard commands that come with the
linkkit.

With one (previously) and two (presently) 16550A UARTs in the SIO card,
the 16550 code is invoked as part of the /etc/inittab sequence.

Stuart wrote a long article about this code (which follows) at the
time we first posted it. There may well be some flaws inherent in the
mode of attack, I don't know. Frankly, I would be concerned about such
if we experienced any problems, but there have been none. The uucp polls
have co-existed with all sorts of heavy activity on the other tty as well
as from the consoles. Granted, the thruput slows down appreciably, but
I have not seen the alarms I had running raw with 16450's, nor have I
lost a feed. I can watch the telebit lights stop and restart at 9600,
without adverse notes coming to screen running -x5. Dammit, there was a
time that just flagging -x5 was enough to create an alarm sequence and
lose the feed.  Today, for kicks, I ran uucico with an x9 flag. Not only
did it fly well, but could be interrupted at will using the scroll lock
key, and reinstated without ever creating an alarm. Running the same hardware 
in the same experimental mode without the FIFO's enabled does create an alarm 
sequence, and loses the feed.

Average speed for transfers based on 9600 baud fall in the high 700 char 
range. 19.2 with this hardware and software is a dream to forget.

Based on what I've been reading, and the mail I'm getting, mileage is
varying on other systems. Sorry neither John Welch nor I have time
to lend individual assistance. What follows is the '286 version, 
exactly the same code that has performed so well here. Good luck with
it. If you find modifications which help, please post them and share
the improvements with others. 


Bill Vajk                     | A person of quality is never intimidated.
learn@igloo                   | 




/******************************************************************************
                            16550 
      a utility that iturns on the FIFO of a NS 16550 chip
             by John Welch, of Igloo Computers
                     Public Domain Software
 Hobbyists, feel free to use, abuse, pirate and re-distribute this program.
       Commercial use prohibited without consent of the author.
                   Send fan mail to jjw@igloo
                  Send flames to jjw@/dev/null
******************************************************************************/
#include <sys/types.h>
#include <sys/io_op.h>
#include <fcntl.h>

int fd;
void outb();
extern int errno;

main() 
{


/*
		I've waded through the NS 16550 docs for several days now,
	and what follows seems accurate enough.
	At any rate, the basic idea is that a 16550 with FIFO enabled
	has (*FINALLY!*) cured igloo's problems with losing newsfeeds. I
	thought I'd make this available to the net in the hopes that it may
	help other people who've been singing the 'microport lost character
	blues.' As microport has been unable to cure this, we finally fixed
	it ourselves. By the way, if you aren't tech-y, this may bore you
	to death. I've got it written to patch tty0 and tty1, and since on a
	16450 or earlier this register isn't writable it should cause no
	problems. Just un-shar it by typing
		sh 16550.shar
	and compile this with
		cc -o 16550 -O 16550.c
	It might be a good idea to chmod this to 700, to prevent users from
	flushing the buffers on you. Adding this to the inittab file or some
	such place should be all thats needed. Run it once at boot-up and
	forget it.
		A bit of history here: Microport's serial port drivers are
	brain-dead. Apparently the problem is with the high-water mark in
	the kernel, and so it's *not* fixable with new drivers. What this means
	is that you lose characters sometimes. It is particularly noticable
	while doing a 9600-baud newsfeed on one serial line while another
	user on the other line is cat-ing a text file at 300 baud. Usually
	when this happens, you get many errors during the newsfeed and as
	often as not you lose the feed altogether. Microport has been told of
	this problem many times, and they've piddled and fuddled and moped
	around trying to fix it. At first they said we should get faster
	hardware because an 8Mhz AT couldn't handle 9600 baud. Fine, we found
	a place that loaned us a 20Mhz 0-wait 4Mbyte 386 board for a weekend.
	Guess what??? The problem was just as bad as before. Then they sent
	us  new driver to install, which did not help the problem. They then
	suggested that we need a smart serial card, to the tune of around
	$1500 or so. They think that 9600 baud cannot be done on these machines.
	That's bull-squat, folks! XENIX does 9600 baud just fine. Microport is
	unable and unwilling to fix this problem. We had to explore alternate
	ways of doing it ourselves, preferrably without costing us hobbyists
	an arm and a leg. We feel we've found an acceptable solution with the
	16550 UART chip.
		The 16550 is a half-way step between a 'smart' serial card
	and the usual 16450-type 'dumb' card. Using the FIFOs in the 16550
	can not only prevent lost characters, but can result in more efficient
	CPU utilization, with less time wasted in processor overhead to read
	each character sent. It does this by a device called a FIFO buffer, a
	First-In, First-Out scheme. When receiving characters, the 16550 will
	only interrupt the CPU when one of two events happens: When enough
	characters have been received (you can define 'enough' to be 1, 4, 8
	or 14) or when at least 1 character has been received and there has
	not been another character come through for 4 times the time 'width'
	of a character. In this manner, when the CPU finally gets interrupted,
	much more data can be dumped to the CPU at once, cutting down on all
	the overhead involved in context-swiching and so forth.
		In addition, if the CPU takes too long to read the FIFO, the
	16550 will send its own flow-control to throttle back the incoming
	data, preventing buffer over-runs that have plagued microport from day
	one.
		The 16550 chip is a drop-in replacement for the 16450, and it
	costs about $25 or so (not much more than the 16450). With this chip
	and a trivial amount of software, you can not only cure microports
	brain-dead serial device driver problems, but you can also enjoy most
	of the benefits of a 'smart' card with very little cost.
		What follows is an explaination of what this program does and
	why it does it. If you have multi-port 'dumb' boards with 8250's,
	16450's or whatever, you *should* be able to replace those chips with
	16550s and modify this program to set (base+2) for each port.
		tty0's base address is 3f8. The FIFO control register is at
	base+2 (3fa). The byte written at this address is defined as follows:

	 Bits 7 & 6 define at what level the 16550 interrupts the CPU. 11 is 14
	bytes deep, 10 is 8 bytes deep, 01 is 4 bytes deep and 00 is 1 byte deep.

	 Bits 5 & 4 are not used, so I set them to 00.

	 Bit 3 defines the performance of some pins that are not used on the
	16450, so it's not likely to be of consequence to anything we do. I've
	chosen to keep them performing the way a 16450 would, setting this bit
	0.
	 Bit 2 clears and resets the transmit FIFO.
	 Bit 1 clears and resets the Receive FIFO.
	 Bit 0 turns the FIFO buffering on.
		To turn on the FIFO at tty1 to a 4-byte level, one should
	write a 0x47 to port 0x2fa. To set tty0 at the maximum FIFO level,
	send 0xc7 to port 0x3fa. To disable FIFOs at tty1 send 0 to 0x2fa.
*/


    if ((fd = open("/dev/mem",O_RDWR)) == -1) /* open memory device for read/write */
    {
        perror("Open /dev/mem");
        exit(1);
    }


    outb(0x3fa,0x87); /* this turns on tty0's FIFO, 8 characters deep */
    outb(0x2fa,0x87); /* this turns on tty1's FIFO, 8 characters deep */

    close(fd); /* all done setting up FIFOs. */
}


void outb(portno, data)
int portno;
unsigned char data;
{
    io_op_t  iop;

    iop.io_port = portno;
    iop.io_byte = data;
    errno = 0; /* clear error indicator */
    ioctl(fd, IOCIOP_WB, &iop); /* write the data to that port */
    if (errno)
	printf("Error setting port %04x\n",portno);
        /* send to stdout so they can re-direct easier */
}

rd@tarpit.UUCP (Bob Thrush x210) (02/25/89)

In article <1162@igloo.Scum.COM> learn@igloo.UUCP (william vajk) writes:
> [deleted]
>Average speed for transfers based on 9600 baud fall in the high 700 char 
>range. 19.2 with this hardware and software is a dream to forget.

  My milage with a 6 Mhz 1 wait original IBM AT with 16550 and
TB+:
  ~600 chars/sec uucp receive rate on an otherwise idle system.
  ~800 chars/sec uucp transmit rate on an otherwise idle system.
The above numbers were collected from the other end of the connection,
since the clock interrupts are mostly missed during TB+ activity
thus rendering the local clock useless.

  The TB+/16550 combo has been working very well for me since July, 1988.
I have not experienced the lockup that others have reported.

  Although I'm not using the igloopatch, I have a script that uses
/src/outb.c to enable the fifo's.  I experimented with different 
fifo thresholds and was unable to measure any significant difference 
(other than the system would not work at 9600 when fifo's were disabled).
I wound up with 'outb 2fa 01; outb 3fa 01'.

  The bottom line is that enabling the 16550 fifo allows 9600 baud uucp
operation with the stock 2.4 serial drivers.  I believe that higher
performance (maybe 19200) would be possible if a driver were crafted
specifically to take advantage of the 16550 and implement hardware handshake
with the TB+.

>
> [most of igloopatch deleted]
>
>		In addition, if the CPU takes too long to read the FIFO, the
>	16550 will send its own flow-control to throttle back the incoming
>	data, preventing buffer over-runs that have plagued microport from day
>	one.

  I have a 16550A preliminary data sheet and did not see this reference.
Could you elaborate on this "other flow-control" mechanism?  As I recall, 
the RTS and DTR pins are controlled only by explicitly programming the 
modem control register.

-- 
Bob Thrush                 UUCP: {rtmvax,ucf-cs}!tarpit!rd
Automation Intelligence,   1200 W. Colonial Drive, Orlando, Florida 32804