First post, by manawyrm
Hi!
I'm building this slightly weird contraption to learn more about the ISA bus.
I have connected an ISA slot to an Arduino Mega (basically just an AVR microprocessor with a lot of 5V capable I/O pins) and I'm directly writing and reading from an attached ISA card.
One of my targets is to output video over a VGA graphics card.
For this to work it needs to execute the Video BIOS ROM, which consists of (up to) 32KiB of x86 Real-Mode code.
I'm using a simple serial ASCII protocol to offer 4 commands:
r - read from memory
w - write to memory
i - read from I/O space
o - output to I/O space
These commands are new-line seperated and can only do single byte transfers.
Here's the code running on the Arduino: https://github.com/Manawyrm/ISAMega/blob/d80e … ee/src/main.cpp
I've utilized the libx86emu library on a PC to emulate an x86 processor and system:
https://gist.github.com/Manawyrm/d5d9c6d5d7fc … 20ac755aaffdbf6
This code will redirect all I/Os, any memory read/write operations on the video memory and the video option ROM to the ISA card.
It's running a very small piece of code that does a "far call"-jump to 0x0C003 (aka the entry point for the video ROM).
Some video BIOSes will call INT 10h when there isn't an interrupt vector registered yet.
What does a normal BIOS do when INT 10h is called before any video ROM was executed?
I have written a small dummy function that will return 0x12 ("function supported") in the AL register whenever INT 10h is called without any other interrupt vector being present.
But I'm really not sure if this is a good idea / anywhere near correct behaviour.
What happens on 16bit memory read instructions on an 8bit ISA bus?
My current behaviour is just to do 2 bus cycles:
memoutb(addr, *val & 0xFF);
memoutb(addr + 1, (*val << 8) & 0xFF);
But that also causes 2 strobes of the ~MEMR/~MEMW [edit: this said IOR/IOW in a previous version] lines. How does a normal CPU behave here?
I have tested 3 cards:
- ATI VGA Wonder-16
- Trident TVGA8900C
- Trident TVGA9000B
The ATI card will execute the BIOS pretty far and then get stuck in an infinite loop reading from I/O port 0x3DA (status?) waiting for 0x08 (bit 3).
The Trident cards show a strange behaviour: the BIOS ROM will run for a while and will then write to 0x0B0000 (video memory). The Trident card pulls IOCHRDY (aka wait) low permanently, stalling the ISA bus and never returning. Any ideas on why write calls to the video memory might cause IOCHRDY to be low permanently?
Hardware-wise I've connected:
- GND, VCC
- D0-7 to a port on the Arduino
- A0-A19 to 3 ports on the Arduino
- IOCHRDY is connected to a pin on the Arduino
- REFRESH is connected to VCC/5V via a Resistor
- ~MEMW, ~MEMR, ~IOW, ~IOR to pins on the Arduino
- OSC is connected to a square wave oscillator (14.31818MHz, 5V amplitude, 2.5V offset, normal TTL signal)
- CLK pin is unconnected (it's also unconnected on all of my ISA VGA cards).
- (B)ALE pin is pulled HIGH permanently in software (see http://www.malinov.com/Home/sergeys-projects/isa-supervga, v1.0 Errata)
- AEN is connected to the Arduino and pulled LOW in software permanently.
- RESET is also hooked up to the Arduino and gets pulsed at the initial init.
Notes:
- Only 8 bits of the data bus are used (the 16bit part is entirely unconnected)
- I'm missing the -12V and -5V rails. These don't seem to be connected anywhere, though.
- I have tested the cards for 8-bit mode compatibility by covering the 16bit pins with tape and testing them in a regular PC.
I've attached some pictures if anyone is interested in the setup:
Thanks for any advice,
Manawyrm