Discovering the IBM PC XT

By Connor Taffe | Published .

Happy new year! As 2023 comes to a close, I'd like to start documenting the journey I've been on over the last month or two, exploring the IBM PC XT.

In mid-November, I came across a listing for an IBM PC XT alongside its monochrome monitor and Model M keyboard in my local area. I met the seller at his home, and he introduced himself as a researcher at the local medical school (UAMS) who was planning to move to Northwest Arkansas. The PC was actually the driver for a System/36 model 5364 which he also had for sale, and contained the driver card -- a brown ISA card with a many-pin connector on the back 1 -- which I asked him to keep for whoever purchased the System/36. He reached out a few weeks later to say someone had driven down from Oklahoma for it, and was very happy to have the controller card. There are examples of a working "Desktop 36", here's a video of one booting up, but it seems like documentation and software are scarce.

Below is the system as I received it, with only a half-sized 5.25" double-sided, double-density (360k) floppy disk drive and no hard drive. The keyboard is a Model F I had on-hand while I was cleaning the Model M. The floppy drive is not completely functional, generating a 601 on boot and sometimes failing to read media (always failing to boot from media).

An IBM PC XT booted into ROM BASIC
An IBM PC XT booted into ROM BASIC

The system contains an Intel 8088 without an 8087 floating point coprocessor (they are seldom present), and 512k of RAM populated into a 256k-640k board. The first board revision supports 64k-256k of RAM, while the second supports 256k-640k. The 8088 uses a 20-bit address bus, which can only address 1MB of memory. 640k of this 1MB is available for RAM, while the rest is reserved for use by cards -- this is called "low memory." On boards with 64k-256k of RAM populated, the remaining 384k can be provided by memory expansion in the I/O channel. Upper memory is used for hardware mapped video memory, the system BIOS, and BIOS expansions such as hard drive controller card ROMs. On later systems this is called real mode.

The earliest PCs such as the XT had only 8-bit ISA slots, followed by 16-bit longer ISA slots in the PC AT -- 8-bit cards work in 16-bit slots and some 16-bit cards support 8-bit slots. Inside it were:

Each card may use an interrupt request (IRQ), an I/O address, and portions of high memory for ROM. They may use multiple, e.g. in the case of multi-purpose cards. These are often configurable either through software or dip switches on the card, and must not conflict. For ROMs, lower addresses are run first, so ROMs can be sequenced. On the XT, only IRQs 0-8 are available, with 0 and 1 taken by the system timer and keyboard. The canonical assignments are:

IRQ Used for
0 RAM refresh and clock tick
1 Keyboard
2 Enhanced Graphics Adapter
3 Serial port COM2/COM4
4 Serial port COM1/COM3
5 Hard disk drive controller
6 Floppy disk drive controller
7 Parallel port LPT1

See this listing of I/O addresses with their usage, so far I've used:

I/O Address Card
0x300 XT-IDE controller card
0x320 Hard drive controller card
0x360 Network card

ROM addresses must align on 2k boundaries, but the cards I've seen use 8k ROMs and allow moving to several 8k aligned addresses. Here is an example setup:

ROM Address Card
0xCC00 XT-IDE controller card
0xCE00 High density floppy disk controller card
0xC800 Hard drive controller card
0xD000 Network card expansion ROM slot

Some ROMs replace the Initial Program Load (INT 0x19), such as the high density floppy controller or XT-IDE; ordering these is important. For instance, to configure the high density floppy controller card, we need its IPL to be last, so it needs to be configured at a higher address than an XT-IDE. In other cases, the XT-IDE ROM needs to be placed higher so that we see its UI on boot instead of having to wait for the high density floppy controller's ROM to attempt to boot from a floppy before passing control.

A program like CheckIt is useful for determining what IRQs, addresses, etc. are used and by what hardware.

Installing Software

Without a hard drive or a working floppy drive and lack of floppy disks, the first challenge was loading software onto the machine. I utilized two pieces of modern equipment popular in the community:

ISA cards populating an XT, including an XT-IDE
ISA cards populating an XT, including an XT-IDE

With these installed, it's now possible to load software from the disk image (see this video for more context):

The below apply to IBM DOS 3.30, but not later DOS installations with automated setups like MS-DOS 5.0:

With an operating system installed, we can now start installing software. For instance, Lotus 1-2-3 2.3 or WordPerfect 5.1 as period-correct productivity software.

High Density Floppy Disks

