summaryrefslogtreecommitdiff
path: root/hw/vga.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/vga.c')
-rw-r--r--hw/vga.c136
1 files changed, 82 insertions, 54 deletions
diff --git a/hw/vga.c b/hw/vga.c
index 8f748b3711..c77b9f9ff1 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -143,9 +143,6 @@ static uint32_t expand4[256];
static uint16_t expand2[256];
static uint8_t expand4to8[16];
-VGAState *vga_state;
-int vga_io_memory;
-
static void vga_screen_dump(void *opaque, const char *filename);
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
@@ -1624,6 +1621,9 @@ static void vga_save(QEMUFile *f, void *opaque)
VGAState *s = opaque;
int i;
+ if (s->pci_dev)
+ pci_device_save(s->pci_dev, f);
+
qemu_put_be32s(f, &s->latch);
qemu_put_8s(f, &s->sr_index);
qemu_put_buffer(f, s->sr, 8);
@@ -1663,11 +1663,17 @@ static void vga_save(QEMUFile *f, void *opaque)
static int vga_load(QEMUFile *f, void *opaque, int version_id)
{
VGAState *s = opaque;
- int is_vbe, i;
+ int is_vbe, i, ret;
- if (version_id != 1)
+ if (version_id > 2)
return -EINVAL;
+ if (s->pci_dev && version_id >= 2) {
+ ret = pci_device_load(s->pci_dev, f);
+ if (ret < 0)
+ return ret;
+ }
+
qemu_get_be32s(f, &s->latch);
qemu_get_8s(f, &s->sr_index);
qemu_get_buffer(f, s->sr, 8);
@@ -1711,10 +1717,16 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
+typedef struct PCIVGAState {
+ PCIDevice dev;
+ VGAState vga_state;
+} PCIVGAState;
+
static void vga_map(PCIDevice *pci_dev, int region_num,
uint32_t addr, uint32_t size, int type)
{
- VGAState *s = vga_state;
+ PCIVGAState *d = (PCIVGAState *)pci_dev;
+ VGAState *s = &d->vga_state;
if (region_num == PCI_ROM_SLOT) {
cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
} else {
@@ -1761,24 +1773,14 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
s->get_resolution = vga_get_resolution;
graphic_console_init(s->ds, vga_update_display, vga_invalidate_display,
vga_screen_dump, s);
- /* XXX: currently needed for display */
- vga_state = s;
}
-
-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)
+/* used by both ISA and PCI */
+static void vga_init(VGAState *s)
{
- VGAState *s;
+ int vga_io_memory;
- s = qemu_mallocz(sizeof(VGAState));
- if (!s)
- return -1;
-
- vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
-
- register_savevm("vga", 0, 1, vga_save, vga_load, s);
+ register_savevm("vga", 0, 2, vga_save, vga_load, s);
register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
@@ -1823,43 +1825,69 @@ int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
vga_io_memory);
+}
+
+int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size)
+{
+ VGAState *s;
+
+ s = qemu_mallocz(sizeof(VGAState));
+ if (!s)
+ return -1;
+
+ vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+ vga_init(s);
- if (bus) {
- PCIDevice *d;
- uint8_t *pci_conf;
-
- d = pci_register_device(bus, "VGA",
- sizeof(PCIDevice),
- -1, NULL, NULL);
- pci_conf = d->config;
- pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
- pci_conf[0x01] = 0x12;
- pci_conf[0x02] = 0x11;
- pci_conf[0x03] = 0x11;
- pci_conf[0x0a] = 0x00; // VGA controller
- pci_conf[0x0b] = 0x03;
- pci_conf[0x0e] = 0x00; // header_type
-
- /* 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 */
- cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
- vga_ram_size, vga_ram_offset);
+ /* XXX: use optimized standard vga accesses */
+ cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
+ vga_ram_size, vga_ram_offset);
#endif
+ return 0;
+}
+
+int pci_vga_init(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)
+{
+ PCIVGAState *d;
+ VGAState *s;
+ uint8_t *pci_conf;
+
+ d = (PCIVGAState *)pci_register_device(bus, "VGA",
+ sizeof(PCIVGAState),
+ -1, NULL, NULL);
+ if (!d)
+ return -1;
+ s = &d->vga_state;
+
+ vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+ vga_init(s);
+ s->pci_dev = &d->dev;
+
+ pci_conf = d->dev.config;
+ pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
+ pci_conf[0x01] = 0x12;
+ pci_conf[0x02] = 0x11;
+ pci_conf[0x03] = 0x11;
+ pci_conf[0x0a] = 0x00; // VGA controller
+ pci_conf[0x0b] = 0x03;
+ pci_conf[0x0e] = 0x00; // header_type
+
+ /* XXX: vga_ram_size must be a power of two */
+ pci_register_io_region(&d->dev, 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->dev, PCI_ROM_SLOT, bios_total_size,
+ PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
}
return 0;
}