Kermit, the 387 and 256 KB of Inboard RAM

/ IBM 5160 and 3270 PC bring-up / updated 2026-10-25 5271 inboard-386 80387 kermit serial dos-5 extended-memory turbo-c masm

The 5271 can send and receive files from my Mac over its serial card now. With that working I could get test programs onto it in seconds instead of making floppies. The 387 on the Inboard passed Intel’s own diagnostic for five minutes. The Inboard’s RAM passed a small tester written for the job, and then Intel’s driver tested the same memory at boot and agreed with it. C: also got cleaned up after the DOS 5 install, which had left half its programs compressed in the root.

MachineIBM 5271, 3270 hardware removed, run as a plain XT
AcceleratorIntel Inboard 386/PC, 1 MB on board, Intel A80387DX-25
DOSMS-DOS 5.00
SerialCOM1 at 3F8h, 3-wire cable, FTDI USB adapter on the Mac
PC sideMS-DOS Kermit 3.14 (KERMITE.EXE), packets 1000, window 4
Mac sideC-Kermit 11.0.508 in server mode
Inboard driveriNBRDPC.SYS 1.1, 02/17/89, md5 c25b951a0a6093dcfa5138d89159cbf6

115200 works once the PC gets one packet at a time

Plain terminal traffic was clean both ways at 9600 on the first try. After that I did a sweep with a 32 KB file holding every byte value plus random data, with 1000-byte packets and a window of 4. At each speed the Mac served it, the PC pulled it with GET and pushed it back with SEND, and the Mac compared hashes. Every round trip came back byte-identical, including 115200, because Kermit resends bad packets.

SpeedGET, Mac to PCSEND, PC to MacRetries GET / SEND
9600 (4 KB file)770 B/s, 80%684 B/s, 71%0 / 0
192001659 B/s, 86%1361 B/s, 71%0 / 0
38400 (4 KB GET)3016 B/s, 79%2517 B/s, 66%0 / 0
576004900 B/s, 85%3512 B/s, 60%0 / 0
115200611 B/s, 5%3661 B/s, 31%121 / 1

At 115200 the PC loses incoming bytes. A byte arrives every 87 µs and one dropped byte spoils a whole 1000-byte packet, so the GET took 53 seconds and 230 packets. My guess is a UART with no FIFO on the serial card, but I haven’t identified the chip.

The losses only happen while the PC is still handling one packet and the next is already arriving. With SET WINDOW 1 the Mac waits for each acknowledgement, and the retries went to zero. After that, bigger packets helped up to about 4000 bytes. All of these are the same 32 KB GET at 115200:

PacketsWindowGETRetries
20041,770 B/s36
20014,201 B/s0
50015,144 B/s0
100015,573 B/s0
200015,789 B/s0
400016,079 B/s0
902416,024 B/s0
902425,018 B/s17

SEND with 4000-byte packets and window 1 ran at 5,526 B/s with no retries, so the 3.6 KB/s ceiling in the sweep was per-packet overhead. Minimal prefixing on the Mac (set prefixing minimal) made no difference, so I left it at the default. C:\KERMIT\MSKERMIT.INI now sets 115200, window 1 and 4000-byte packets.

If MS-Kermit at 115200 shows a pile of retries on a 16450-era serial card, try SET WINDOW 1 before anything else. The Mac server also has to allow long packets with set send packet-length 9024, or it quietly caps them at whatever it was started with.

If C-Kermit 11 is running as a server on a port it opened with set line, the PC gets “GET disabled”. The server defaults GET and SEND to “Remote only”, and enable get, enable send before server fixes it.

The 387 passes Intel’s diagnostic

The test came from the Intel387 DX Math CoProcessor Utilities disk from 1991. It’s a 1.2 MB image, so I pulled MCPDIAG.EXE (21 KB) out of it on the Mac and sent it over Kermit. It says “Your Intel Math CoProcessor is installed correctly!”, so it identified the chip as Intel. MCPDIAG also knows IIT, ULSI and Cyrix parts by name. Intel recommends five minutes on a first install, so it ran for 5:01.