High Density disks such as 1.2MB 5.25" floppies or 1.44MB 3.5" floppies require new firmware on an expansion ROM. Sergey's isa-fdc project provides this firmware on a ROM in an ISA floppy drive controller card capable of supporting "IBM PC, AT, and PS/2 floppy types from 160 KB 5.25" single side disks to 2.88 MB 3.5" ED (Extended Density) disks."

Sergey Kiselev's Floppy Disk Controller
Sergey Kiselev's Floppy Disk Controller

These can be purchase pre-assembled, although shipping from Bulgaria does take a while. The key for the DIP switches is conveniently printed on the back, initially mine was set to a ROM address which collided with my Seagate ST11R hard drive controller card, so I set switch block one to 01000001 and two to 11101110. This combo uses IRQ 4 for COM1, and uses the corresponding I/O port 0x3F8, enables the ROM, makes the EEPROM writable so we can run the setup with F2, and sets the ROM address to 0xD0000 (what the XT-IDE uses). I also set the motherboard dip switches to reflect one floppy disk, since I only wanted to use a single drive at a time.

Booting the machine with the hard drive controller in place, we can leave the drive empty and boot from our DOS installation on the hard drive. With an empty physical 3.5" drive I get an "Boot failed, error 80" where I can press F to boot from the hard drive -- this could be an issue with the drive itself. If I then insert the disk, I can navigate to A: in DOS and see the files with dir. Funnily enough, the last edited timestamp of each file corresponds with the DOS version -- 6:22AM on May 31st, 1994.

DIR on a 3.5 inch 1.44MB floppy disk
DIR on a 3.5 inch 1.44MB floppy disk

I tested booting from high density disk both with an XT-IDE using an image of my DOS 6.22 setup disk I created with dd, and a real 3.5" drive with the real disk. Both displayed "Starting MS-DOS" before hanging, which I believe is a common problem with the 6.22 installer on the XT. On a different XT with the same amount of memory, I was able to load the 6.22 installer from a Gotek after adding interface=ibmpc to the FF.CFG file.

DOS 6.22 Intstaller
DOS 6.22 Intstaller

In case (like me) you accidentally wipe it attempting to configure another card; the ROM image can be reflashed using XTIDECFG.

Printing

Each application provides its own printer drivers, and printing under DOS is reliant on parallel ports. Lotus 1-2-3 configures printers during installation or later by running INSTALL. For a modern printer like an HP LaserJet, I use the Apple LaserWriter driver, which sends PostScript to the printer. Early HP Laser printer drivers may also work since they'll use an older version of HP's control language.

With the LocalTalk PC card and AppleShare PC software described below, you can print to virtual parallel ports which are networked printers. I've successfully printed to my Apple ImageWriter II over LocalTalk directly, and my HP LaserJet with a 635n EIO card over Ethernet via an AsanteTalk bridge.

These parallel ports are available to DOS as well, not just applications with printer drivers. A command like:

C:> DIR >LPT3

will pipe a directory listing to our third parallel port, in this case a virtual port managed by AppleShare PC and configured to send to the ImageWriter II.

Upgrading

To max out the memory and add a coprocessor, I found an XT motherboard on eBay:

IBM Motherboard
IBM Motherboard

Using a chip lifter, an indispensable tool when dealing with old hardware, I was able to move the last two banks of memory onto my XT's motherboard. On the 256k-640k boards, the last two banks use the smaller memory chips which are used in the 64k-256k boards. Once those banks were populated, I just needed to toggle dip switches 3 and 4 off and the memory test passed without issue.

The 8087 coprocessor was similarly simple, although lifting longer chips and fitting them into the socket takes plenty of light and patience. Then flip dip switch 2 off. This allows for quicker floating point operations in programs like Lotus.

A NEC V20 processor is another great investment, for only $3.35 and some waiting, you can swap out your 8088 for a 80186-compatible and faster processor -- without changing the clock speed.

Graphics

IBM Color Displays are expensive, but after a week or two of searching, emailing Craigslist sellers, etc., I found a listing on eBay for an entire IBM PC XT with Hercules Color Card and a CGA Display and made an offer. At the same time, I made an offer on another CGA Display. My luck was such that both were accepted, and I ended up with two working CGA monitors and another entire XT. Around the same time I found another XT with an IBM CGA card, one that'd been stored in a garage and was a bit dirty. By some miracle, both of these XTs worked, were configured at the maximum of 640k of RAM (the first via expansion card, and the second via 640K mainboard), and contained a hard drive controller card and working hard drive.

