* THE SOFTWARE.
*/
#include "hw.h"
+#include "loader.h"
#include "console.h"
#include "pci.h"
+#include "vmware_vga.h"
#define VERBOSE
-#define EMBED_STDVGA
#undef DIRECT_VRAM
#define HW_RECT_ACCEL
#define HW_FILL_ACCEL
#define HW_MOUSE_ACCEL
-#ifdef EMBED_STDVGA
# include "vga_int.h"
-#endif
struct vmsvga_state_s {
-#ifdef EMBED_STDVGA
VGACommonState vga;
-#endif
int width;
int height;
int on;
} cursor;
-#ifndef EMBED_STDVGA
- DisplayState *ds;
- int vram_size;
- ram_addr_t vram_offset;
- uint8_t *vram_ptr;
-#endif
target_phys_addr_t vram_base;
int index;
int syncing;
int fb_size;
+ ram_addr_t fifo_offset;
+ uint8_t *fifo_ptr;
+ unsigned int fifo_size;
+ target_phys_addr_t fifo_base;
+
union {
uint32_t *fifo;
struct __attribute__((__packed__)) {
int hot_x;
int hot_y;
uint32_t mask[1024];
- uint32_t image[1024];
+ uint32_t image[4096];
};
#define SVGA_BITMAP_SIZE(w, h) ((((w) + 31) >> 5) * (h))
cursor.height = y = vmsvga_fifo_read(s);
vmsvga_fifo_read(s);
cursor.bpp = vmsvga_fifo_read(s);
+
+ if (SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask ||
+ SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) {
+ args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp);
+ goto badcmd;
+ }
+
for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args ++)
cursor.mask[args] = vmsvga_fifo_read_raw(s);
for (args = 0; args < SVGA_PIXMAP_SIZE(x, y, cursor.bpp); args ++)
static uint32_t vmsvga_index_read(void *opaque, uint32_t address)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
return s->index;
}
static void vmsvga_index_write(void *opaque, uint32_t address, uint32_t index)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
s->index = index;
}
static uint32_t vmsvga_value_read(void *opaque, uint32_t address)
{
uint32_t caps;
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
switch (s->index) {
case SVGA_REG_ID:
return s->svgaid;
return 0x0;
case SVGA_REG_VRAM_SIZE:
- return s->vga.vram_size - SVGA_FIFO_SIZE;
+ return s->vga.vram_size;
case SVGA_REG_FB_SIZE:
return s->fb_size;
return caps;
case SVGA_REG_MEM_START:
- return s->vram_base + s->vga.vram_size - SVGA_FIFO_SIZE;
+ return s->fifo_base;
case SVGA_REG_MEM_SIZE:
- return SVGA_FIFO_SIZE;
+ return s->fifo_size;
case SVGA_REG_CONFIG_DONE:
return s->config;
static void vmsvga_value_write(void *opaque, uint32_t address, uint32_t value)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
switch (s->index) {
case SVGA_REG_ID:
if (value == SVGA_ID_2 || value == SVGA_ID_1 || value == SVGA_ID_0)
s->width = -1;
s->height = -1;
s->invalidated = 1;
-#ifdef EMBED_STDVGA
s->vga.invalidate(&s->vga);
-#endif
- if (s->enable)
- s->fb_size = ((s->depth + 7) >> 3) * s->new_width * s->new_height;
+ if (s->enable) {
+ s->fb_size = ((s->depth + 7) >> 3) * s->new_width * s->new_height;
+ vga_dirty_log_stop(&s->vga);
+ } else {
+ vga_dirty_log_start(&s->vga);
+ }
break;
case SVGA_REG_WIDTH:
case SVGA_REG_CONFIG_DONE:
if (value) {
- s->fifo = (uint32_t *) &s->vga.vram_ptr[s->vga.vram_size - SVGA_FIFO_SIZE];
+ s->fifo = (uint32_t *) s->fifo_ptr;
/* Check range and alignment. */
if ((CMD(min) | CMD(max) |
CMD(next_cmd) | CMD(stop)) & 3)
static void vmsvga_update_display(void *opaque)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
if (!s->enable) {
-#ifdef EMBED_STDVGA
s->vga.update(&s->vga);
-#endif
return;
}
s->width = -1;
s->height = -1;
s->svgaid = SVGA_ID;
- s->depth = 24;
- s->bypp = (s->depth + 7) >> 3;
+ s->depth = ds_get_bits_per_pixel(s->vga.ds);
+ s->bypp = ds_get_bytes_per_pixel(s->vga.ds);
s->cursor.on = 0;
s->redraw_fifo_first = 0;
s->redraw_fifo_last = 0;
break;
}
s->syncing = 0;
+
+ vga_dirty_log_start(&s->vga);
}
static void vmsvga_invalidate_display(void *opaque)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
if (!s->enable) {
-#ifdef EMBED_STDVGA
s->vga.invalidate(&s->vga);
-#endif
return;
}
available */
static void vmsvga_screen_dump(void *opaque, const char *filename)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
if (!s->enable) {
-#ifdef EMBED_STDVGA
s->vga.screen_dump(&s->vga, filename);
-#endif
return;
}
static void vmsvga_text_update(void *opaque, console_ch_t *chardata)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
if (s->vga.text_update)
s->vga.text_update(&s->vga, chardata);
#ifdef DIRECT_VRAM
static uint32_t vmsvga_vram_readb(void *opaque, target_phys_addr_t addr)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
if (addr < s->fb_size)
return *(uint8_t *) (ds_get_data(s->ds) + addr);
else
static uint32_t vmsvga_vram_readw(void *opaque, target_phys_addr_t addr)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
if (addr < s->fb_size)
return *(uint16_t *) (ds_get_data(s->ds) + addr);
else
static uint32_t vmsvga_vram_readl(void *opaque, target_phys_addr_t addr)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
if (addr < s->fb_size)
return *(uint32_t *) (ds_get_data(s->ds) + addr);
else
static void vmsvga_vram_writeb(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
if (addr < s->fb_size)
*(uint8_t *) (ds_get_data(s->ds) + addr) = value;
else
static void vmsvga_vram_writew(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
if (addr < s->fb_size)
*(uint16_t *) (ds_get_data(s->ds) + addr) = value;
else
static void vmsvga_vram_writel(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
- struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+ struct vmsvga_state_s *s = opaque;
if (addr < s->fb_size)
*(uint32_t *) (ds_get_data(s->ds) + addr) = value;
else
*(uint32_t *) (s->vram_ptr + addr) = value;
}
-static CPUReadMemoryFunc *vmsvga_vram_read[] = {
+static CPUReadMemoryFunc * const vmsvga_vram_read[] = {
vmsvga_vram_readb,
vmsvga_vram_readw,
vmsvga_vram_readl,
};
-static CPUWriteMemoryFunc *vmsvga_vram_write[] = {
+static CPUWriteMemoryFunc * const vmsvga_vram_write[] = {
vmsvga_vram_writeb,
vmsvga_vram_writew,
vmsvga_vram_writel,
};
#endif
-static void vmsvga_save(struct vmsvga_state_s *s, QEMUFile *f)
-{
- qemu_put_be32(f, s->depth);
- qemu_put_be32(f, s->enable);
- qemu_put_be32(f, s->config);
- qemu_put_be32(f, s->cursor.id);
- qemu_put_be32(f, s->cursor.x);
- qemu_put_be32(f, s->cursor.y);
- qemu_put_be32(f, s->cursor.on);
- qemu_put_be32(f, s->index);
- qemu_put_buffer(f, (uint8_t *) s->scratch, s->scratch_size * 4);
- qemu_put_be32(f, s->new_width);
- qemu_put_be32(f, s->new_height);
- qemu_put_be32s(f, &s->guest);
- qemu_put_be32s(f, &s->svgaid);
- qemu_put_be32(f, s->syncing);
- qemu_put_be32(f, s->fb_size);
-}
-
-static int vmsvga_load(struct vmsvga_state_s *s, QEMUFile *f)
+static int vmsvga_post_load(void *opaque, int version_id)
{
- int depth;
- depth=qemu_get_be32(f);
- s->enable=qemu_get_be32(f);
- s->config=qemu_get_be32(f);
- s->cursor.id=qemu_get_be32(f);
- s->cursor.x=qemu_get_be32(f);
- s->cursor.y=qemu_get_be32(f);
- s->cursor.on=qemu_get_be32(f);
- s->index=qemu_get_be32(f);
- qemu_get_buffer(f, (uint8_t *) s->scratch, s->scratch_size * 4);
- s->new_width=qemu_get_be32(f);
- s->new_height=qemu_get_be32(f);
- qemu_get_be32s(f, &s->guest);
- qemu_get_be32s(f, &s->svgaid);
- s->syncing=qemu_get_be32(f);
- s->fb_size=qemu_get_be32(f);
-
- if (s->enable && depth != s->depth) {
- printf("%s: need colour depth of %i bits to resume operation.\n",
- __FUNCTION__, depth);
- return -EINVAL;
- }
+ struct vmsvga_state_s *s = opaque;
s->invalidated = 1;
if (s->config)
- s->fifo = (uint32_t *) &s->vga.vram_ptr[s->vga.vram_size - SVGA_FIFO_SIZE];
+ s->fifo = (uint32_t *) s->fifo_ptr;
return 0;
}
+static const VMStateDescription vmstate_vmware_vga_internal = {
+ .name = "vmware_vga_internal",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = vmsvga_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_INT32_EQUAL(depth, struct vmsvga_state_s),
+ VMSTATE_INT32(enable, struct vmsvga_state_s),
+ VMSTATE_INT32(config, struct vmsvga_state_s),
+ VMSTATE_INT32(cursor.id, struct vmsvga_state_s),
+ VMSTATE_INT32(cursor.x, struct vmsvga_state_s),
+ VMSTATE_INT32(cursor.y, struct vmsvga_state_s),
+ VMSTATE_INT32(cursor.on, struct vmsvga_state_s),
+ VMSTATE_INT32(index, struct vmsvga_state_s),
+ VMSTATE_VARRAY_INT32(scratch, struct vmsvga_state_s,
+ scratch_size, 0, vmstate_info_uint32, uint32_t),
+ VMSTATE_INT32(new_width, struct vmsvga_state_s),
+ VMSTATE_INT32(new_height, struct vmsvga_state_s),
+ VMSTATE_UINT32(guest, struct vmsvga_state_s),
+ VMSTATE_UINT32(svgaid, struct vmsvga_state_s),
+ VMSTATE_INT32(syncing, struct vmsvga_state_s),
+ VMSTATE_INT32(fb_size, struct vmsvga_state_s),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_vmware_vga = {
+ .name = "vmware_vga",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField []) {
+ VMSTATE_PCI_DEVICE(card, struct pci_vmsvga_state_s),
+ VMSTATE_STRUCT(chip, struct pci_vmsvga_state_s, 0,
+ vmstate_vmware_vga_internal, struct vmsvga_state_s),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
{
s->scratch_size = SVGA_SCRATCH_SIZE;
- s->scratch = (uint32_t *) qemu_malloc(s->scratch_size * 4);
-
- vmsvga_reset(s);
-
-#ifdef EMBED_STDVGA
- vga_common_init((VGAState *) s, vga_ram_size);
- vga_init((VGAState *) s);
-#else
- s->vram_size = vga_ram_size;
- s->vram_offset = qemu_ram_alloc(vga_ram_size);
- s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
-#endif
+ s->scratch = qemu_malloc(s->scratch_size * 4);
s->vga.ds = graphic_console_init(vmsvga_update_display,
vmsvga_invalidate_display,
vmsvga_screen_dump,
- vmsvga_text_update, &s->vga);
+ vmsvga_text_update, s);
-#ifdef CONFIG_BOCHS_VBE
- /* XXX: use optimized standard vga accesses */
- cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
- vga_ram_size, s->vga.vram_offset);
-#endif
-}
-static void pci_vmsvga_save(QEMUFile *f, void *opaque)
-{
- struct pci_vmsvga_state_s *s = (struct pci_vmsvga_state_s *) opaque;
- pci_device_save(&s->card, f);
- vmsvga_save(&s->chip, f);
-}
+ s->fifo_size = SVGA_FIFO_SIZE;
+ s->fifo_offset = qemu_ram_alloc(s->fifo_size);
+ s->fifo_ptr = qemu_get_ram_ptr(s->fifo_offset);
-static int pci_vmsvga_load(QEMUFile *f, void *opaque, int version_id)
-{
- struct pci_vmsvga_state_s *s = (struct pci_vmsvga_state_s *) opaque;
- int ret;
+ vga_common_init(&s->vga, vga_ram_size);
+ vga_init(&s->vga);
+ vmstate_register(0, &vmstate_vga_common, &s->vga);
- ret = pci_device_load(&s->card, f);
- if (ret < 0)
- return ret;
+ vga_init_vbe(&s->vga);
- ret = vmsvga_load(&s->chip, f);
- if (ret < 0)
- return ret;
+ rom_add_vga(VGABIOS_FILENAME);
- return 0;
+ vmsvga_reset(s);
}
static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
+ pcibus_t addr, pcibus_t size, int type)
{
struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
struct vmsvga_state_s *s = &d->chip;
}
static void pci_vmsvga_map_mem(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
+ pcibus_t addr, pcibus_t size, int type)
{
struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
struct vmsvga_state_s *s = &d->chip;
s->vram_base = addr;
#ifdef DIRECT_VRAM
- iomemtype = cpu_register_io_memory(0, vmsvga_vram_read,
+ iomemtype = cpu_register_io_memory(vmsvga_vram_read,
vmsvga_vram_write, s);
#else
iomemtype = s->vga.vram_offset | IO_MEM_RAM;
#endif
cpu_register_physical_memory(s->vram_base, s->vga.vram_size,
iomemtype);
+
+ s->vga.map_addr = addr;
+ s->vga.map_end = addr + s->vga.vram_size;
+ vga_dirty_log_restart(&s->vga);
+}
+
+static void pci_vmsvga_map_fifo(PCIDevice *pci_dev, int region_num,
+ pcibus_t addr, pcibus_t size, int type)
+{
+ struct pci_vmsvga_state_s *d = (struct pci_vmsvga_state_s *) pci_dev;
+ struct vmsvga_state_s *s = &d->chip;
+ ram_addr_t iomemtype;
+
+ s->fifo_base = addr;
+ iomemtype = s->fifo_offset | IO_MEM_RAM;
+ cpu_register_physical_memory(s->fifo_base, s->fifo_size,
+ iomemtype);
}
-void pci_vmsvga_init(PCIBus *bus, int vga_ram_size)
+static int pci_vmsvga_initfn(PCIDevice *dev)
{
- struct pci_vmsvga_state_s *s;
+ struct pci_vmsvga_state_s *s =
+ DO_UPCAST(struct pci_vmsvga_state_s, card, dev);
- /* Setup PCI configuration */
- s = (struct pci_vmsvga_state_s *)
- pci_register_device(bus, "QEMUware SVGA",
- sizeof(struct pci_vmsvga_state_s), -1, 0, 0);
pci_config_set_vendor_id(s->card.config, PCI_VENDOR_ID_VMWARE);
pci_config_set_device_id(s->card.config, SVGA_PCI_DEVICE_ID);
- s->card.config[PCI_COMMAND] = 0x07; /* I/O + Memory */
+ s->card.config[PCI_COMMAND] = PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER; /* I/O + Memory */
pci_config_set_class(s->card.config, PCI_CLASS_DISPLAY_VGA);
- s->card.config[0x0c] = 0x08; /* Cache line size */
- s->card.config[0x0d] = 0x40; /* Latency timer */
- s->card.config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
- s->card.config[0x2c] = PCI_VENDOR_ID_VMWARE & 0xff;
- s->card.config[0x2d] = PCI_VENDOR_ID_VMWARE >> 8;
- s->card.config[0x2e] = SVGA_PCI_DEVICE_ID & 0xff;
- s->card.config[0x2f] = SVGA_PCI_DEVICE_ID >> 8;
- s->card.config[0x3c] = 0xff; /* End */
-
- pci_register_io_region(&s->card, 0, 0x10,
- PCI_ADDRESS_SPACE_IO, pci_vmsvga_map_ioport);
- pci_register_io_region(&s->card, 1, vga_ram_size,
- PCI_ADDRESS_SPACE_MEM_PREFETCH, pci_vmsvga_map_mem);
-
- vmsvga_init(&s->chip, vga_ram_size);
-
- register_savevm("vmware_vga", 0, 0, pci_vmsvga_save, pci_vmsvga_load, s);
+ s->card.config[PCI_CACHE_LINE_SIZE] = 0x08; /* Cache line size */
+ s->card.config[PCI_LATENCY_TIMER] = 0x40; /* Latency timer */
+ s->card.config[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL;
+ s->card.config[PCI_SUBSYSTEM_VENDOR_ID] = PCI_VENDOR_ID_VMWARE & 0xff;
+ s->card.config[PCI_SUBSYSTEM_VENDOR_ID + 1] = PCI_VENDOR_ID_VMWARE >> 8;
+ s->card.config[PCI_SUBSYSTEM_ID] = SVGA_PCI_DEVICE_ID & 0xff;
+ s->card.config[PCI_SUBSYSTEM_ID + 1] = SVGA_PCI_DEVICE_ID >> 8;
+ s->card.config[PCI_INTERRUPT_LINE] = 0xff; /* End */
+
+ pci_register_bar(&s->card, 0, 0x10,
+ PCI_BASE_ADDRESS_SPACE_IO, pci_vmsvga_map_ioport);
+ pci_register_bar(&s->card, 1, VGA_RAM_SIZE,
+ PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_mem);
+
+ pci_register_bar(&s->card, 2, SVGA_FIFO_SIZE,
+ PCI_BASE_ADDRESS_MEM_PREFETCH, pci_vmsvga_map_fifo);
+
+ vmsvga_init(&s->chip, VGA_RAM_SIZE);
+
+ return 0;
+}
+
+void pci_vmsvga_init(PCIBus *bus)
+{
+ pci_create_simple(bus, -1, "vmware-svga");
+}
+
+static PCIDeviceInfo vmsvga_info = {
+ .qdev.name = "vmware-svga",
+ .qdev.size = sizeof(struct pci_vmsvga_state_s),
+ .qdev.vmsd = &vmstate_vmware_vga,
+ .init = pci_vmsvga_initfn,
+};
+
+static void vmsvga_register(void)
+{
+ pci_qdev_register(&vmsvga_info);
}
+device_init(vmsvga_register);