Some changes for the Bochs VBE support.

- Limit VBE bank size to 64k as expected.
- Enabling VBE mode now clears the whole video memory for all bpp modes unless
  "noclear" bit is set.
- Prepared 32k bank granularity mode required for text output functions. Added
  new VBE_DISPI_ID6 to indicate this capability. The default is still 64k.
This commit is contained in:
Volker Ruppert 2021-05-21 20:49:34 +00:00
parent f36ce19524
commit 43033b2137
2 changed files with 42 additions and 14 deletions

View File

@ -106,6 +106,7 @@ bool bx_vga_c::init_vga_extension(void)
BX_VGA_THIS vbe.yres=480;
BX_VGA_THIS vbe.bpp=8;
BX_VGA_THIS vbe.bank=0;
BX_VGA_THIS vbe.bank_granularity_kb=64;
BX_VGA_THIS vbe.curindex=0;
BX_VGA_THIS vbe.offset_x=0;
BX_VGA_THIS vbe.offset_y=0;
@ -188,6 +189,7 @@ void bx_vga_c::register_state(void)
new bx_shadow_num_c(vbe, "yres", &BX_VGA_THIS vbe.yres);
new bx_shadow_num_c(vbe, "bpp", &BX_VGA_THIS vbe.bpp);
new bx_shadow_num_c(vbe, "bank", &BX_VGA_THIS vbe.bank);
new bx_shadow_num_c(vbe, "bank_granularity_kb", &BX_VGA_THIS vbe.bank_granularity_kb);
BXRS_PARAM_BOOL(vbe, enabled, BX_VGA_THIS vbe.enabled);
new bx_shadow_num_c(vbe, "curindex", &BX_VGA_THIS vbe.curindex);
new bx_shadow_num_c(vbe, "visible_screen_size", &BX_VGA_THIS vbe.visible_screen_size);
@ -736,9 +738,13 @@ bx_vga_c::vbe_mem_read(bx_phy_address addr)
if (addr >= BX_VGA_THIS vbe.base_address) {
// LFB read
offset = (Bit32u)(addr - BX_VGA_THIS vbe.base_address);
} else {
} else if (addr < 0xB0000) {
// banked mode read
offset = (Bit32u)(BX_VGA_THIS vbe.bank*65536 + addr - 0xA0000);
offset = (Bit32u)(BX_VGA_THIS vbe.bank * (BX_VGA_THIS vbe.bank_granularity_kb << 10) +
(addr & 0xffff));
} else {
// out of bounds read
return 0;
}
// check for out of memory read
@ -757,9 +763,13 @@ bx_vga_c::vbe_mem_write(bx_phy_address addr, Bit8u value)
if (addr >= BX_VGA_THIS vbe.base_address) {
// LFB write
offset = (Bit32u)(addr - BX_VGA_THIS vbe.base_address);
} else {
} else if (addr < 0xB0000) {
// banked mode write
offset = (Bit32u)(BX_VGA_THIS vbe.bank*65536 + (addr - 0xA0000));
offset = (Bit32u)(BX_VGA_THIS vbe.bank * (BX_VGA_THIS vbe.bank_granularity_kb << 10) +
(addr & 0xffff));
} else {
// ignore out of bounds write
return;
}
// check for out of memory write
@ -894,7 +904,7 @@ Bit32u bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len)
#else
UNUSED(this_ptr);
#endif
Bit16u max_xres, max_yres, max_bpp;
Bit16u max_xres, max_yres, max_bpp, new_bank_gran;
bool new_vbe_8bit_dac;
bool needs_update = 0;
unsigned i;
@ -921,7 +931,8 @@ Bit32u bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len)
(value == VBE_DISPI_ID2) ||
(value == VBE_DISPI_ID3) ||
(value == VBE_DISPI_ID4) ||
(value == VBE_DISPI_ID5))
(value == VBE_DISPI_ID5) ||
(value == VBE_DISPI_ID6))
{
// allow backwards compatible with previous dispi bioses
BX_VGA_THIS vbe.cur_dispi=value;
@ -1011,13 +1022,18 @@ Bit32u bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len)
case VBE_DISPI_INDEX_BANK: // set bank
{
value=value & 0xff; // FIXME lobyte = vbe bank A?
unsigned divider = (BX_VGA_THIS vbe.bpp!=VBE_DISPI_BPP_4)?64:256;
Bit16u num_banks = (Bit16u)(VBE_DISPI_TOTAL_VIDEO_MEMORY_KB / BX_VGA_THIS vbe.bank_granularity_kb);
if (BX_VGA_THIS vbe.bpp == VBE_DISPI_BPP_4) num_banks >>= 2;
value &= 0x1ff;
// check for max bank nr
if (value < (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB / divider)) {
if (value < num_banks) {
BX_DEBUG(("VBE set bank to %d", value));
BX_VGA_THIS vbe.bank = value;
BX_VGA_THIS s.plane_offset = (BX_VGA_THIS vbe.bank << 16);
if (BX_VGA_THIS vbe.bank_granularity_kb == 64) {
BX_VGA_THIS s.plane_offset = (BX_VGA_THIS vbe.bank << 16);
} else {
BX_VGA_THIS s.plane_offset = (BX_VGA_THIS vbe.bank << 15);
}
} else {
BX_ERROR(("VBE set invalid bank (%d)", value));
}
@ -1081,10 +1097,10 @@ Bit32u bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len)
BX_INFO(("VBE enabling x %d, y %d, bpp %d, %u bytes visible", BX_VGA_THIS vbe.xres, BX_VGA_THIS vbe.yres, BX_VGA_THIS vbe.bpp, BX_VGA_THIS vbe.visible_screen_size));
if ((value & VBE_DISPI_NOCLEARMEM) == 0) {
memset(BX_VGA_THIS s.memory, 0, VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES);
}
if (depth > 4) {
if ((value & VBE_DISPI_NOCLEARMEM) == 0) {
memset(BX_VGA_THIS s.memory, 0, BX_VGA_THIS vbe.visible_screen_size);
}
bx_gui->dimension_update(BX_VGA_THIS vbe.xres, BX_VGA_THIS vbe.yres, 0, 0, depth);
BX_VGA_THIS s.last_bpp = depth;
BX_VGA_THIS s.last_fh = 0;
@ -1111,6 +1127,16 @@ Bit32u bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len)
BX_VGA_THIS vbe.max_bpp = max_bpp;
}
}
if ((value & VBE_DISPI_BANK_GRANULARITY_32K) != 0) {
new_bank_gran = 32;
} else {
new_bank_gran = 64;
}
if (new_bank_gran != BX_VGA_THIS vbe.bank_granularity_kb) {
BX_VGA_THIS vbe.bank_granularity_kb = new_bank_gran;
BX_VGA_THIS vbe.bank = 0;
BX_VGA_THIS s.plane_offset = 0;
}
new_vbe_8bit_dac = ((value & VBE_DISPI_8BIT_DAC) != 0);
if (new_vbe_8bit_dac != BX_VGA_THIS vbe.dac_8bit) {
if (new_vbe_8bit_dac) {

View File

@ -30,7 +30,6 @@
#define VBE_DISPI_4BPP_PLANE_SHIFT 22
#define VBE_DISPI_BANK_ADDRESS 0xA0000
#define VBE_DISPI_BANK_SIZE_KB 64
#define VBE_DISPI_MAX_XRES 2560
#define VBE_DISPI_MAX_YRES 1600
@ -58,6 +57,7 @@
#define VBE_DISPI_ID3 0xB0C3
#define VBE_DISPI_ID4 0xB0C4
#define VBE_DISPI_ID5 0xB0C5
#define VBE_DISPI_ID6 0xB0C6
#define VBE_DISPI_BPP_4 0x04
#define VBE_DISPI_BPP_8 0x08
@ -69,6 +69,7 @@
#define VBE_DISPI_DISABLED 0x00
#define VBE_DISPI_ENABLED 0x01
#define VBE_DISPI_GETCAPS 0x02
#define VBE_DISPI_BANK_GRANULARITY_32K 0x10
#define VBE_DISPI_8BIT_DAC 0x20
#define VBE_DISPI_LFB_ENABLED 0x40
#define VBE_DISPI_NOCLEARMEM 0x80
@ -148,6 +149,7 @@ private:
Bit16u max_yres;
Bit16u max_bpp;
Bit16u bank;
Bit16u bank_granularity_kb;
bool enabled;
Bit16u curindex;
Bit32u visible_screen_size; /**< in bytes */