TestPassedFailed
Addition, multiplication, subtraction, division92 each0
Constant, system integrity, transcendental, environment92 each0
MCPDIAG after 5 minutes on the A80387DX-25: 92 passes, 0 failures on every test.
MCPDIAG after 5 minutes on the A80387DX-25: 92 passes, 0 failures on every test.

The BIOS equipment word at 0040:0010 is 0221h, which has the coprocessor bit clear. So the motherboard switch for the coprocessor is probably still set to none. MCPDIAG doesn’t care, but anything that asks the BIOS won’t see the 387.

256 KB above 1 MB, tested two ways

I didn’t want to start with the driver. The only copies I could find online come out of the win95-intel-inboard-386pc project, some of them patched, and loading one means trusting it with CONFIG.SYS. So the first test was a small .COM program, INBMEM, that needs no driver. It puts the 386’s GS register in unreal mode with a 4 GB limit and turns on the Inboard’s A20 gate with OUT 60h,DFh. That port and value come from Al Williams’ 1990 Dr. Dobb’s article “DOS + 386 = 4 Gigabytes!” and match 386MAX’s Inboard path, both written up in that repo’s docs.

An address above 1 MB that no Inboard RAM answers goes out on the 20-bit XT bus and lands somewhere in low memory. So INBMEM sizes memory in 64 KB steps and checks for that each time. With interrupts off, it saves the low-memory alias, writes the probe address, sees whether the alias changed, and puts both back. Then it runs address, inverted address, 55555555h and AAAAAAAAh patterns twice over what it found, and over the free conventional block DOS hands back. Before it went near the 5271 I checked it under DOSBox-X. It found the edge of a 3 MB machine, reported the wrap with A20 forced off, and caught an injected stuck bit on every pattern.

INBMEM 1.0 - Inboard 386/PC RAM test
CPU: 386, real mode, GS limit 4 GB
A20: on via port 60h (Inboard)
RAM above 1 MB: 00100000-0013FFFF (256 KB)
  stopped at no RAM: 00140000
Free conventional RAM: 00020AA0-0009FFFF (509 KB)
RESULT: PASS

Both regions ran at the same speed per KB, so the conventional memory looks like it’s Inboard RAM too. That’s from timing only.

Then I loaded the stock driver. Its md5 matches the untouched original recorded in that repo. The repo also has a patched copy that skips the driver’s self-test, but that’s for 86Box, where the stock self-test fails. On the real board the stock one is fine. Line one of CONFIG.SYS is now DEVICE=C:\UTIL\INBRDPC.SYS NOPAUSE, and the old file is kept as C:\CONFIG.OK.

iNBRDPC.SYS 1.1 boot report on the 5271: 256k extended, 0k bad, system BIOS in 32-bit RAM.
iNBRDPC.SYS 1.1 boot report on the 5271: 256k extended, 0k bad, system BIOS in 32-bit RAM.

The driver tests the extended memory at every boot and found the same 256 KB with 0k bad. It costs 3,760 bytes of conventional memory: 587,120 bytes free before, 583,360 after. The 1 MB on the board adds up now. 640k is conventional and 256k is extended, which leaves the 128 KB at 5E0000 to 5FFFFF that the board reserves for shadowing, which is presumably where the driver keeps its copy of the system BIOS.

DOS 5’s MEM still says 655360 bytes of conventional memory and nothing else, because it doesn’t report extended memory on an XT. To see what the driver offers, ask the BIOS. In DEBUG, mov ah,88 / int 15 returned AX=0100 with carry clear, which is 256 KB.

The DOS 5 install left its programs compressed

MEM wouldn’t run at all to begin with. The install had copied MEM.EX_ and seven other compressed files into C:\ and never expanded them, along with EXPALL.BAT to do it. A small INVENTRY.BAT listed the whole disk over Kermit, and CLEANUP.BAT expanded MEM, EMM386, RESTORE, BACKUP, DOSSWAP, MODE, EGA.CPI and EDIT.HLP into C:\DOS. It deleted each compressed file only once its expanded copy existed, moved the loose DOS files into C:\DOS, and cleared out test leftovers. The root is down to COMMAND.COM, the two hidden system files, CONFIG.SYS, AUTOEXEC.BAT and the directories. AUTOEXEC sets PROMPT $P$G, puts C:\DOS;C:\TC;C:\TD;C:\MASM\BIN;C:\KERMIT;C:\UTIL on the path, sets TEMP, INCLUDE, HELPFILES and INIT for MASM, and loads DOSKEY.

