ISA I/O space
x86 has a separate 16-bit I/O address space (ports 0x0000–0xFFFF) accessed with IN and OUT instructions. v86 implements this as a flat array of 65 536 handler records in src/io.js. When WASM executes IN AL, DX, it calls the JS import io_port_read8(DX) → JS dispatches to the registered device handler.
Read/Write Dispatch Flow
WASMGuest executes
IN AL, 0x60⟱
CPU encodes port 0x60, size=1 (byte)
WASM → JSCalls imported function
⟱
io_port_read8(0x60) — crosses WASM/JS boundaryio.jsLooks up port handler
⟱
io_port_map[0x60].read8 — registered by PS/2 device at initps2.jsDevice handler runs
⟱
Dequeues next scancode from keyboard FIFO, returns byte value
JS → WASMReturns to WASM
⟰
Return value (e.g.
0x1C = "A" pressed) placed in AL registerPort Assignment Map
Click any row for details about that port range.
Port RangeDeviceIRQ / Note
0x0000–0x001F
DMA Controller 1
ch 0–3
0x0020–0x003F
PIC 1 (8259A)
master
0x0040–0x0047
PIT Timer (8254)
IRQ 0
0x0060, 0x0064
PS/2 Controller (8042)
IRQ 1, 12
0x0061
A20 Gate / PC Speaker
sys ctrl
0x0070–0x0071
RTC / CMOS
IRQ 8
0x0080–0x008F
DMA Page Registers
ch 0–7
0x00A0–0x00BF
PIC 2 (8259A)
slave
0x00C0–0x00DF
DMA Controller 2
ch 4–7
0x0170–0x0177, 0x0376
IDE Secondary
IRQ 15
0x01F0–0x01F7, 0x03F6
IDE Primary
IRQ 14
0x0220–0x0233
SoundBlaster 16
IRQ 5
0x0280–0x029F
NE2000 Network Card
IRQ 9
0x02F8–0x02FF
UART COM2
IRQ 3
0x03C0–0x03DF
VGA Registers
—
0x03F0–0x03F7
Floppy Controller
IRQ 6
0x03F8–0x03FF
UART COM1
IRQ 4
0x0CF8–0x0CFF
PCI Configuration
—
0xE000–0xE0FF (var)
Virtio I/O Port BAR
PCI IRQ
Port Handler Record
Per-port handler record
Each of the 65 536 ports has a record with up to 6 functions (read8, read16, read32, write8, write16, write32) plus a device back-reference. Unregistered ports have null handlers and return 0xFF on reads.
| Function | Called when | Typical return |
|---|---|---|
| read8(port) | Guest: IN AL, port | 8-bit device register value |
| read16(port) | Guest: IN AX, port | 16-bit value (or two 8-bit reads chained) |
| read32(port) | Guest: IN EAX, port | 32-bit value (PCI config data etc.) |
| write8(port, val) | Guest: OUT port, AL | — |
| write16(port, val) | Guest: OUT port, AX | — |
| write32(port, val) | Guest: OUT port, EAX | — |
VGA Port Breakdown (0x03C0–0x03DF)
VGA has the most complex port layout — 14 registers spread across a 32-byte window.
| Port | Name | Description |
|---|---|---|
| 0x3C0 | AC Index+Data | Attribute Controller: write index, then data alternately. Controls color palette, overscan, display mode. |
| 0x3C2 | Misc Output (W) / Input Status 0 (R) | Clock select, sync polarity, page select (write); feature bits, CRT interrupt (read). |
| 0x3C4 | Sequencer Index | Selects sequencer register: reset, clocking mode, map mask, character map, memory mode. |
| 0x3C5 | Sequencer Data | Reads/writes the selected sequencer register. |
| 0x3C6 | DAC PEL Mask | Masks bits passed to palette DAC (normally 0xFF). |
| 0x3C7 | DAC State / DAC Read Index | Read: DAC state. Write: set read index for DAC palette reads. |
| 0x3C8 | DAC Write Index | Select DAC palette entry to write (0–255). |
| 0x3C9 | DAC Data | Read/write R,G,B bytes for selected palette entry (6 bits each, 0–63). |
| 0x3CA | Feature Control (R) | Reads back the feature control register. |
| 0x3CC | Misc Output (R) | Reads back the miscellaneous output register. |
| 0x3CE | GC Index | Graphics Controller index: set/reset, enable S/R, color compare, rotate, read map, mode, misc, color don't care, bitmask. |
| 0x3CF | GC Data | Read/write selected Graphics Controller register. |
| 0x3D4 | CRTC Index | CRT Controller: selects from 25 registers (htotal, hdisplay end, cursor, start/end, vretrace, etc.). |
| 0x3D5 | CRTC Data | Read/write selected CRTC register. |
| 0x3DA | Input Status 1 | Vertical retrace and display enable bits. Also resets AC flip-flop for attribute controller access. |