//#define DEBUG_VGA_MEM
//#define DEBUG_VGA_REG
-//#define DEBUG_S3
//#define DEBUG_BOCHS_VBE
-/* S3 VGA is deprecated - another graphic card will be emulated */
-//#define CONFIG_S3VGA
-
/* force some bits to zero */
const uint8_t sr_mask[8] = {
(uint8_t)~0xfc,
case 0x3c7:
val = s->dac_state;
break;
+ case 0x3c8:
+ val = s->dac_write_index;
+ break;
case 0x3c9:
val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
if (++s->dac_sub_index == 3) {
val = s->cr[s->cr_index];
#ifdef DEBUG_VGA_REG
printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
-#endif
-#ifdef DEBUG_S3
- if (s->cr_index >= 0x20)
- printf("S3: CR read index=0x%x val=0x%x\n",
- s->cr_index, val);
#endif
break;
case 0x3ba:
printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
#endif
/* handle CR0-7 protection */
- if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
+ if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
/* can always write bit 4 of CR7 */
if (s->cr_index == 7)
s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
case 0x12: /* veritcal display end */
s->cr[s->cr_index] = val;
break;
-
-#ifdef CONFIG_S3VGA
- /* S3 registers */
- case 0x2d:
- case 0x2e:
- case 0x2f:
- case 0x30:
- /* chip ID, cannot write */
- break;
- case 0x31:
- /* update start address */
- {
- int v;
- s->cr[s->cr_index] = val;
- v = (val >> 4) & 3;
- s->cr[0x69] = (s->cr[69] & ~0x03) | v;
- }
- break;
- case 0x51:
- /* update start address */
- {
- int v;
- s->cr[s->cr_index] = val;
- v = val & 3;
- s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
- }
- break;
-#endif
default:
s->cr[s->cr_index] = val;
break;
}
-#ifdef DEBUG_S3
- if (s->cr_index >= 0x20)
- printf("S3: CR write index=0x%x val=0x%x\n",
- s->cr_index, val);
-#endif
break;
case 0x3ba:
case 0x3da:
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
VGAState *s = opaque;
- int memory_map_mode, plane, write_mode, b, func_select;
+ int memory_map_mode, plane, write_mode, b, func_select, mask;
uint32_t write_mask, bit_mask, set_mask;
#ifdef DEBUG_VGA_MEM
if (s->sr[4] & 0x08) {
/* chain 4 mode : simplest access */
plane = addr & 3;
- if (s->sr[2] & (1 << plane)) {
+ mask = (1 << plane);
+ if (s->sr[2] & mask) {
s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM
printf("vga: chain4: [0x%x]\n", addr);
#endif
+ s->plane_updated |= mask; /* only used to detect font change */
cpu_physical_memory_set_dirty(s->vram_offset + addr);
}
} else if (s->gr[5] & 0x10) {
/* odd/even mode (aka text mode mapping) */
plane = (s->gr[4] & 2) | (addr & 1);
- if (s->sr[2] & (1 << plane)) {
+ mask = (1 << plane);
+ if (s->sr[2] & mask) {
addr = ((addr & ~1) << 1) | plane;
s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM
printf("vga: odd/even: [0x%x]\n", addr);
#endif
+ s->plane_updated |= mask; /* only used to detect font change */
cpu_physical_memory_set_dirty(s->vram_offset + addr);
}
} else {
do_write:
/* mask data according to sr[2] */
- write_mask = mask16[s->sr[2]];
+ mask = s->sr[2];
+ s->plane_updated |= mask; /* only used to detect font change */
+ write_mask = mask16[mask];
((uint32_t *)s->vram_ptr)[addr] =
(((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
(val & write_mask);
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
{
- /* XXX: TODO */
- return 0;
+ return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
}
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
{
/* compute line_offset in bytes */
line_offset = s->cr[0x13];
-#ifdef CONFIG_S3VGA
- {
- uinr32_t v;
- v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
- if (v == 0)
- v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
- line_offset |= (v << 8);
- }
-#endif
line_offset <<= 3;
-
+
/* starting address */
start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
-#ifdef CONFIG_S3VGA
- start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
-#endif
}
*pline_offset = line_offset;
*pstart_addr = start_addr;
s->font_offsets[1] = offset;
full_update = 1;
}
-
+ if (s->plane_updated & (1 << 2)) {
+ /* if the plane 2 was modified since the last display, it
+ indicates the font may have been modified */
+ s->plane_updated = 0;
+ full_update = 1;
+ }
full_update |= update_basic_params(s);
line_offset = s->line_offset;
return ret;
}
+static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
+{
+ int width, height;
+
+ width = (s->cr[0x01] + 1) * 8;
+ height = s->cr[0x12] |
+ ((s->cr[0x07] & 0x02) << 7) |
+ ((s->cr[0x07] & 0x40) << 3);
+ height = (height + 1);
+ *pwidth = width;
+ *pheight = height;
+}
+
void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
{
int y;
full_update |= update_basic_params(s);
- width = (s->cr[0x01] + 1) * 8;
- height = s->cr[0x12] |
- ((s->cr[0x07] & 0x02) << 7) |
- ((s->cr[0x07] & 0x40) << 3);
- height = (height + 1);
+ s->get_resolution(s, &width, &height);
disp_width = width;
shift_control = (s->gr[0x05] >> 5) & 3;
- double_scan = (s->cr[0x09] & 0x80);
- if (shift_control > 1) {
- multi_scan = (s->cr[0x09] & 0x1f);
+ double_scan = (s->cr[0x09] >> 7);
+ if (shift_control != 1) {
+ multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
} else {
- multi_scan = 0;
+ /* in CGA modes, multi_scan is ignored */
+ /* XXX: is it correct ? */
+ multi_scan = double_scan;
}
multi_run = multi_scan;
if (shift_control != s->shift_control ||
line_offset = s->line_offset;
#if 0
- printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
+ printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
#endif
addr1 = (s->start_addr * 4);
}
page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
- update = full_update | cpu_physical_memory_is_dirty(page0) |
- cpu_physical_memory_is_dirty(page1);
+ update = full_update |
+ cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
+ cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
if ((page1 - page0) > TARGET_PAGE_SIZE) {
/* if wide line, can use another page */
- update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
+ update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
+ VGA_DIRTY_FLAG);
}
/* explicit invalidation for the hardware cursor */
update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
}
}
if (!multi_run) {
- if (!double_scan || (y & 1) != 0) {
- if (y1 == s->line_compare) {
- addr1 = 0;
- } else {
- mask = (s->cr[0x17] & 3) ^ 3;
- if ((y1 & mask) == mask)
- addr1 += line_offset;
- }
- y1++;
- }
+ mask = (s->cr[0x17] & 3) ^ 3;
+ if ((y1 & mask) == mask)
+ addr1 += line_offset;
+ y1++;
multi_run = multi_scan;
} else {
multi_run--;
- y1++;
}
+ /* line compare acts on the displayed lines */
+ if (y == s->line_compare)
+ addr1 = 0;
d += linesize;
}
if (y_start >= 0) {
}
/* reset modified pages */
if (page_max != -1) {
- cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
+ cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
+ VGA_DIRTY_FLAG);
}
memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
}
}
}
+/* force a full display refresh */
+void vga_invalidate_display(void)
+{
+ VGAState *s = vga_state;
+
+ s->last_width = -1;
+ s->last_height = -1;
+}
+
static void vga_reset(VGAState *s)
{
memset(s, 0, sizeof(VGAState));
-#ifdef CONFIG_S3VGA
- /* chip ID for 8c968 */
- s->cr[0x2d] = 0x88;
- s->cr[0x2e] = 0xb0;
- s->cr[0x2f] = 0x01; /* XXX: check revision code */
- s->cr[0x30] = 0xe1;
-#endif
s->graphic_mode = -1; /* force full update */
}
uint32_t addr, uint32_t size, int type)
{
VGAState *s = vga_state;
-
- cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
+ if (region_num == PCI_ROM_SLOT) {
+ cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
+ } else {
+ cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
+ }
}
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
s->ds = ds;
s->get_bpp = vga_get_bpp;
s->get_offsets = vga_get_offsets;
+ s->get_resolution = vga_get_resolution;
/* XXX: currently needed for display */
vga_state = s;
}
-int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base,
- unsigned long vga_ram_offset, int vga_ram_size,
- int is_pci)
+int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size,
+ unsigned long vga_bios_offset, int vga_bios_size)
{
VGAState *s;
cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
vga_io_memory);
- if (is_pci) {
+ if (bus) {
PCIDevice *d;
uint8_t *pci_conf;
- d = pci_register_device("VGA",
+ d = pci_register_device(bus, "VGA",
sizeof(PCIDevice),
- 0, -1,
- NULL, NULL);
+ -1, NULL, NULL);
pci_conf = d->config;
pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
pci_conf[0x01] = 0x12;
/* XXX: vga_ram_size must be a power of two */
pci_register_io_region(d, 0, vga_ram_size,
PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+ if (vga_bios_size != 0) {
+ unsigned int bios_total_size;
+ s->bios_offset = vga_bios_offset;
+ s->bios_size = vga_bios_size;
+ /* must be a power of two */
+ bios_total_size = 1;
+ while (bios_total_size < vga_bios_size)
+ bios_total_size <<= 1;
+ pci_register_io_region(d, PCI_ROM_SLOT, bios_total_size,
+ PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+ }
} else {
#ifdef CONFIG_BOCHS_VBE
/* XXX: use optimized standard vga accesses */
DisplayState *saved_ds, ds1, *ds = &ds1;
/* XXX: this is a little hackish */
- s->last_width = -1;
- s->last_height = -1;
+ vga_invalidate_display();
saved_ds = s->ds;
memset(ds, 0, sizeof(DisplayState));