Turbo Pascal taking advantage of color and monochrome monitors
Turbo Pascal taking advantage of color and monochrome monitors

To enable color, you'll need to install a CGA card (e.g. a Hercules Color Card or IBM Color Graphics Adapter), and toggle dip switch 5 (80 column) or 6 (40 column) on the motherboard on. With both an MDA and CGA (or Hercules Color Card), applications can utilize two monitors. With Turbo Pascal 7.0, simply use the /d option. Lotus 1-2-3 can also utilize the color monitor to display graphs, as demonstrated in this video.

CGA graphics are lower resolution than monochrome, so are more useful for graphs or games; while the monochrome monitor is better for text.

Try PAKU PAKU for a game which takes advantage of CGA graphics. You'll notice a little "snow," which happens when software writes to the video memory while the video memory is being read out to the display. The XT-IDE BIOS also takes advantage of CGA to highlight the boot options in color, but also produces some snow.

Monochrome

On the monochrome side, there are improvements to be made as well. Hercules Graphics, a de-facto standard supported by many applications and cards, adds a bitmapped graphics mode to the functionality provided by the IBM Monochrome Graphics Adapter. Lotus 1-2-3 uses this to depict graphs, while Hercules' HBASIC is a version of BASIC with facilities for drawing graphics to the screen as discussed in this 1983 BYTE Magazine review.

I found the card below from a recycler on eBay, but several clone boards which offer the same functionality are available too:

Hercules Graphics Card
Hercules Graphics Card

You may notice the missing chip marked C17, this is where the font ROM should be! The seller was kind enough to refund me and allow me to keep the card, so I'm working on finding this chip. We can tell that the card is at least somewhat functional otherwise though, because the screen is pained with green boxes except where the text would be highlighted. The ROM is the same type used in the MDA card, the Hercules Color Card, and the IBM PC XT motherboard, but with different data. In fact, the data is so similar on the Hercules Color Card that the HGC will use it, but this results in two identical characters stacked on top of each other for each character, because CGA text is lower resolution (8 pixel instead of 14).

