[TriEmbed] intentional re-interrupting shaggy dog story

Peter Soper pete at soper.us
Wed Jan 27 23:50:14 CST 2021


This may be timed to help some of you night owls get to sleep...

Around 1981 I was part of a local startup called Network Products making 
a statistical multiplexer as a first product. It had an 8MHz Intel 8088 
(8 bit bus x86) and 10 kilobytes of static ram (RCA CDM6116) and 12k of 
code ROM (2732). It had eight async UART ports (Rockwell R6551) running 
from 110 to 19200 baud and one synchronous USART port (Intel 8274) for 
running eight serial devices with a single leased phone line and 
synchronous modems. One identical device on each end multiplexed and 
demultiplexed the data giving the user eight async ports sharing the 
aggregate stream that could be up to a couple megabaud, but in customer 
setting the speed was limited to about 56k by the huge cost of leased 
lines. The hardware also included an Intel 8257 for DMA, and an AMD 8253 
for interval timing. But until I opened up the system I kept and looked 
at it an hour ago my memory was that it had priority interrupt control 
via an Intel 8259. But that memory was false: the 8259 didn't come in 
until we started on the modular datacomm product line that followed the 
first three simple devices. So all interrupts in the system were at the 
same priority, and that realization caused some details to fit properly.

One requirement was all eight async ports sending and receiving data at 
19.2k baud simultaneously without data loss. That's a character every 
32.5usec and the UARTs had just one byte of buffering and were simply 
interrupt driven. The USART feeding/draining the UARTs did use the DMA 
and so there was only one interrupt per HDLC packet sent or received or 
some exception happening. Steve Schleimer, an ex-Data General software 
Jedi Knight who was part of the "Fountainhead Project" described in /The 
Soul of a New Machine/, wrote the data aggregator/deaggregator and was 
architect/CTO while I wrote the handler for async data and the RTOS and 
had no non-dev duties. This was a simple RTOS that supported just 
exactly the required features with things like task control blocks 
statically declared for exactly the number of tasks required, etc. The 
term "thread" might have existed in Unix land, but not in our ex-DG 
world (I worked on other projects and wasn't involved in what Kidder 
documented but Schleimer was lead on an earlier project I took over to 
free him up and worked I worked closely with the Eagle guys porting a 
commercial language compiler/VM/runtime/source level debugger to their 
second gen operating system called AOS. The Fountainhead work was top 
secret in some apartments down route 9 from the main DG site in Westboro 
and had its own LOCKED part of the building on Alexander Drive in Durham 
after the move south). Preemptive scheduling was required and so the mux 
RTOS wasn't a trivial system, with per-task stacks, dynamic memory 
allocation and a few other whistles.

