diff --git a/bochs/iodev/display/vga.cc b/bochs/iodev/display/vga.cc index aebba971c..a11e9c5e5 100644 --- a/bochs/iodev/display/vga.cc +++ b/bochs/iodev/display/vga.cc @@ -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) { diff --git a/bochs/iodev/display/vga.h b/bochs/iodev/display/vga.h index 3e2206247..683162b84 100644 --- a/bochs/iodev/display/vga.h +++ b/bochs/iodev/display/vga.h @@ -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 */