Use real ISA cards in an emulator

What is it?

This project allows the use of ISA extension cards on a modern computer over a USB interface.
The main project goal was to learn about the ISA bus, not to build a polished product.

First prototype (Arduino Mega / AVR-based)

To get a feel for the ISA bus, an Arduino Mega 2560 was manually wired to an ISA slot. Little integrated switch-mode converters provide the -5V and -12V supply rails for ISA cards, a 74HCT32 OR-gate was used as a clock buffer for the 14.31818 MHz clock.

The Arduino uses a very simple serial protocol to accept transactions from a PC.

r - read from memory  
w - write to memory  
i - read from I/O space  
o - output to I/O space  

are all of the supported transactions.
The Linux utility “isapnptools” was used back in the 1990s to configure Plug & Play ISA cards. This utility normally uses outb/inb commands to directly talk to the I/O-registers of an x86 machine. It was modified to redirect all I/O accesses to a serial connection instead.

In this video, isapnptools runs on a Linux machine, detects and configures an Aztech ISA sound card connected to the Arduino Mega and then starts a simple OPL playback routine (which sends music data to the sound cards synthesizer registers):

STM32-based ISA-over-USB card

Because the performance of the Arduino Mega was limited by the available CPU performance, not the USB bus itself, a STM32-based ISA adapter card was designed. This card includes an STM32H743 with external SDRAM and a native USB 1.1 interface. The STM + SDRAM design was also used in the CMM2 clone project, so we were already familiar with the MCU.

The x86 emulator PCem was modified to redirect certain memory and I/O calls to the STM32 card. This allows a virtual machine to use real ISA peripherals like a sound card, video card or POST analyser card:

You can see the slow scrolling performance. This is a result of the maximum transfer speed of the USB interface. For scrolling, the entire screen content needs to be read and written back to a different address. With 1000 accesses per second in total, scrolling the entire screen takes a while.

STM32-standalone PC emulation

With the fast STM32H743 and external SDRAM, a port of PCem to the 32bit ARM inside the STM32 was attempted. We were able to execute enough BIOS code to initialize the VGA card and get a first Award BIOS screen, but didn’t get any further.
PCem’s code does a lot of unaligned memory accesses (which aren’t possible on the 32bit ARM architecture).

A similar setup with a much faster, arm64 CPU like on a Raspberry Pi would be a good target platform for further experiments. This would also enable the use of the x86->arm64 JIT. The BCM2835 chips also have a SMI feature, which might be use for low-latency, high-speed bus interfacing. PCIe (either with an FPGA or WCH-IC converter) might also be an interesting target.