A HWINFO.BAT dumps the rest of what I wanted to know about the machine.

System BIOS11/08/82
Video BIOSAMI VGA BIOS, 08/01/91, header says 32 KB
C800Western Digital ROM, 07/15/86
D000 to EFFFempty
PortsCOM1 at 3F8h, no COM2, no LPT
C:42,661,888 bytes, 122,880 in bad sectors, 38.8 MB free

The XT has no clock battery, so every boot starts in 1980.

Turbo C, Turbo Debugger and MASM 6.00 over Kermit

The 5271 has Turbo C 2.0, Turbo Debugger 1.0 and MASM 6.00 on it now. One batch file copied them from the Mac over Kermit.

ToolWhere it came fromOn the 5271
Turbo C 2.0: the TC IDE, TCC, MAKE, TLINK, all six memory modelsthe DOS 3.3 hard disk image I use in 86BoxC:\TC
Turbo Debugger 1.0the TASM 1.0 disksC:\TD
MASM 6.00: ML, LINK 5.13, LIB, NMAKE, CodeView, QuickHelpthe Windows 3.1 VM in 86Box, already installed and expandedC:\MASM

That came to 4.6 MB. I left out PWB and TD386. TD386 wants a 386 memory manager of its own, which would fight iNBRDPC.SYS. MASM 6.00’s README says ML.EXE runs in real mode on an 8088 and only MLX.EXE needs a 286, so .386 code assembles fine on this machine without a DOS extender.

PCINST.BAT makes the folders, then for each one does a DOS CD and runs one Kermit:

CD C:\TC
KERMITE SET FILE COLLISION OVERWRITE, REMOTE CD /tmp/pci/TC, GET *, EXIT

MS-Kermit runs comma-separated commands straight from its command line, so each fetch is one line in the batch file. /tmp/pci is a link on the Mac to the payload folder, because DOS cuts a command line at 127 characters and the full path didn’t fit. Afterwards PCPOST.BAT swaps in the new AUTOEXEC.BAT, keeps the old one as C:\AUTOEXEC.OK, builds two test programs and sends a log back to the Mac.

The first version used one Kermit TAKE script with Kermit’s own cd C:\TC before each GET. It worked in DOSBox-X with a different MS-Kermit build. On the 5271 all 128 files landed in C:\UTIL instead, so KERMITE’s cd inside the script didn’t move it, and I haven’t worked out why. A generated PCFIX.BAT moved them into their folders by name.

The rehearsals ran in DOSBox-X with its serial port set to nullmodem server:127.0.0.1 port:2323 transparent:1. A 23-line Python bridge between a pty and that TCP port let C-Kermit on the Mac treat DOSBox-X as a serial line.

CheckResult
TCC HEAPTEST.C from the DOS promptnear heap 63,688 bytes, far heap 510,072
the same program from Turbo C’s DOS shellnear heap 63,694 bytes, far heap 179,400
ML HELLO386.ASM, which uses EAXMASM 386: OK

The IDE itself costs about 330 KB of far heap while it sits underneath a DOS shell, and it shows 187K available while compiling. Turbo C 2.0’s ALLOC.H has malloc, farmalloc, coreleft and farcoreleft, and nothing to check the heap with. heapcheck() and heapwalk() came later, with Turbo C++.

Still open

Find out what UART is on the serial card. A scratch-register probe in DEBUG read back FF everywhere, so that told me nothing. If it’s socketed, a 16550A might let a window of 4 work at 115200.

Try EGACACHE on the driver line. The VGA BIOS header says 32 KB, which is the most the driver accepts.

See whether RAMDRIVE or SMARTDRV can use the 256 KB, or whether they want HIMEM.SYS, which I haven’t tried on this machine.

Benchmark with and without the driver, to see what running the BIOS from 32-bit RAM is worth.

Set the coprocessor switch so the BIOS reports the 387.

Write a debug heap in Turbo C, since 2.0 doesn’t come with one.

The rest of Intel’s utility diskette (ISTATPC, ICACHE, iLIM386.SYS) still hasn’t turned up.