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), and 0x3BA is a mirror of 0x3DA in monochrome mode. A vga_port_active() helper is added to check the current mode so that the monochrome ports share the same logic and env state as the colour ports. Reads to 0x3BA/0x3DA also use this helper, so the 0x3C0 address flip-flop is reset and the 0x3DA status bits are toggled only when the accessed port is decoded in the current mode. This also means 0x3DA no longer decodes in monochrome mode, which matches real hardware. 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. While these changes are needed for the Aspeed AST2600 VBIOS to run, these VGA ports are part of the general VGA spec and might be useful for other VBIOSes. Signed-off-by: Anirudh Srinivasan <[email protected]> --- drivers/bios_emulator/besys.c | 50 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/drivers/bios_emulator/besys.c b/drivers/bios_emulator/besys.c index 76a05e74f55..5c440c6792e 100644 --- a/drivers/bios_emulator/besys.c +++ b/drivers/bios_emulator/besys.c @@ -248,11 +248,27 @@ 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) +/**************************************************************************** +PARAMETERS: +port - Port to check + +REMARKS: +Some VGA ports (the CRTC index/data pair 3B4/3D4 and 3B5/3D5, and +Input Status Register 1 3BA/3DA) have a monochrome (0x3Bx) and a +colour (0x3Dx) alias. Bit 0 of 0x3C2 selects which one is decoded: +0x3Bx when clear, 0x3Dx when set. Return true if port is decoded in +the current mode. +****************************************************************************/ +static bool vga_port_active(int port) +{ + return (port >= 0x3d0) == !!(_BE_env.emu3C2 & 1); +} + /**************************************************************************** PARAMETERS: port - Port to read from @@ -313,18 +329,28 @@ static u8 VGA_inpb (const int port) if (_BE_env.emu3CE < GRA_C) return _BE_env.emu3CF[_BE_env.emu3CE]; break; + /* + * 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: case 0x3D4: - if (_BE_env.emu3C2 & 0x1) + if (vga_port_active(port)) return _BE_env.emu3D4; break; + case 0x3B5: case 0x3D5: - if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C)) + if (vga_port_active(port) && (_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; - _BE_env.emu3DA ^= 0x9; + if (vga_port_active(port)) { + _BE_env.flipFlop3C0 = 0; + val = _BE_env.emu3DA; + _BE_env.emu3DA ^= 0x9; + } break; } return val; @@ -390,12 +416,18 @@ static void VGA_outpb (int port, u8 val) if (_BE_env.emu3CE < GRA_C) _BE_env.emu3CF[_BE_env.emu3CE] = val; break; + /* + * 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: case 0x3D4: - if (_BE_env.emu3C2 & 0x1) + if (vga_port_active(port)) _BE_env.emu3D4 = val; break; + case 0x3B5: case 0x3D5: - if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C)) + if (vga_port_active(port) && (_BE_env.emu3D4 < CRT_C)) _BE_env.emu3D5[_BE_env.emu3D4] = val; break; } -- 2.43.0
