The IS_VGA_PORT macro currently doesn't cover the 0x3B4, 0x3B5 and 0x3BA I/O ports. Reads/writes to this currently fall through to LOG_inpb/outb which are unimplemented on non x86 architectures (which don't support I/O ports).
Add these ports to the IS_VGA_PORT macro, and implement reads/writes to these ports. 0x3B4 and 0x3B5 are mirrors of 0x3D4 and 0x3D5 that are used in monochrome mode (bit 0 of 0x3C2 is not set). Implement these with the same logic and env state as 0x3D4/0x3D5, but with the bit check condition for 0x3C2 flipped. 0x3BA is a mirror of 0x3DA, so the implementation for this falls back to the same logic as 0x3DA. The extended range also covers the non-VGA ports 0x3B6-0x3B9 and 0x3BB-0x3BF (LPT1 on legacy PCs): reads return 0xff and writes are dropped instead of reaching the real inb/outb path, which is harmless from the VBIOS's perspective. The write side handles 0x3B4/0x3B5 but not 0x3BA, consistent with the existing lack of a 0x3DA write handler. The Aspeed AST2600's VBIOS uses these I/O ports, and these changes are needed for it's VBIOS to run. Signed-off-by: Anirudh Srinivasan <[email protected]> --- drivers/bios_emulator/besys.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/bios_emulator/besys.c b/drivers/bios_emulator/besys.c index 76a05e74f55..c06ed34c0af 100644 --- a/drivers/bios_emulator/besys.c +++ b/drivers/bios_emulator/besys.c @@ -248,8 +248,8 @@ void X86API BE_wrl(u32 addr, u32 val) #define IS_TIMER_PORT(port) (0x40 <= port && port <= 0x43) #define IS_CMOS_PORT(port) (0x70 <= port && port <= 0x71) -/*#define IS_VGA_PORT(port) (_BE_env.emulateVGA && 0x3C0 <= port && port <= 0x3DA)*/ -#define IS_VGA_PORT(port) (0x3C0 <= port && port <= 0x3DA) +/*#define IS_VGA_PORT(port) (_BE_env.emulateVGA && 0x3B4 <= port && port <= 0x3DA)*/ +#define IS_VGA_PORT(port) (0x3B4 <= port && port <= 0x3DA) #define IS_PCI_PORT(port) (0xCF8 <= port && port <= 0xCFF) #define IS_SPKR_PORT(port) (port == 0x61) @@ -270,6 +270,18 @@ static u8 VGA_inpb (const int port) debug_io("vga_inb.%04X -> ", (u16) port); switch (port) { + /* + * 3B4 and 3B5 are mirrors of 3D4 and 3D5 that are used in + * monochrome mode (i.e., bit 0 of 3C2 is not set) + */ + case 0x3B4: + if (!(_BE_env.emu3C2 & 0x1)) + return _BE_env.emu3D4; + break; + case 0x3B5: + if (!(_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C)) + return _BE_env.emu3D5[_BE_env.emu3D4]; + break; case 0x3C0: /* 3C0 has funky characteristics because it can act as either a data register or index register depending on the state @@ -321,6 +333,10 @@ static u8 VGA_inpb (const int port) if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C)) return _BE_env.emu3D5[_BE_env.emu3D4]; break; + /* + * 3BA is a mirror of 3DA + */ + case 0x3BA: case 0x3DA: _BE_env.flipFlop3C0 = 0; val = _BE_env.emu3DA; @@ -343,6 +359,18 @@ to use. static void VGA_outpb (int port, u8 val) { switch (port) { + /* + * 3B4 and 3B5 are mirrors of 3D4 and 3D5 that are used in + * monochrome mode (i.e., bit 0 of 3C2 is not set) + */ + case 0x3B4: + if (!(_BE_env.emu3C2 & 0x1)) + _BE_env.emu3D4 = val; + break; + case 0x3B5: + if (!(_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C)) + _BE_env.emu3D5[_BE_env.emu3D4] = val; + break; case 0x3C0: /* 3C0 has funky characteristics because it can act as either a data register or index register depending on the state -- 2.43.0