But we couldn't avoid async receiver overruns (i.e. a newly arrived char 
fully deserialized but the UART buffer still full) at full speed. After 
a lot of weeping and gnashing of teeth it dawned on me that I could 
modify the USART interrupt handler to save its state and return from its 
interrupt without clearing the interrupt source and this allowed more 
UART interrupts to get through before the sync hardware interrupted 
again to get the synchronous data operation completed. Don't ask me how 
that worked. Maybe I could clear the 8274 but cause a DMA interrupt or 
possibly the hardware designer, Steve Haefle (also ex-Fountainhead) 
provided some kind of ad hoc round robin interrupt control like with a 
shift register or something that put the next 8274 interrupt at the end 
of the line. I'm not tempted to reverse engineer the PCB to figure it 
out. I put a good photo of the PCB here 
<http://triembed.org/images/NetworkProductsBabyMuxPCB.jpg> in case 
anybody wants to take a crack at it. So the sync interrupt service was 
done in multiple operations while incoming async chars were buffered on 
time. (Two smaller plug in boards not shown provided the other six async 
lines with their UARTS and additional buffer memory.

The part I have a hard time understanding after all this time is how the 
8088 assembly code could have been so optimized that this all ran fast 
enough and fit. The initial 8088 performance numbers we got from Intel 
turned out to be "that which is not true", as they wouldn't give us 
cycle counts. Because 16 bit addresses and data took pairs of memory bus 
operations and the actual vs wishful thinking cycles for typical 
instructions were many in total it was something like a MIP or one and a 
half from memory. So to get a new async byte and buffer, goosing the 
task scheduler as needed, etc was vaguely 50 machine instructions. I 
went for a stretch of years mis-remembering the ROM size by a factor of 
two and finally scraped a label off to see they are 2732 (i.e. three at 
four kilobytes each). Our next gen modular product had fist fulls of 
27128s for each of several 68K boards in a hot-pluggable backplane. I 
didn't realize the value of keeping a paper copy of the source code back 
then but wish I had asked permission to do that. I also remember the ROM 
space being a serious pain. The front panel UI ended up being run with a 
microscopic virtual machine with extremely dense "byte code" that I 
cooked up because a regular implementation in straight assembler had no 
hope of fitting.

And no, the device would not move data through all the async ports at 
full speed for more than a very short time because there were so few 
cycles left for aggregation and de-aggregation of the data in that 
situation. But it was as reliable as a door stop. If the customer could 
not implement flow control they had to go slow enough to avoid data loss 
that was on them.

Oh, one last detail. Anybody remember "break characters"? These are not 
in your ASCII character chart. They were periods of a "space" level with 
the UART signals and I refuse to recall their reason for existence. 
Async RS232 serial signals alternated between "mark" and space logic 
levels traceable to 19th century telegraphs, but with the start, data, 
parity and stop bit conventions still used today. We had to faithfully 
transmit and receive "break characters". We cried for a few minutes and 
then added escapes to define the 257th byte value for "break".  But some 
apps needed this and it was also was wrapped up with implementing 
automatic baud rate detection. The customer typed a keyboard character 
once or twice until the cpu figured out the client device baud rate and 
the user's typed character echoed properly. Very fuzzy on how that was 
done!

I ended up using a pair of those muxes at the next startup (Encore 
Computer) after another guy (Steve Goldman) and I were "marooned" in 
1985. Encore sold the chunk of the company making a 4th generation 
language in Cary to Unisys but we worked for the platform dev piece of 
the company in Massachusetts, retargeting and optimizing the compilers,  
runtimes and libraries for 3rd gen languages (Pascal, C, C++, Fortran; 
another few guys handled Ada, thank heavens).  We were forced to 
telecommute to the Boston area from here for years until Encore closed 
the Massachusetts site and we unplugged and replugged the line into a 
site in south Florida. Network Products gave me a good deal on a pair of 
the muxes. I remember literally using one as a door stop around that 
time and think maybe they only gave me the second one.

It cost Encore $1k/month for a 9600 baud leased line between Cary and 
Marlboro, Mass. Yes, imagine two programmers existing with dumb 
terminals connected to a machine up there with total bandwidth of 1200 
characters per second. (The synchronous modem line has a clock and needs 
no start or stop or parity bits, the HDLC protocol providing error 
detection and packet retransmissions as needed, so it was 1200 instead 
of 960 per second). We each had three lines fed into monstrous 19" 
terminals Encore conveniently produced that had three "logical screens" 
of 24x132 characters fed by independent async ports. The other two mux 
ports fed a serial printer and a modem.

The cost of a 56k baud speed bump was out of the question until we 
convinced the folks up north we were worth it after a year or so. We 
retargeted Oregon Software and Green Hills compilers to the Encore 
NS32k-based, highly concurrent SMP systems in time for the first launch 
of the 16 processor "Multimax" in October of 1985. Want to know what the 
first "concurrent app" was for that system as the OS kernel guys were 
making it stable. Parallel "fsck"!!

When we got to 56K we could use NCD serial X terminals for GUI sessions 
with Encore's flavors of Unix. Encore could not make up their mind, 
offering very good ports of BSD, SVR4 and Mach. We eventually had a 
small mountain of computers in Cary for regression testing and dev and 
just used the line for email and revision control traffic, remote logins 
to chase problems, etc. We stopped needing the two muxes after Sun 
bought Encore in 1997 and gave us a 256k baud connection to the Sun 
intranet and we moved into the Sun sales office a year later and just 
had a couple racks of gear for the test system until we were done with 
Sun in 2008. But one big upside of Encore starting in 1984 was a 
connection to this thing called "Arpanet"!

-Pete


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.triembed.org/pipermail/triembed_triembed.org/attachments/20210128/002e2951/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ppeedkhikkbodmgn.jpeg
Type: image/jpeg
Size: 405135 bytes
Desc: not available
URL: <http://mail.triembed.org/pipermail/triembed_triembed.org/attachments/20210128/002e2951/attachment.jpeg>


More information about the TriEmbed mailing list