The ROM is 24 pin, but is compatible with the AT28C64 28 pin EEPROM when adapted. This means we can use a reflashable, cheaply available ROM in place of the old Font ROM. We can use any card with a writable ROM chip slot (such as the XT-IDE or Sergey's floppy controller) and XTIDECFG to flash the EEPROM from an image, such as this one. I ordered a handful of pre-assembled 2364 adapters along with AT28C64-12PC EEPROMs; after flashing them using XTIDECFG, the PC still emitted one long beep followed by two short and the display showed the top half of a character but a solid bottom half -- I also noticed some tick mark characters in random positions on screen.

Hercules Graphics Card with ROM
Hercules Graphics Card with ROM

The Plus is similar but uses a new chip and on-card RAM to provide RAMFont capabilities.

Hercules Graphics Card Plus Ad
Hercules Graphics Card Plus Ad

MFM/RLL Hard Drives

The second XT also contained a 20MB hard drive and Western Digital Modified Frequency Modulation (MFM) controller card, alongside a full-sized floppy disk drive. As expected, the computer refused to boot from the hard drive, but once reformatted it worked perfectly. Similarly, my third XT cam with a 31.5MB ST-238R RLL drive and Seagate ST11R Run Length Limited (RLL) controller card alongside two half-height floppy drives. The hard drive booted once to the existing install before giving out and needing to be reformatted. MFM and RLL are simply different encodings, where RLL packs more data onto the same area and requires a more accurate hard drive mechanism. When formatting, an RLL drive will use more sectors pre track -- the ST238R can be formatted with 26 sectors per track instead of the MFM's 17.

Seagate ST-238R Ad
Seagate ST-238R Ad

These hard drives are "dumb" in that the controller does a "low-level partitioning" of the drive and stores information such as bad sectors, which the manufacturer supplies as a list on the sticker from the manufacturer. All hard drives have some defects, but the drive is manufactured such that there is enough room to handle this and still provide the advertised capacity. Controller cards contain a ROM which will contain a copy of a partitioning utility.

To low-level format a drive, we can use DEBUG (included with a DOS install) to branch into the ROM's formatting utility. The address depends on the manufacturer:

Manufacturer Address
Western Digital G=C800:800
Adaptec G=C800:CCC
Omti G=C800:6
Seagate, DTC (Data Technology), etc. G=C800:5
A:> debug
- G=C800:800

See this hints file for more information on individual drives, such as cylinder counts, etc.

For my Seagate ST-238R, this is how I configured it (this guide may help):

  1. From a bootable floppy disk with DEBUG (formatting fails with an XT-IDE installed), run:

    A:> DEBUG
    - G=C800:5
    

    This launches the ST11 BIOS v2.0 Hard Disk Initialization Utility, assuming the card jumpers are using the default setting (no connections).

  2. Choose the drive to format, I choose 0.

  3. Confirm the existing configuration for the drive or input a new one, mine is as follows:

    Option Value
    Total cylinders on the drive 615
    Total heads on the drive 4
    Number of sectors per track 26
    Starting write precomp cylinder 616
    Drive model ST-238R
    Drive serial number 82119697
    Interleave 4

    Note the track value is 26, not the standard 17 for MFM, which will allow us to use 32MB instead of 20MB. The optimal interleave should be noted by the utility, SpinRite can also test interleave values to find the optimal.

Tools

SpinRite is a good alternative to ordinary low-level formatting, because it doesn't destroy the contents of a disk. However, it does not work with many kinds of drives, especially those that use sector translation.

Controllers like the ST11R cannot be formatted with SpinRite because of sector translation (which SpinRite will detect), but once formatted and partitioned with fdisk SpinRite is able to test them.

SpinRite is an excellent tool for detecting bad sectors -- run the complete analysis after formatting your drive to detect any bad sectors. The analysis will test every sector of the disk and takes several hours. It can also choose the best interleave setting for your drive. Below is a readout of a completed scan:

SpinRite scan summary
SpinRite scan summary

Another option is SpeedStor, which can also be used to low-level format disks. It can also create 32MB partitions, if your DOS isn't new enough to support larger ones, but I prefer to use fdisk for that.

XT-IDE

My card came loaded with the "tiny" version of XUB, which doesn't allow selecting which drive to boot from (it always checks floppy drives first). To swap it, run XTIDECFG and choose the "XT" BIOS re-flash it, ensure that "SDP Command" is set to "None." The "auto detect" functionality should detect your card revision information, I/O address, etc. Ensure the "W" dip switch is in the on position when re-flashing, and toggle it off otherwise to avoid accidental overwrite with e.g. driver misconfiguration.

XT-IDE card with CF card adapter and CF card
XT-IDE card with CF card adapter and CF card

Some network cards use the same I/O address (0x300) as the XT-IDE uses by default, the first six dip switches on the SW1 block, labeled A9-A4, are the binary encoding of the I/O address. By default they will be (starting at A9) 110000 or 0x30, you can change it to the standard hard drive controller location of 0x320 by switching A5 to on, making 110010. Once this is done, the card must be reflashed. The XUB won't be able to find the CF card, so you must boot from a prepared disk image with XTIDECFG. Once booted, auto-detect should update the address correctly, if not just set it manually to e.g. 320 and 328.

As long as there is no I/O address overlap, XT-IDE cards can be used alongside a hard drive controller cards. During boot, the IDE drive will be drive D: and the hard drive will be C:. By pressing D, you can switch the IDE drive to boot as the primary hard drive, and once booted the hard drive will show up as D:. This is especially handy when initializing a hard drive: after low-level formatting, you can use the formatting tools of your existing DOS installation via fdisk followed by format d: /s. A DOS booted from one disk cannot mark a second disk's primary partition as active, but a PC-DOS 3.3 boot disk's fdisk was able to mark a primary partition active which was created with PC-DOS 2000 and greater than the 32MB limit that PC-DOS 3.3 could create itself. You must mark the partition active or the system won't boot using that disk (in my case it silently continues to BASIC).

Mounting

To mount the CF card under macOS, sometimes it will show up as blank. This is because macOS is stricter about FAT16 filesystems than DOS, but it's easy to resolve with repairVolume:

# Identify your CF card's device
; diskutil list external physical
# Replace /dev/disk4 with your disk
; diskutil unmountDisk /dev/disk4
; diskutil repairVolume /dev/disk4s1
; diskutil mountDisk /dev/disk4

Additionally, macOS will create hidden files such as a trash folder, spotlight index, fsevents folder, and attribute files for individual files. For a given volume name, you can disable some of these:

; sudo mdutil -i off -d /Volumes/MY_DISK

If you are having difficulty copying a file onto a disk, these files may be the culprit. Use ls -a to view them, and then rm to delete. Under Settings, Privacy & Security, Full Disk Access, you'll need to grant your terminal emulator access so it can delete spotlight indexes.

Backups

To back up your system, you can use dd:

# Identify your CF card's device
; diskutil list external physical
# Replace /dev/disk4 with your disk
; dd if=/dev/disk4 of="$HOME/Desktop/xt-backup-20240101.img"

This .img file can be opened and edited like any floppy disk image. Using an emulator like 86Box, you can even use it with a virtualized IBM PC XT -- unfortunately I've not been able to successfully boot from an image. Using this method, I was able to install IBM PC-DOS 2000, which is only distributed on 1.4MB 3.5" disks. After installation and backup, I was able to repartition my CF card into a single 128MB partition, and use rsync to copy all the files from that backup image to my current disk image:

; rsync -av /Volumes/NO\ NAME/ /Volumes/IBM\ PC\ XT --exclude=COMMAND.COM

Before flashing it back onto my CF card:

; sudo dd if=$HOME/Desktop/xt-dos7.img of=/dev/disk4

Hardware

Although I'd never owned a PC with ISA slots, I had accumulated a couple of cards over the years:

Omitting those discussed in detail above, I also acquired the following cards within the three XTs:

Professional Debug Facility

The Professional Debug Facility is a Terminate and Stay Resident (TSR) program for DOS which works alongside an ISA card which provides a unmaskable (un-ignorable) interrupt, so that whatever your application or the operating system is doing, the debugger can be invoked.

Professional Debug Facility
Professional Debug Facility

When invoked, either through a breakpoint in a program or via the card's button, the Resident Debug Tool presents the current execution environment:

Resident Debug Tool
Resident Debug Tool

It seems to fill a similar niche to MacsBug on the Macintosh, which can also be installed as a resident program and be invoked with a key press.

Networking

The IBM PC XT existed during the wild west of LAN networks: LocalTalk, Ethernet, Token Ring, StarLAN, Novell NetWare, etc. We'll focus on LocalTalk (AppleTalk) and Ethernet (IP).

Apple LocalTalk PC Card

The Apple LocalTalk PC Card, described in this OVCR post, enables printing to AppleTalk printers and mounting of AppleShare drives, but won't work with Netatalk 2.x printers or shares. Another write-up exists in this Reddit post, and another in this blog post. There is also information on Corey Anderson's blog, the apparent genius behind a talking toaster.

Software:

Apple LocalTalk PC card
Apple LocalTalk PC card

Farallon's fork of this software places several batch files into C:\PHONENET alongside the programs, ABOTH.BAT loads facilities for both printing and files, but doesn't load DA as a TSR by default (so the Alt+A hotkey doesn't work) -- to do this simply add the /r switch. The CONFIG.SYS file should contain FILES=20 or higher. In the Apple version, the loading script is placed directly into AUTOEXEC.BAT, below is an example:

lh C:\aspc\LSL
   if errorlevel 1 goto aspc_err
lh C:\aspc\LTALKP /NAME=LTALK$
   if errorlevel 1 goto aspc_err
lh C:\aspc\ATALK
   if errorlevel 1 goto aspc_err
lh C:\aspc\ASP_WS
   if errorlevel 1 goto aspc_err
lh C:\aspc\ASHARE
   if errorlevel 1 goto aspc_err
lh C:\aspc\MINSES
   if errorlevel 1 goto aspc_err
lh C:\aspc\REDIR
   if errorlevel 1 goto aspc_err
lh C:\aspc\PAP_WS
   if errorlevel 1 goto aspc_err
lh C:\aspc\APRINT
   if errorlevel 1 goto aspc_err
lh C:\aspc\DA /r
   if errorlevel 1 goto aspc_err
lh C:\aspc\ANET AUTO
   if errorlevel 1 goto aspc_err
REM ***  Memory usage for the above programs is approximately 200 K bytes.
goto skip_aspc
:aspc_err
echo *** A fatal error has occurred while loading AppleShare PC. ***
pause *ASPC*
:skip_aspc

You can use goto skip_aspc above this to only load AppleShare PC under certain circumstances, since it uses around 200KB out of 640KB total. Once loaded, using either Farallon's or Apple's version, the DA command or hotkey will load you into the "desktop accessory." Using tab and F keys, you can navigate through adding a printer and mounting it as a parallel port, or appleshare volume as a drive letter.

NCSA Telnet reportedly works with AppleTalk, but I have not had success with my Netatalk-based IP Gateway. I found this copy of version 2.3, here's the relevant excerpt from Telnet's FAQ:

Can I use Telnet with AppleTalk?


Using an Appletalk network involves some special considerations. First,
you must load the Appletalk driver into memory. Version 1.0 of the
"ATALK.EXE" driver was used in the development of NCSA Telnet.

The second consideration involves the "interrupt=" line. The "interrupt="
line in your CONFIG.TEL file refers to the software interrupt the
Appletalk driver is using, not the hardware interrupt the card is set to.
For example, if your Appletalk card is set to IRQ2, you should NOT set
the "interrupt=" line to "2". Instead, the value should be set to the
software interrupt, usually "interrupt=60" or "interrupt=5C".

Static addressing does not work at the current time in NCSA Telnet 2.3
using the AppleTalk driver. Therefore, NCSA Telnet ignores any IP address
you set in your CONFIG.TEL file, and assigns an IP address to your PC by
the Appletalk gateway.

Some AppleTalk users have been more successful with v2.3.03 of Telnet.
If you would like to try v2.3.03, it's available on our anonymous ftp
server in the /Telnet/DOS/contributions directory.

One of our users wrote:

To load telnet from the dosprompt [nothing telnet-specific in
config.sys or autoexec.bat we use the following sequence:

lsl.com
ltalk.com
atalk.com
ashare.com
compat.com
d:\network\telnet\telbin -n -h d:\network\telnet\config.tel

where all of the atalk stuff would be in the current directory and all
of the telnet stuff is in d:\network\telnet.

broadcast=255.255.255.255
netmask=255.255.255.0
hardware=atalk          # network adapter board (Appletalk)
interrupt=60            # I have an Apple or Farralon card and PhoneNET Talk
			#remember to run COMPAT.COM for NCSA to run on
			# LocalTalk
#interrupt=5C           # I have a TOPS Flashcard

mtu=512                 # maximum transmit unit in bytes
maxseg=512              # largest segment we can receive
rwin=512                # most bytes we can receive without ACK

The COMPAT.COM file is not loaded by default and is essential. Under Farallon's fork, this is commented out in the batch script, whereas it needs to be added manually with earlier versions.

I've also found copies of PCROUTE 2.24, which I am hosting: source, binaries. PCROUTE allows an IBM PC to act as a router, bridging between LocalTalk, Ethernet, SLIP, or StarLAN.

IP

IP Networking is possible on an XT given a card with a packet driver and mTCP. I was able to find a couple of Intel 8/16 LAN Adapter cards, which are compatible with both 8- and 16-bit ISA slots and configurable on both with SOFTSET.EXE. A copy is available at ftp://ftp.oldskool.org, navigate to pub/misc/Hardware/Intel/8_16 LAN ADAPTER/.

The files e16disk.exe and softset2.exe are self-expanding archives which should be run in a new folder on your XT. In the resulting files from e16disk.exe, the softset.exe program is a stand-along configuration utility for your card, which allows setting a new IRQ and I/O address based on your machine's available options. Also among the files is packet/eth16.com, the packet drive. You may need exp8.com within the FTP folder on an 8088. The softset2.exe files contain a softset2.exe which is nearly identical to softset.exe. Via softset, you can also configure the address of the boot ROM (or disable it) -- the socket supports AT28C64 chips which can be programmed with an XT-IDE board, so could support additional ROM software.

Once the card is configured, you'll need to load the packet driver by executing exp8.com (or exp16.com, add it to AUUTOEXEC.BAT), which will allow the mTCP programs a standard interface. Programs like PCROUTE can also support cards via a packet driver. With mTCP working, you can finally access BBSs, IRC, and even ChatGPT.

Intel 8/16 LAN Adapter
Intel 8/16 LAN Adapter

Unfortunately, my cards were defective and failed softset's diagnostics under several configurations. I reached out the eBay seller who is sending another two cards after running diagnostics themselves, and I'll fill this in as I get TCP/IP working. A third card, which also failed SOFTSET's diagnostics for the "82586 chip," did work:

  1. Run SOFTSET.EXE and automatically configure the card. Take note of ROM address, as this may conflict with other cards you have. I use 0xCC00 for my XT-IDE ROM, 0xCE00 for my high density floppy controller, 0xC800 for the MFM hard drive controller, and 0xD000 for the Intel 8/16 LAN Adapter (empty). Also note the I/O address, I used 0x360-0x36F as it is listed as for use with a PC Network -- the XTIDE by default uses 0x300, and the hard drive controller card uses 0x320. The software chose available IRQ 2.

  2. Confirm the software I/O address, usually 0x60 by running

    EXP8.COM 0x60
    
  3. Assuming mTCP is installed at C:\MTCP, add a TCP.CFG configuration file with the following contents:

    PACKETINT 0x60
    HOSTNAME xt
    MTU 1500
    

    The MTU line configures mTCP to use the maximum packet size according to RFC 894. Other fields are unnecessary if using DHCP (most networks do). mTCP's DHCP updates the configuration with IPs and other lease metadata each time it's run.

  4. and EXP8.COM under C:\ETHEREXP, add the following to your AUTOEXEC.BAT:

    SET MTCPCFG=C:\MTCP\TCP.CFG
    C:\ETHEREXP\EXP8.COM 0x60
    C:\MTCP\DHCP.EXE
    

    This will load the packet driver and run DHCP on each boot. Alternatively, place the last two lines in a batch file and run it only when you wish to connect.

    Adding a SLEEP between the packet driver and DHCP may be necessary to resolve an issue where the DHCP client fails to fetch a lease on the first two attempts because the packet driver has not fully initialized.

Once the packet driver is loaded and DHCP is run to establish an IP address, the other mTCP programs will read that info from the updated config file pointed to by MTCPCFG. For instance, we can use TELNET to access other computers across the Internet:

Star Wars playing via Telnet
Star Wars playing via Telnet

Or simply across our local network, such as this Linux VM:

Linux shell via Telnet
Linux shell via Telnet

The SOFTWARE.DOC file from a Crynwr distribution lists software that works with packet drivers, and where you could get it in 1993.

Telnet

If using a monochrome monitor via either MDA or Hercules, set TERM=pcansi-mono so that programs emit monochrome text (by default TERM=ansi). Otherwise, telnet will map colors to black or white which can result in invisible black-on-black text (for example, the tmux status bar). You may need to install the pcansi-mono terminfo entry on your Linux machine, on Fedora install ncurses-term.

sudo dnf install -y ncurses-term

You may also need to set LANG=en_US to disable UTF-8. You can have telnet set TERM automatically by adding:

TELNET_TERMTYPE pcansi-mono

to TCP.CFG, see the mTCP Telnet documentation.

A Bug

In testing telnet with tmux I uncovered a bug in its auto-margin implementation. Once I tracked the issue down, mbbrutman was able to patch telnet and make a test version available which works. Previously, tmux (but not screen) would trigger the cursor to move down to a new row by drawing the status line across the bottom of the screen. On each update of the status bar (which contains the time), the problem would compound and the text of the screen would move a line further up from the cursor.

First, I was able to get tmux working over telnet by using a termcap with automatic margins disabled. That way, tmux won't write the last character of the last line until it expects a line wrap, which side-steps our issue. This works either using an existing termcap like vt100-nam, or by crafting a new one:

; infocmp -C -T pcansi-mono > pcansi-mono-nam
; sed -i 's/pcansi-m|pcansi-mono|ibm-pc terminal programs claiming to be ANSI (mono mode):/pcansi-mono-no-am:/' pcansi-mono-nam
; sed -i 's/:am:/:/' pcansi-mono-nam
; tic pcansi-mono-nam

The tic command will compile the new pcansi-mono-nam terminal definition and place it under a personal terminfo database at: ~/.terminfo/p/pcansi-mono-nam. To place it under /usr/share/terminfo, run tic as root. Although tmux will find the terminal definitions under ~/.terminfo, screen will not.

Now, if we set TERM=pcansi-mono-nam, tmux would work correctly. We can set TELNET_TERMTYPE to our custom pcansi-mono-nam in TCP.CFG to set it automatically.

The issue lies in a little-known terminal feature called "auto-margin", see the termcap documentation on wrapping, which notes:

Wrapping means moving the cursor from the right margin to the left margin of the following line. Some terminals wrap automatically when a graphic character is output in the last column, while others do not.

See also the OpenGroup terminfo documentation.

The documentation notes that the am indicates the terminal will scroll if a character is placed in the last column of the last line. Using infocmp, we can show that our pcansi-mono terminal does have am, indicating a character should not be placed in the last column of the last line.

; infocmp -C -T pcansi-mono
#	Reconstructed via infocmp from file: /usr/share/terminfo/p/pcansi-mono
# (rmacs/smacs removed for consistency)
pcansi-m|pcansi-mono|ibm-pc terminal programs claiming to be ANSI (mono mode):\
	:am:bs:mi:ms:\
	:co#80:it#8:li#24:\
	:al=\E[L:bl=^G:bt=\E[Z:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\
	:cm=\E[%i%d;%dH:cr=\r:ct=\E[3g:dc=\E[P:dl=\E[M:do=\E[B:\
	:ho=\E[H:kb=^H:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\
	:le=\E[D:mb=\E[5m:md=\E[1m:me=\E[0m:mr=\E[7m:nd=\E[C:\
	:..sa=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;12%;m:\
	:se=\E[m:sf=\n:so=\E[7m:st=\EH:ta=^I:ue=\E[m:up=\E[A:\
	:us=\E[4m:

The screen manual has this to say:

If your terminal is a “true” auto-margin terminal (it doesn’t allow the last position on the screen to be updated without scrolling the screen) consider using a version of your terminal’s termcap that has automatic margins turned off. This will ensure an accurate and optimal update of the screen in all circumstances. Most terminals nowadays have “magic” margins (automatic margins plus usable last column). This is the VT100 style type and perfectly suited for screen. If all you’ve got is a “true” auto-margin terminal screen will be content to use it, but updating a character put into the last position on the screen may not be possible until the screen scrolls or the character is moved into a safe position in some other way. This delay can be shortened by using a terminal with insert-character capability.

Confusingly, they suggest removing am if the terminal supports "true" auto-margin, and this is what resolves the issue with tmux.

However, the real issue lied in mTCP's telnet implementation, which should implement "magic margins." It correctly does not automatically wrap when the final character is written, but it does when certain additional control characters are sent. In the source code, in TELNETSC.CPP:

// Overhang mode is kind of goofy and I created it based on experimentation I
// did with putty.  Basically, if the cursor is in the last column and you
// print a character there you do not automatically wrap.  You only wrap to
// the first column on the next line if another character gets printed.
// This allows you to put a character in the last column, and then interpret
// a control code such as Backspace, LF or CR while still on that same line.

From the telnet server host, we can run the following to get a hex dump of the packet contents, including the status line that caused the issue:

sudo tcpdump -i ens160 dst misc.home.arpa and src xt.home.arpa and src port telnet -X
02:11:04.009483 IP misc.home.arpa.telnet > xt.home.arpa.pluribus: Flags [P.], seq 247231475:247231587, ack 1849633838, win 64134, length 112
	0x0000:  4510 0098 c703 4000 4006 5981 0a00 0303  E.....@.@.Y.....
	0x0010:  0a00 02c9 0017 0d8d 0ebc 73f3 6e3f 2c2e  ..........s.n?,.
	0x0020:  5018 fa86 1a56 0000 1b5b 3330 6d1b 5b34  P....V...[30m.[4
	0x0030:  326d 1b5b 3235 3b31 485b 305d 2030 3a69  2m.[25;1H[0].0:i
	0x0040:  7273 7369 2d20 313a 6261 7368 2a20 2020  rssi-.1:bash*...
	0x0050:  2020 2020 2020 2020 2020 2020 2020 2020  ................
	0x0060:  2020 205b 302c 305d 2022 6d69 7363 2e68  ...[0,0]."misc.h
	0x0070:  6f6d 652e 6172 7061 2220 3032 3a31 3120  ome.arpa".02:11.
	0x0080:  3235 2d4e 6f76 2d32 341b 5b30 3b31 306d  25-Nov-24.[0;10m
	0x0090:  1b5b 3133 3b31 3948                      .[13;19H

This hex dump is equivalent to:

printf "\e[30m\e[42m\e[25;1H[0] 0:irssi- 1:bash*                      [0,0] \"misc.home.arpa\" 02:13 25-Nov-24\e[0;10m\e[13;19H"

The control sequences are:

Sequence Category Description
\e[30m Select Graphic Rendition Set the foreground to black, see tput setaf 0 | xxd
\e[42m Select Graphic Rendition Set the background color to green, see tput setab 2 | xxd
\e[25;1H Direct Cursor Addressing Set the cursor position to (25, 1), the first character of the last row of the screen
... 80 characters of text, placing us at the last character, (25, 80)
\e[0;10m Select Graphic Rendition Resets all colors using the sgr0 value for our terminal, see tput sgr0 | xxd under TERM=pcansi-mono

Note \e[ aka \x1b[ aka \033[ is known as a Control Sequence Introducer (CSI), so these are sometimes redundantly referred to as CSI sequences.

Resources

Here are a few helpful resources I found during this project:


  1. I snapped a photo of the card, for those curious:

    System/36 IBM PC XT Driver Card ↩︎