bochs vbe: virtual screen support and bank switch (untested)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@605 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2004-02-06 23:58:08 +00:00
parent 6411cfb6f3
commit cae61cef89
1 changed files with 67 additions and 20 deletions

View File

@ -116,11 +116,13 @@ typedef struct VGAState {
uint8_t dac_write_index; uint8_t dac_write_index;
uint8_t dac_cache[3]; /* used when writing */ uint8_t dac_cache[3]; /* used when writing */
uint8_t palette[768]; uint8_t palette[768];
uint32_t bank_offset;
#ifdef CONFIG_BOCHS_VBE #ifdef CONFIG_BOCHS_VBE
uint16_t vbe_index; uint16_t vbe_index;
uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; uint16_t vbe_regs[VBE_DISPI_INDEX_NB];
uint32_t vbe_start_addr; uint32_t vbe_start_addr;
uint32_t vbe_line_offset; uint32_t vbe_line_offset;
uint32_t vbe_bank_mask;
#endif #endif
/* display refresh support */ /* display refresh support */
DisplayState *ds; DisplayState *ds;
@ -537,28 +539,34 @@ static void vbe_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
#endif #endif
switch(s->vbe_index) { switch(s->vbe_index) {
case VBE_DISPI_INDEX_ID: case VBE_DISPI_INDEX_ID:
if (val != VBE_DISPI_ID0 && if (val == VBE_DISPI_ID0 ||
val != VBE_DISPI_ID1 && val == VBE_DISPI_ID1 ||
val != VBE_DISPI_ID2) val == VBE_DISPI_ID2) {
return; s->vbe_regs[s->vbe_index] = val;
}
break; break;
case VBE_DISPI_INDEX_XRES: case VBE_DISPI_INDEX_XRES:
if ((val > VBE_DISPI_MAX_XRES) || ((val & 7) != 0)) if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
return; s->vbe_regs[s->vbe_index] = val;
}
break; break;
case VBE_DISPI_INDEX_YRES: case VBE_DISPI_INDEX_YRES:
if (val > VBE_DISPI_MAX_YRES) if (val <= VBE_DISPI_MAX_YRES) {
return; s->vbe_regs[s->vbe_index] = val;
}
break; break;
case VBE_DISPI_INDEX_BPP: case VBE_DISPI_INDEX_BPP:
if (val == 0) if (val == 0)
val = 8; val = 8;
if (val != 4 && val != 8 && val != 15 && if (val == 4 || val == 8 || val == 15 ||
val != 16 && val != 24 && val != 32) val == 16 || val == 24 || val == 32) {
return; s->vbe_regs[s->vbe_index] = val;
}
break; break;
case VBE_DISPI_INDEX_BANK: case VBE_DISPI_INDEX_BANK:
val &= 0xff; val &= s->vbe_bank_mask;
s->vbe_regs[s->vbe_index] = val;
s->bank_offset = (val << 16) - 0xa0000;
break; break;
case VBE_DISPI_INDEX_ENABLE: case VBE_DISPI_INDEX_ENABLE:
if (val & VBE_DISPI_ENABLED) { if (val & VBE_DISPI_ENABLED) {
@ -584,9 +592,9 @@ static void vbe_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset); s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
} }
/* we initialize graphic mode force graphic mode /* we initialize the VGA graphic mode (should be done
(should be done in BIOS) */ in BIOS) */
s->gr[6] |= 1; s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
s->cr[0x17] |= 3; /* no CGA modes */ s->cr[0x17] |= 3; /* no CGA modes */
s->cr[0x13] = s->vbe_line_offset >> 3; s->cr[0x13] = s->vbe_line_offset >> 3;
/* width */ /* width */
@ -609,12 +617,49 @@ static void vbe_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
} }
s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5); s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
s->cr[0x09] &= ~0x9f; /* no double scan */ s->cr[0x09] &= ~0x9f; /* no double scan */
s->vbe_regs[s->vbe_index] = val;
} else {
/* XXX: the bios should do that */
s->bank_offset = -0xa0000;
}
break;
case VBE_DISPI_INDEX_VIRT_WIDTH:
{
int w, h, line_offset;
if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
return;
w = val;
if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
line_offset = w >> 1;
else
line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
h = s->vram_size / line_offset;
/* XXX: support weird bochs semantics ? */
if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
return;
s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
s->vbe_line_offset = line_offset;
}
break;
case VBE_DISPI_INDEX_X_OFFSET:
case VBE_DISPI_INDEX_Y_OFFSET:
{
int x;
s->vbe_regs[s->vbe_index] = val;
s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
s->vbe_start_addr += x >> 1;
else
s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
s->vbe_start_addr >>= 2;
} }
break; break;
default: default:
break; break;
} }
s->vbe_regs[s->vbe_index] = val;
} }
} }
#endif #endif
@ -633,9 +678,9 @@ static uint32_t vga_mem_readb(uint32_t addr)
addr -= 0xa0000; addr -= 0xa0000;
break; break;
case 1: case 1:
addr -= 0xa0000; if (addr >= 0xb0000)
if (addr >= 0x10000)
return 0xff; return 0xff;
addr += s->bank_offset;
break; break;
case 2: case 2:
addr -= 0xb0000; addr -= 0xb0000;
@ -711,9 +756,9 @@ void vga_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
addr -= 0xa0000; addr -= 0xa0000;
break; break;
case 1: case 1:
addr -= 0xa0000; if (addr >= 0xb0000)
if (addr >= 0x10000)
return; return;
addr += s->bank_offset;
break; break;
case 2: case 2:
addr -= 0xb0000; addr -= 0xb0000;
@ -1611,9 +1656,11 @@ int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base,
register_ioport_read(0x3d4, 2, vga_ioport_read, 1); register_ioport_read(0x3d4, 2, vga_ioport_read, 1);
register_ioport_read(0x3ba, 1, vga_ioport_read, 1); register_ioport_read(0x3ba, 1, vga_ioport_read, 1);
register_ioport_read(0x3da, 1, vga_ioport_read, 1); register_ioport_read(0x3da, 1, vga_ioport_read, 1);
s->bank_offset = -0xa0000;
#ifdef CONFIG_BOCHS_VBE #ifdef CONFIG_BOCHS_VBE
s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0; s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
register_ioport_read(0x1ce, 1, vbe_ioport_read, 2); register_ioport_read(0x1ce, 1, vbe_ioport_read, 2);
register_ioport_read(0x1cf, 1, vbe_ioport_read, 2); register_ioport_read(0x1cf, 1, vbe_ioport_read, 2);