* Re: [Qemu-devel] xserver-xorg-video-intel
[not found] ` <200803281106.59074.computers57@hotmail.com>
@ 2008-03-28 17:06 ` C.W. Betts
0 siblings, 0 replies; 4+ messages in thread
From: C.W. Betts @ 2008-03-28 17:06 UTC (permalink / raw)
To: Chris Gregan; +Cc: qemu-devel
[-- Attachment #1.1: Type: text/plain, Size: 711 bytes --]
On Thursday 27 March 2008 01:14:30 pm Chris Gregan wrote:
> C.W. Betts wrote:
> > On Wednesday 26 March 2008 03:01:48 pm Chris Gregan wrote:
> >> Hello,
> >> I am attempting to virtualize a MID image that requires this driver. Is
> >> there a process for getting something like this supported? What
> >> information\actions do you need from me to consider the support?
> >>
> >> Thanks,
> >> Chris
> >
> > I think there was a patch that emulates an Intel integrated X3100
> > chipset, but it isn't complete.
>
> Thank you C.W.
> Can I help out with some testing?
Umm, I'm not the one who made it. It was Vincent Hanquez at tab@snarc.org.
Included is the patch he sent to the mailing list.
[-- Attachment #1.2: qemu-x3100.patch --]
[-- Type: text/x-diff, Size: 88552 bytes --]
diff --git a/Makefile.target b/Makefile.target
index 9c83733..f813daa 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -535,6 +535,7 @@ OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o
OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o
+OBJS+= x3100_debug.o x3100_vga.o x3100_gtt.o x3100_fb.o x3100_mi.o x3100_regs.o x3100.o
CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
endif
ifeq ($(TARGET_BASE_ARCH), ppc)
diff --git a/hw/pc.c b/hw/pc.c
index 2a569c7..03a6d1a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -706,6 +706,7 @@ static void pc_init1(int ram_size, int vga_ram_size,
char buf[1024];
int ret, linux_boot, i;
ram_addr_t ram_addr, vga_ram_addr, bios_offset, vga_bios_offset;
+ ram_addr_t x3100_ram_addr = 0;
int bios_size, isa_bios_size, vga_bios_size;
PCIBus *pci_bus;
int piix3_devfn = -1;
@@ -753,7 +754,13 @@ static void pc_init1(int ram_size, int vga_ram_size,
cpu_register_physical_memory(0, ram_size, ram_addr);
/* allocate VGA RAM */
- vga_ram_addr = qemu_ram_alloc(vga_ram_size);
+
+ if (x3100_enabled) {
+ vga_ram_addr = qemu_ram_alloc(vga_ram_size - X3100_RAM_SIZE);
+ x3100_ram_addr = qemu_ram_alloc(X3100_RAM_SIZE);
+ }
+ else
+ vga_ram_addr = qemu_ram_alloc(vga_ram_size);
/* BIOS load */
if (bios_name == NULL)
@@ -872,6 +879,14 @@ static void pc_init1(int ram_size, int vga_ram_size,
vga_ram_addr, vga_ram_size);
else
fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
+ } else if (x3100_enabled) {
+ if (pci_enabled)
+ pci_x3100_init(pci_bus, ds, phys_ram_base + vga_ram_addr,
+ vga_ram_addr, vga_ram_size,
+ phys_ram_base + x3100_ram_addr, x3100_ram_addr,
+ x3100_debug);
+ else
+ fprintf(stderr, "%s: x3100: no PCI bus\n", __FUNCTION__);
} else {
if (pci_enabled) {
pci_vga_init(pci_bus, ds, phys_ram_base + vga_ram_addr,
diff --git a/hw/pc.h b/hw/pc.h
index 9f83050..d91407f 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -113,6 +113,8 @@ int piix4_init(PCIBus *bus, int devfn);
#define VGA_RAM_SIZE (9 * 1024 * 1024)
#endif
+#define X3100_RAM_SIZE (128 * 1024 * 1024)
+
int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
unsigned long vga_ram_offset, int vga_ram_size);
int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
@@ -123,6 +125,11 @@ int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
int it_shift);
+int pci_x3100_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size,
+ uint8_t *x3100_ram_base, unsigned long x3100_ram_offset,
+ int debug);
+
/* cirrus_vga.c */
void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
unsigned long vga_ram_offset, int vga_ram_size);
diff --git a/hw/pci.h b/hw/pci.h
index e870987..47a4e67 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -17,7 +17,9 @@ typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
#define PCI_ADDRESS_SPACE_MEM 0x00
#define PCI_ADDRESS_SPACE_IO 0x01
+#define PCI_ADDRESS_SPACE_MEM64 0x04
#define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08
+#define PCI_ADDRESS_SPACE_MEM64_PREFETCH 0x0c
typedef struct PCIIORegion {
uint32_t addr; /* current PCI mapping address. -1 means not mapped */
diff --git a/hw/x3100.c b/hw/x3100.c
new file mode 100644
index 0000000...ad73329
--- /dev/null
+++ b/hw/x3100.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2008 Vincent Hanquez
+ *
+ * QEMU Intel X3100 emulation
+ */
+
+#include "x3100.h"
+#include "x3100_regs.h"
+
+typedef struct PCIX3100State {
+ PCIDevice dev;
+ X3100State state;
+} PCIX3100State;
+
+typedef struct PCIX3100DsState {
+ PCIDevice dev;
+ X3100DsState state;
+} PCIX3100DsState;
+
+static inline X3100State *pcidev_to_gmastate(PCIDevice *pci_dev)
+{
+ return &((PCIX3100State *) pci_dev)->state;
+}
+
+static inline X3100DsState *pcidev_to_gmadsstate(PCIDevice *pci_dev)
+{
+ return &((PCIX3100DsState *) pci_dev)->state;
+}
+
+/******************************************************************************/
+static void x3100_mmio2_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ printf("mmio2 %lx %x\n", addr, val);
+}
+
+static uint32_t x3100_mmio2_readl(void *opaque, target_phys_addr_t addr)
+{
+ printf("mmio2 %lx\n", addr);
+ return 0;
+}
+
+static CPUReadMemoryFunc *x3100_mmio2_read[3] = {
+ x3100_mmio2_readl, x3100_mmio2_readl, x3100_mmio2_readl,
+};
+
+static CPUWriteMemoryFunc *x3100_mmio2_write[3] = {
+ x3100_mmio2_writel, x3100_mmio2_writel, x3100_mmio2_writel,
+};
+
+/******************************************************************************/
+static uint32_t x3100_ioport_read(void *opaque, uint32_t addr)
+{
+ X3100State *s = opaque;
+ x3100_dbg(DBG_CLASS_IOPORT, "IOPORT: r(%x)\n", addr);
+ return 0;
+}
+
+static void x3100_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ X3100State *s = opaque;
+ x3100_dbg(DBG_CLASS_IOPORT, "IOPORT: w(%x,%x)\n", addr, val);
+}
+
+/******************************************************************************/
+static void mmio_map(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ X3100State *s = pcidev_to_gmastate(pci_dev);
+
+ x3100_dbg(DBG_CLASS_MAP, "MAP: MMIO (%d,%x,%x,%x)\n", region_num, addr, size, type);
+ if (region_num == 0) {
+ cpu_register_physical_memory(addr, size / 2, s->registered_mmio_index);
+ cpu_register_physical_memory(addr + size / 2, size / 2, s->registered_gtt_index);
+ } else if (region_num == 2) {
+ s->mi_start = addr;
+ cpu_register_physical_memory(addr, size, s->registered_ram_index);
+ }
+}
+
+static void io_map(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ X3100State *s = pcidev_to_gmastate(pci_dev);
+
+ x3100_dbg(DBG_CLASS_MAP, "MAP: IO (%d,%x,%x,%x)\n", region_num, addr, size, type);
+ register_ioport_read(addr, size, 4, x3100_ioport_read, s);
+ register_ioport_write(addr, size, 4, x3100_ioport_write, s);
+}
+
+static void void_map(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ X3100DsState *s = pcidev_to_gmadsstate(pci_dev);
+
+ x3100_dbg(DBG_CLASS_MAP, "MAP: VOID (%d,%x,%x,%x)\n", region_num, addr, size, type);
+ cpu_register_physical_memory(addr, size, s->registered_other_index);
+}
+
+#define PCI_VENDOR_INTEL 0x8086
+#define PCI_DEVICE_INTEL_GMA965HB 0x2A00
+#define PCI_DEVICE_INTEL_X3100 0x2A02
+#define PCI_CLASS_VGA_BASE 0x030000
+
+static PCIX3100State * register_graphic_ctrl(PCIBus *bus, DisplayState *ds,
+ uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset,
+ int vga_ram_size,
+ uint8_t *x3100_ram_base,
+ unsigned long x3100_ram_offset)
+{
+ PCIX3100State *d;
+ uint8_t *pci_conf;
+ X3100State *s;
+ int vga_io_memory;
+
+ d = (PCIX3100State *) pci_register_device(bus, "X3100",
+ sizeof(PCIX3100State),
+ -1, NULL, NULL);
+ pci_conf = d->dev.config;
+
+ pci_conf[0x00] = PCI_VENDOR_INTEL & 0xff;
+ pci_conf[0x01] = PCI_VENDOR_INTEL >> 8;
+ pci_conf[0x02] = PCI_DEVICE_INTEL_X3100 & 0xff;
+ pci_conf[0x03] = PCI_DEVICE_INTEL_X3100 >> 8;
+
+ pci_conf[0x04] = 0x05; /* command = I/O space, Bus Master */
+
+ pci_conf[0x09] = PCI_CLASS_VGA_BASE & 0xff;
+ pci_conf[0x0a] = (PCI_CLASS_VGA_BASE >> 8) & 0xff;
+ pci_conf[0x0b] = PCI_CLASS_VGA_BASE >> 16;
+
+ pci_conf[0x0e] = 0x80; // header_type
+ pci_conf[0x34] = 0x90;
+ pci_conf[0x3d] = 1; /* interrupt pin 1 */
+ pci_conf[0x44] = 0x48; /* capabilities pointer */
+ pci_conf[0x52] = 0x30; /* mirror of GMCH graphics*/
+ pci_conf[0x53] = 0x00;
+ pci_conf[0x62] = 0x02; /* multi size aperture control */
+ pci_conf[0x90] = 0x05; /* MSI capability ID */
+ pci_conf[0x91] = 0xd0;
+ pci_conf[0xa4] = 0x09; /* FLR capability ID */
+ pci_conf[0xa5] = 0x00;
+ pci_conf[0xa6] = 0x06; /* FLR Len Ver */
+ pci_conf[0xa7] = 0x20;
+ pci_conf[0xd0] = 0x01; /* PM Capability ID */
+ pci_conf[0xd1] = 0x00;
+ pci_conf[0xd2] = 0x22; /* PM capability */
+ pci_conf[0xd3] = 0x00;
+
+ s = &d->state;
+
+ s->registered_mmio_index = cpu_register_io_memory(0, x3100_mmio_read,
+ x3100_mmio_write, s);
+ s->registered_gtt_index = cpu_register_io_memory(0, x3100_gtt_read,
+ x3100_gtt_write, s);
+ s->registered_ram_index = cpu_register_io_memory(0, x3100_mi_read,
+ x3100_mi_write, s);
+
+ pci_register_io_region(&d->dev, 0, 1024 * 1024,
+ PCI_ADDRESS_SPACE_MEM64, mmio_map);
+ pci_register_io_region(&d->dev, 2, 128 * 1024 * 1024,
+ PCI_ADDRESS_SPACE_MEM64_PREFETCH, mmio_map);
+ pci_register_io_region(&d->dev, 4, 8, PCI_ADDRESS_SPACE_IO, io_map);
+
+ x3100_regs_init(s);
+
+ vga_common_init((VGAState *) s, ds, vga_ram_base,
+ vga_ram_offset, vga_ram_size);
+
+ graphic_console_init(s->ds, s->update, s->invalidate,
+ s->screen_dump, s->text_update, s);
+
+ /* register all vga ioports */
+ register_ioport_write(0x3c0, 16, 1, x3100_vga_ioport_write, s);
+
+ register_ioport_write(0x3b4, 2, 1, x3100_vga_ioport_write, s);
+ register_ioport_write(0x3d4, 2, 1, x3100_vga_ioport_write, s);
+ register_ioport_write(0x3ba, 1, 1, x3100_vga_ioport_write, s);
+ register_ioport_write(0x3da, 1, 1, x3100_vga_ioport_write, s);
+
+ register_ioport_read(0x3c0, 16, 1, x3100_vga_ioport_read, s);
+
+ register_ioport_read(0x3b4, 2, 1, x3100_vga_ioport_read, s);
+ register_ioport_read(0x3d4, 2, 1, x3100_vga_ioport_read, s);
+ register_ioport_read(0x3ba, 1, 1, x3100_vga_ioport_read, s);
+ register_ioport_read(0x3da, 1, 1, x3100_vga_ioport_read, s);
+
+ /* register to VGA memory */
+ vga_io_memory = cpu_register_io_memory(0, x3100_vga_mem_read,
+ x3100_vga_mem_write, s);
+ cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
+ vga_io_memory);
+
+ s->redraw_timer = qemu_new_timer(rt_clock, x3100_fb_update, s);
+
+ s->redraw_x1 = s->redraw_y1 = 0xfffff;
+ s->redraw_x2 = s->redraw_y2 = 0x0;
+
+ s->gtt_size_kb = 128;
+ s->ram = x3100_ram_base;
+ s->ram_offset = x3100_ram_offset;
+
+ return d;
+}
+
+static PCIX3100DsState * register_display_ctrl(PCIBus *bus, int devfn)
+{
+ PCIX3100DsState *d;
+ uint8_t *pci_conf;
+ X3100DsState *s;
+
+ d = (PCIX3100DsState *) pci_register_device(bus, "X3100Disp",
+ sizeof(PCIX3100DsState),
+ -1, NULL, NULL);
+ pci_conf = d->dev.config;
+ pci_conf[0x00] = PCI_VENDOR_INTEL & 0xff;
+ pci_conf[0x01] = PCI_VENDOR_INTEL >> 8;
+ pci_conf[0x02] = PCI_DEVICE_INTEL_X3100 & 0xff;
+ pci_conf[0x03] = PCI_DEVICE_INTEL_X3100 >> 8;
+ pci_conf[0x04] = 0x05; /* command = I/O space, Bus Master */
+ pci_conf[0x0a] = 0x80; /* Display controller */
+ pci_conf[0x0b] = 0x03;
+ pci_conf[0x0e] = 0x00; /* header_type */
+ pci_conf[0x3d] = 0; /* interrupt pin 0 */
+
+ s = &d->state;
+
+ pci_register_io_region(&d->dev, 0, 1024 * 1024, PCI_ADDRESS_SPACE_MEM64, void_map);
+
+ s->registered_other_index = cpu_register_io_memory(0, x3100_mmio2_read,
+ x3100_mmio2_write, s);
+
+ return d;
+}
+
+static int register_host_bridge(PCIBus *bus)
+{
+ PCIDevice *dev;
+ uint8_t *pci_conf;
+
+ dev = pci_register_device(bus, "GM965HB", sizeof(PCIDevice), -1, NULL, NULL);
+
+ pci_conf = dev->config;
+
+ pci_conf[0x00] = PCI_VENDOR_INTEL & 0xff;
+ pci_conf[0x01] = PCI_VENDOR_INTEL >> 8;
+ pci_conf[0x02] = PCI_DEVICE_INTEL_GMA965HB & 0xff;
+ pci_conf[0x03] = PCI_DEVICE_INTEL_GMA965HB >> 8;
+
+ pci_conf[0x0a] = 0x00; /* HOST Bridge controller */
+ pci_conf[0x0b] = 0x06;
+
+ return 0;
+}
+
+int pci_x3100_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size,
+ uint8_t *x3100_ram_base, unsigned long x3100_ram_offset,
+ int debug)
+{
+ PCIX3100State *d;
+ PCIX3100DsState *d2;
+
+ /* fake host bridge to have access to GTT */
+ register_host_bridge(bus);
+
+ d = register_graphic_ctrl(bus, ds,
+ vga_ram_base, vga_ram_offset, vga_ram_size,
+ x3100_ram_base, x3100_ram_offset);
+ d2 = register_display_ctrl(bus, d->dev.devfn + 2);
+
+ /* output files are hardcoded, but once we don't need flexible debugs
+ * everything can be simplified */
+ if (debug) {
+ FILE *f;
+
+ f = fopen("qemu_intel_x3100.dump", "w");
+ if (!f)
+ f = stderr;
+
+ x3100_dbg_set_output(0, f);
+
+ f = fopen("qemu_intel_x3100.mi.dump", "w");
+ x3100_dbg_set_output(1, f);
+
+ x3100_dbg_set_class(DBG_CLASS_REG, 0, 1);
+ x3100_dbg_set_class(DBG_CLASS_MAP, 0, 1);
+ x3100_dbg_set_class(DBG_CLASS_IOPORT, 0, 1);
+ x3100_dbg_set_class(DBG_CLASS_MI, 1, 1);
+ x3100_dbg_set_class(DBG_CLASS_INST, 0, 1);
+ x3100_dbg_set_class(DBG_CLASS_GTT, 0, 1);
+ }
+
+ return 0;
+}
diff --git a/hw/x3100.h b/hw/x3100.h
new file mode 100644
index 0000000..b57951b
--- /dev/null
+++ b/hw/x3100.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2008 Vincent Hanquez
+ *
+ * QEMU Intel X3100 emulation
+ */
+#ifndef QEMU_X3100_H
+#define QEMU_X3100_H
+
+#include "hw.h"
+#include "pc.h"
+#include "pci.h"
+#include "console.h"
+#include "vga_int.h"
+#include "qemu-timer.h"
+
+#define X3100_EVENT_MOUSE_UPDATE (1 << 1)
+#define X3100_EVENT_RESIZE (1 << 2)
+#define X3100_EVENT_RING (1 << 3)
+
+#define X3100_REFRESH_INTERVAL (1000 / 30)
+
+#define BITS(x,f,t) (((x) >> f) & ((1 << t) - 1))
+
+typedef struct X3100State {
+ VGA_STATE_COMMON
+
+ int registered_mmio_index; /* qemu index of operations for mmio */
+ int registered_gtt_index; /* qemu index of operations for GTT */
+ int registered_ram_index; /* qemu index of operations for ram */
+
+ target_phys_addr_t mi_start;
+
+ int gtt_enable;
+ int gtt_size_kb;
+ unsigned long gtt_base_addr;
+ unsigned long gtt_tbl[128 * 1024];
+
+ unsigned long ram_offset;
+ uint8_t *ram;
+
+ int gpioctl[8];
+ uint32_t ier, iir, imr, isr;
+ struct {
+ uint32_t start;
+ uint32_t end;
+ } fences[16];
+
+ struct {
+ int enable;
+ int autoreport;
+ int tail;
+ int headcount;
+ int head;
+ int start;
+ int length;
+ uint32_t control;
+ } ring;
+
+ struct {
+ int addr_start;
+ int addr_offset;
+ uint8_t enable;
+ uint8_t gamma;
+ uint8_t tiled;
+ uint8_t rotated;
+ uint32_t stride;
+ uint8_t format;
+ uint8_t cpp;
+ uint16_t width;
+ uint16_t height;
+ uint16_t out_width;
+ uint16_t out_height;
+ } dsp[2];
+
+ struct {
+ /* clipping rectangle */
+ struct { int x1, y1, x2, y2, xorigin, yorigin; } cliprect;
+ /* pipelined ptrs */
+ uint32_t vs, gs, clip, sf, wm, color;
+ /* binding tables */
+ struct { uint32_t vs, gs, clip, sf, ps; } bt;
+ int gs_enable, clip_enable;
+ } ff;
+
+ int mouse_show;
+ int mouse_x;
+ int mouse_y;
+
+ int eventpending;
+
+ target_phys_addr_t fb_start;
+ target_phys_addr_t fb_end;
+ uint16_t fb_sz_w;
+ uint16_t fb_sz_h;
+ uint32_t *fb;
+
+ QEMUTimer *redraw_timer;
+ int need_redraw;
+ int redraw_x1, redraw_x2, redraw_y1, redraw_y2;
+
+ uint8_t *mmio_regs;
+} X3100State;
+
+typedef struct X3100DsState {
+ int registered_other_index;
+} X3100DsState;
+
+void x3100_regs_init(X3100State *state);
+void x3100_regs_write(X3100State *state, int addr, uint32_t val);
+uint32_t x3100_regs_read(X3100State *state, int addr);
+
+typedef enum {
+ DBG_CLASS_REG,
+ DBG_CLASS_MI,
+ DBG_CLASS_INST,
+ DBG_CLASS_MAP,
+ DBG_CLASS_GTT,
+ DBG_CLASS_IOPORT,
+} x3100_dbg_class;
+
+/* debug facility */
+void x3100_dbg(x3100_dbg_class cl, const char *fmt, ...);
+void x3100_dbg_set_output(int nb, FILE *output);
+void x3100_dbg_set_class(x3100_dbg_class cl, int output, int enable);
+
+/* vga part */
+uint32_t x3100_vga_ioport_read(void *opaque, uint32_t addr);
+void x3100_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val);
+extern CPUReadMemoryFunc *x3100_vga_mem_read[3];
+extern CPUWriteMemoryFunc *x3100_vga_mem_write[3];
+
+/* memory interface (mi) part */
+extern CPUReadMemoryFunc *x3100_mi_read[3];
+extern CPUWriteMemoryFunc *x3100_mi_write[3];
+
+void x3100_ring_process(X3100State *state);
+
+/* register mmio part */
+extern CPUReadMemoryFunc *x3100_mmio_read[3];
+extern CPUWriteMemoryFunc *x3100_mmio_write[3];
+
+/* gtt/gart part */
+extern CPUReadMemoryFunc *x3100_gtt_read[3];
+extern CPUWriteMemoryFunc *x3100_gtt_write[3];
+
+/* framebuffer stuff */
+void x3100_fb_update(void *opaque);
+void x3100_fb_write(X3100State *state, int size, int addr, uint32_t val);
+uint32_t x3100_fb_read(X3100State *state, int size, int addr);
+void x3100_fb_queue_refresh(X3100State *state, uint32_t x, uint32_t y);
+void x3100_fb_queue_refresh_rect(X3100State *state, uint32_t x1, uint32_t y1,
+ uint32_t x2, uint32_t y2);
+void x3100_fb_xy_set(X3100State *state, int x, int y, uint32_t val);
+
+#endif
diff --git a/hw/x3100_debug.c b/hw/x3100_debug.c
new file mode 100644
index 0000000..59df746
--- /dev/null
+++ b/hw/x3100_debug.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include "x3100.h"
+
+static FILE * dbg_outputs[] =
+{
+ [0] = NULL,
+ [1] = NULL,
+};
+
+struct dbgclass { int enable; int output; };
+
+static struct dbgclass dbg_class_enabled[] =
+{
+ [DBG_CLASS_REG] = { 0, 0 },
+ [DBG_CLASS_MI] = { 0, 0 },
+ [DBG_CLASS_INST] = { 0, 0 },
+ [DBG_CLASS_MAP] = { 0, 0 },
+ [DBG_CLASS_GTT] = { 0, 0 },
+ [DBG_CLASS_IOPORT] = { 0, 0 },
+};
+
+void x3100_dbg(x3100_dbg_class cl, const char *fmt, ...)
+{
+ va_list ap;
+ FILE *out;
+
+ if (!dbg_class_enabled[cl].enable)
+ return;
+ out = dbg_outputs[dbg_class_enabled[cl].output];
+ va_start(ap, fmt);
+ vfprintf(out, fmt, ap);
+ va_end(ap);
+ fflush(out);
+}
+
+void x3100_dbg_set_output(int nb, FILE *output)
+{
+ dbg_outputs[nb] = output;
+}
+
+void x3100_dbg_set_class(x3100_dbg_class cl, int output, int enable)
+{
+ dbg_class_enabled[cl].output = output;
+ dbg_class_enabled[cl].enable = enable;
+}
diff --git a/hw/x3100_fb.c b/hw/x3100_fb.c
new file mode 100644
index 0000000..6a322ef
--- /dev/null
+++ b/hw/x3100_fb.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2008 Vincent Hanquez
+ *
+ * QEMU Intel X3100 emulation
+ */
+
+#include "x3100.h"
+
+void x3100_fb_update(void *opaque)
+{
+ X3100State *state = opaque;
+
+ if (state->need_redraw) {
+ #if 0
+ printf("refreshing with %d<->%d x %d<->%d\n",
+ state->redraw_x1, state->redraw_x2, state->redraw_y1, state->redraw_y2);
+ #endif
+ state->ds->dpy_update(state->ds,
+ state->redraw_x1, state->redraw_y1,
+ (state->redraw_x2 - state->redraw_x1) + 1,
+ (state->redraw_y2 - state->redraw_y1) + 1);
+ state->redraw_x1 = state->redraw_y1 = 0xfffff;
+ state->redraw_x2 = state->redraw_y2 = 0x0;
+ state->need_redraw = 0;
+ }
+}
+
+void x3100_fb_queue_refresh(X3100State *state, uint32_t x, uint32_t y)
+{
+ if (!state->need_redraw) {
+ state->need_redraw = 1;
+ qemu_mod_timer(state->redraw_timer, qemu_get_clock(rt_clock) + X3100_REFRESH_INTERVAL);
+ }
+
+ if (x < state->redraw_x1) state->redraw_x1 = x;
+ if (state->redraw_x2 < x) state->redraw_x2 = x;
+ if (y < state->redraw_y1) state->redraw_y1 = y;
+ if (state->redraw_y2 < y) state->redraw_y2 = y;
+}
+
+void x3100_fb_queue_refresh_rect(X3100State *state, uint32_t x1, uint32_t y1,
+ uint32_t x2, uint32_t y2)
+{
+ /* FIXME: optimize */
+ if (x2 >= state->dsp[0].out_width) x2 = state->dsp[0].out_width - 1;
+ if (y2 >= state->dsp[0].out_height) y2 = state->dsp[0].out_height - 1;
+ x3100_fb_queue_refresh(state, x1, y1);
+ x3100_fb_queue_refresh(state, x2, y2);
+}
+
+void x3100_fb_write(X3100State *state, int size, int addr, uint32_t val)
+{
+ uint32_t offset;
+ uint32_t *ptr;
+ int x, y;
+
+ offset = addr / 4;
+ /* addr is in bytes */
+ x = (state->dsp[0].width > 0) ? offset % state->dsp[0].width : -1;
+ y = (state->dsp[0].width > 0) ? offset / state->dsp[0].width : -1;
+
+ ptr = (uint32_t *) state->ds->data;
+ ptr += (state->ds->linesize / 4 * y);
+ ptr += x;
+ switch (size) {
+ case 4: *ptr = val; break;
+ case 1:
+ *(((uint8_t *) ptr) + (addr % 4)) = val;
+ break;
+ }
+ x3100_fb_queue_refresh(state, x, y);
+}
+
+
+
+uint32_t x3100_fb_read(X3100State *state, int size, int addr)
+{
+ uint32_t offset;
+ uint32_t *ptr;
+ uint32_t r;
+ int x, y;
+
+ offset = addr / 4;
+ /* addr is in bytes */
+ x = (state->dsp[0].width > 0) ? offset % state->dsp[0].width : -1;
+ y = (state->dsp[0].width > 0) ? offset / state->dsp[0].width : -1;
+
+ ptr = (uint32_t *) state->ds->data;
+ ptr += (state->ds->linesize / 4 * y);
+ ptr += x;
+ switch (size) {
+ case 4: r = *ptr; break;
+ case 2: r = *(((uint16_t *) ptr) + (addr % 2)); break;
+ case 1: r = *(((uint8_t *) ptr) + (addr % 4)); break;
+ }
+ return r;
+}
+
+void x3100_fb_xy_set(X3100State *state, int x, int y, uint32_t val)
+{
+ uint32_t *ptr;
+ ptr = (uint32_t *) state->ds->data;
+ ptr += (state->ds->linesize / 4 * y);
+ ptr += x;
+ *ptr = val;
+}
diff --git a/hw/x3100_gtt.c b/hw/x3100_gtt.c
new file mode 100644
index 0000000..9bb100a
--- /dev/null
+++ b/hw/x3100_gtt.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2008 Vincent Hanquez
+ *
+ * QEMU Intel X3100 emulation
+ */
+
+#include "x3100.h"
+
+static uint32_t x3100_gtt_readb(void *opaque, target_phys_addr_t addr)
+{
+ x3100_dbg(DBG_CLASS_GTT, "GTT: r(1,%lx)\n", addr);
+ return -1;
+}
+
+static uint32_t x3100_gtt_readw(void *opaque, target_phys_addr_t addr)
+{
+ x3100_dbg(DBG_CLASS_GTT, "GTT: r(2,%lx)\n", addr);
+ return -1;
+}
+
+static uint32_t x3100_gtt_readl(void *opaque, target_phys_addr_t addr)
+{
+ X3100State *s = opaque;
+ int a;
+ uint32_t ret;
+
+ a = ((addr & (1024 * 1024 - 1)) - 512 * 1024) / 4;
+ ret = (a >= 0 && a <= 128 * 1024) ? s->gtt_tbl[a] : 0;
+ x3100_dbg(DBG_CLASS_GTT, "GTT: r(4,%lx) = %x (A=%x, M=%x, V=%d)\n",
+ addr, ret, ret & 0xfffff000, (ret >> 1) & 0x3, ret & 0x1);
+
+ return ret;
+}
+
+static void x3100_gtt_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ x3100_dbg(DBG_CLASS_GTT, "GTT: w(1,%lx,%x)\n", addr, val);
+}
+
+static void x3100_gtt_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ x3100_dbg(DBG_CLASS_GTT, "GTT: w(2,%lx,%x)\n", addr, val);
+}
+
+static void x3100_gtt_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ X3100State *s = opaque;
+ int a;
+
+ a = ((addr & (1024 * 1024 - 1)) - 512 * 1024) / 4;
+ if (a >= 0 && a <= 128 * 1024)
+ s->gtt_tbl[a] = val;
+ x3100_dbg(DBG_CLASS_GTT, "GTT: w(4,%lx,%x) (A=%x, M=%x, V=%d)\n",
+ addr, val, val & 0xfffff000, (val >> 1) & 0x3, val & 0x1);
+}
+
+CPUReadMemoryFunc *x3100_gtt_read[3] = {
+ x3100_gtt_readb, x3100_gtt_readw, x3100_gtt_readl,
+};
+
+CPUWriteMemoryFunc *x3100_gtt_write[3] = {
+ x3100_gtt_writeb, x3100_gtt_writew, x3100_gtt_writel,
+};
diff --git a/hw/x3100_mi.c b/hw/x3100_mi.c
new file mode 100644
index 0000000..b356cbc
--- /dev/null
+++ b/hw/x3100_mi.c
@@ -0,0 +1,766 @@
+/*
+ * Copyright (c) 2008 Vincent Hanquez
+ *
+ * QEMU Intel X3100 emulation
+ */
+
+#include "x3100.h"
+#include "x3100_mi.h"
+
+struct handler_fct {
+ int (*f)(X3100State *state, uint32_t *ptr);
+ int dword;
+ int ignore;
+};
+
+
+static inline int get_bpp_from_colordepth(int colordepth)
+{
+ switch (colordepth) {
+ case 0: return 1; /* 8 bits */
+ case 1: return 2; /* 16 bits (565) */
+ case 2: return 2; /* 16 bits (1555) */
+ case 3: default: return 4; /* 32 bits */
+ }
+}
+
+static int cmd_mi_set_context(X3100State *state, uint32_t *ringdata)
+{
+ int addr;
+
+ addr = ringdata[1] >> 11;
+
+ x3100_dbg(DBG_CLASS_MI, "MI: set_context(addr=%x)\n", addr);
+ return 0;
+}
+
+static int cmd_mi_display_flip(X3100State *state, uint32_t *ringdata)
+{
+ return ((ringdata[0] >> 22) & 0x1) ? 3 : 4;
+}
+
+static int cmd_2d_xy_mono_src_copy_blt(X3100State *state, uint32_t *ringdata)
+{
+ int dst_x1, dst_y1, dst_x2, dst_y2, dst_pitch;
+ uint32_t src_fg_color, src_bg_color;
+ uint32_t dst, src;
+ int rop, dst_tiled, bpp, is_display, transparency;
+ int x, y;
+ uint8_t *dst_ptr, *src_ptr;
+
+ rop = (ringdata[1] >> 16) & 0xff;
+ dst_pitch = ringdata[1] & 0xffff;
+ dst_y1 = ringdata[2] >> 16;
+ dst_x1 = ringdata[2] & 0xffff;
+ dst_y2 = ringdata[3] >> 16;
+ dst_x2 = ringdata[3] & 0xffff;
+ dst_tiled = ringdata[0] >> 11 & 0x1;
+ dst = ringdata[4];
+ src = ringdata[5];
+ src_bg_color = ringdata[6];
+ src_fg_color = ringdata[7];
+ transparency = ringdata[1] >> 29 & 0x1;
+
+ bpp = get_bpp_from_colordepth(ringdata[1] >> 24 & 0x3);
+
+ x3100_dbg(DBG_CLASS_MI, "MI: 2d xy_mono_src_copy_blt(rop=%x, trans=%d, dst=%x (%d,%d) (%d,%d) (%d), src=%x (bg=%x) (fg=%x))\n",
+ rop, transparency, dst, dst_x1, dst_y1, dst_x2, dst_y2, dst_pitch,
+ src, src_bg_color, src_fg_color);
+
+ dst_ptr = state->ram + dst;
+ src_ptr = state->ram + src;
+ is_display = (dst == state->dsp[0].addr_start);
+
+ for (y = dst_y1; y < dst_y2; y++)
+ for (x = dst_x1; x < dst_x2; x++) {
+ uint32_t *dpa;
+ uint8_t *spa;
+ uint32_t val;
+
+ dpa = (uint32_t *) (dst_ptr + (y * dst_pitch) + (x * bpp));
+ spa = (uint8_t *) (src_ptr + (y * dst_pitch) + (x / 8));
+ val = !!(*spa & (1 << (7 - (x % 8))))
+ ? src_fg_color
+ : (transparency ? *dpa : src_bg_color);
+ switch (rop) {
+ case 0x88: /*D&S*/ val &= *dpa; break;
+ case 0xcc: /*S*/ break;
+ default: val = *dpa; break;
+ }
+ *dpa = val;
+
+ if (dst >= state->dsp[0].addr_start &&
+ dst < (state->fb_end - state->mi_start)) {
+ int offset = dst - state->dsp[0].addr_start;
+ int xscreen, yscreen;
+ yscreen = ((offset / dst_pitch)) + y;
+ xscreen = ((offset % dst_pitch) / bpp) + x;
+ x3100_fb_xy_set(state, xscreen, yscreen, val);
+ x3100_fb_queue_refresh(state, xscreen, yscreen);
+ }
+ }
+ return 0;
+}
+
+static int cmd_2d_xy_mono_pat_blt(X3100State *state, uint32_t *ringdata)
+{
+ int dst_x1, dst_y1, dst_x2, dst_y2;
+ int rop, dst_pitch;
+ uint32_t dst, pat_bg_color, pat_fg_color, pat_d0, pat_d1;
+ int pat_h_seed, pat_v_seed;
+
+ pat_h_seed = (ringdata[0] >> 12) & 0x3;
+ pat_v_seed = (ringdata[0] >> 8) & 0x3;
+ rop = (ringdata[1] >> 16) & 0xff;
+ dst_pitch = ringdata[1] & 0xffff;
+ dst_y1 = ringdata[2] >> 16;
+ dst_x1 = ringdata[2] & 0xffff;
+ dst_y2 = ringdata[3] >> 16;
+ dst_x2 = ringdata[3] & 0xffff;
+ dst = ringdata[4];
+ pat_bg_color = ringdata[5];
+ pat_fg_color = ringdata[6];
+ pat_d0 = ringdata[7];
+ pat_d1 = ringdata[8];
+
+ x3100_dbg(DBG_CLASS_MI, "MI: 2d xy_mono_pat_blt(rop=%x, dst=%x (%d,%d) (%d,%d) (%d), pat (bg=%x) (fg=%x) (d0=%x) (d1=%x) (vseed=%x) (hseed=%x))\n",
+ rop, dst, dst_x1, dst_y1, dst_x2, dst_y2, dst_pitch,
+ pat_bg_color, pat_fg_color, pat_d0, pat_d1, pat_v_seed, pat_h_seed);
+ return 0;
+}
+
+static int cmd_2d_src_copy_blt(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: 2d src_copy_blt(dest_height=%d, dest_width=%d, dest=%x, src=%x)\n",
+ ringdata[2] >> 16,
+ (ringdata[2]) & 0xffff,
+ ringdata[3],
+ ringdata[5]);
+ return 0;
+}
+
+/*
+ * use by the linux driver in EXA mode
+ */
+static int cmd_2d_xy_src_copy_blt(X3100State *state, uint32_t *ringdata)
+{
+ int dst_x1, dst_y1, dst_x2, dst_y2, src_x1, src_y1;
+ int dst_pitch, src_pitch, dst_tiled, src_tiled;
+ uint32_t dst, src;
+ uint8_t *dst_ptr, *src_ptr;
+ int rop;
+ int is_display;
+ int bpp;
+ int y, x;
+ int dy, dx;
+
+ dst_tiled = (ringdata[0] >> 11) & 0x1;
+ rop = (ringdata[1] >> 16) & 0xff;
+ dst_pitch = ringdata[1] & 0xffff;
+ dst_y1 = ringdata[2] >> 16;
+ dst_x1 = ringdata[2] & 0xffff;
+ dst_y2 = ringdata[3] >> 16;
+ dst_x2 = ringdata[3] & 0xffff;
+ dst = ringdata[4];
+ src_y1 = ringdata[5] >> 16;
+ src_x1 = ringdata[5] & 0xffff;
+ src_pitch = ringdata[6] & 0xffff;
+ src_tiled = (ringdata[0] >> 15) & 0x1;
+ src = ringdata[7];
+
+ if (src_tiled)
+ src_pitch <<= 2;
+ if (dst_tiled)
+ dst_pitch <<= 2;
+
+ bpp = get_bpp_from_colordepth(ringdata[1] >> 24 & 0x3);
+
+ is_display = (dst == state->dsp[0].addr_start);
+
+ x3100_dbg(DBG_CLASS_MI, "MI: 2d xy_src_copy_blt(bpp=%x, rop=%x, clip=%d, dst=%x (%d,%d) (%d,%d) (%d) (t=%d), src=%x (%d, %d) (%d) (t=%d))\n",
+ bpp, rop, (ringdata[1] >> 30) & 0x1,
+ dst, dst_x1, dst_y1, dst_x2, dst_y2, dst_pitch, dst_tiled,
+ src, src_x1, src_y1, src_pitch, src_tiled);
+
+ dst_ptr = state->ram + dst;
+ src_ptr = state->ram + src;
+
+ /* check if we overlap, but else normal left->right,top->bottom copy */
+ dy = dx = 1;
+ if (dst == src) {
+ dy = (dst_y1 <= src_y1) ? 1 : -1;
+ dx = (dst_x1 <= src_x1) ? 1 : -1;
+ }
+
+ for (y = (dy == 1) ? dst_y1 : dst_y2 - 1;
+ (dy == 1) ? y < dst_y2 : y >= dst_y1;
+ y += dy) {
+ for (x = (dx == 1) ? dst_x1 : dst_x2 - 1;
+ (dx == 1) ? x < dst_x2 : x >= dst_x1;
+ x += dx) {
+ uint32_t *dpa, *spa;
+
+ /* FIXME: tile is not implemented */
+ if (dst_tiled)
+ dpa = (uint32_t *) (dst_ptr + (y * dst_pitch) + (x * bpp));
+ else
+ dpa = (uint32_t *) (dst_ptr + (y * dst_pitch) + (x * bpp));
+ /* FIXME: tile is not implemented */
+ if (src_tiled) {
+ spa = (uint32_t *) (src_ptr +
+ ((src_y1 + (y - dst_y1)) * src_pitch) +
+ ((src_x1 + (x - dst_x1)) * bpp));
+ } else {
+ spa = (uint32_t *) (src_ptr +
+ ((src_y1 + (y - dst_y1)) * src_pitch) +
+ ((src_x1 + (x - dst_x1)) * bpp));
+ }
+ switch (rop) {
+ case 0xcc: /*S*/ *dpa = *spa; break;
+ case 0xee: /*D|S*/ *dpa |= *spa; break;
+ default: break;
+ }
+ if (is_display &&
+ x < state->dsp[0].out_width && y < state->dsp[0].out_height)
+ x3100_fb_xy_set(state, x, y, *spa);
+ }
+ }
+ if (is_display) {
+ x3100_fb_queue_refresh_rect(state, dst_x1, dst_y1, dst_x2, dst_y2);
+ }
+ return 0;
+}
+
+static int cmd_2d_color_blt(X3100State *state, uint32_t *ringdata)
+{
+ int dst_w, dst_h, dst_pitch, rop, bpp;
+ uint32_t dst;
+ uint32_t color;
+ int y, x;
+ uint8_t *dst_ptr;
+ int is_display;
+
+ rop = (ringdata[1] >> 16) & 0xff;
+ dst_pitch = ringdata[1] & 0xffff;
+ dst_h = ringdata[2] >> 16;
+ dst_w = ringdata[2] & 0xffff;
+ dst = ringdata[3];
+ color = ringdata[4];
+
+ bpp = get_bpp_from_colordepth(ringdata[1] >> 24 & 0x3);
+
+ is_display = (dst >= state->dsp[0].addr_start && dst < (state->fb_end - state->mi_start));
+
+ x3100_dbg(DBG_CLASS_MI,
+ "MI: 2d color_blt(rop=%x, dst=%x (%d,%d) (%d), color=%x)\n",
+ rop, dst, dst_w, dst_h, dst_pitch, color);
+
+ dst_ptr = (uint8_t *) (state->ram + dst);
+ for (y = 0; y < dst_h; y++)
+ for (x = 0; x < (dst_w / bpp); x++) {
+ uint32_t *dpa;
+ uint32_t val;
+
+ dpa = (uint32_t *) (dst_ptr + (y * dst_pitch) + (x * bpp));
+ switch (rop) {
+ case 0xf0: /*P*/ val = color; break;
+ case 0x5a: /*D^P*/ val = *dpa ^ color; break;
+ default: val = *dpa; break;
+ }
+ *dpa = val;
+ if (dst >= state->dsp[0].addr_start &&
+ dst < (state->fb_end - state->mi_start)) {
+ int offset = dst - state->dsp[0].addr_start;
+ int xscreen, yscreen;
+ yscreen = ((offset / dst_pitch)) + y;
+ xscreen = ((offset % dst_pitch) / bpp) + x;
+ x3100_fb_xy_set(state, xscreen, yscreen, val);
+ x3100_fb_queue_refresh(state, xscreen, yscreen);
+ }
+ }
+ return 0;
+}
+
+/*
+ * use by the linux driver in EXA mode
+ */
+static int cmd_2d_xy_color_blt(X3100State *state, uint32_t *ringdata)
+{
+ int dst_x1, dst_y1, dst_x2, dst_y2;
+ int dst_pitch, rop, bpp;
+ uint32_t color;
+ uint32_t dst;
+ uint8_t *dst_ptr;
+ int is_display;
+ int y, x;
+
+ rop = (ringdata[1] >> 16) & 0xff;
+ dst_y1 = ringdata[2] >> 16;
+ dst_x1 = ringdata[2] & 0xffff;
+ dst_y2 = ringdata[3] >> 16;
+ dst_x2 = ringdata[3] & 0xffff;
+ dst_pitch = ringdata[1] & 0xffff;
+ dst = ringdata[4];
+ color = ringdata[5];
+
+ bpp = get_bpp_from_colordepth(ringdata[1] >> 24 & 0x3);
+
+ is_display = (dst == state->dsp[0].addr_start);
+
+ x3100_dbg(DBG_CLASS_MI,
+ "MI: 2d xy_color_blt(rop=%x, dst=%x (%d,%d) (%d,%d) (%d) (t=%d), color=%x)\n",
+ rop, dst, dst_x1, dst_y1, dst_x2, dst_y2, dst_pitch, (ringdata[0] >> 11) & 0x1, color);
+ dst_ptr = state->ram + dst;
+
+ for (y = dst_y1; y < dst_y2; y++)
+ for (x = dst_x1; x < dst_x2; x++) {
+ uint32_t *dpa;
+ uint32_t val;
+
+ dpa = (uint32_t *) (dst_ptr + (y * dst_pitch) + (x * bpp));
+ switch (rop) {
+ case 0xf0: /* P */ val = color; break;
+ case 0x5a: /* D ^ P */ val = *dpa ^ color; break;
+ default: val = *dpa; break;
+ }
+ *dpa = val;
+
+ if (is_display)
+ x3100_fb_xy_set(state, x, y, val);
+ }
+ if (is_display)
+ x3100_fb_queue_refresh_rect(state, dst_x1, dst_y1, dst_x2, dst_y2);
+ return 0;
+}
+
+static int cmd_2d_xy_pat_blt_immediate(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI,
+ "MI: 2d xy_pat_blt_immediate:\n");
+ return 0;
+}
+
+static int cmd_gfx_urb_fence(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: gfx urb fence: CLIP=(%x,%d) GS=(%x,%d) VS=(%x,%d) CS=(%x,%d) VFE=(%x,%d) SF=(%x,%d)\n",
+ ringdata[1] >> 20 & 0x3ff, ringdata[0] >> 10 & 0x1,
+ ringdata[1] >> 10 & 0x3ff, ringdata[0] >> 9 & 0x1,
+ ringdata[1] & 0x3ff, ringdata[0] >> 8 & 0x1,
+ ringdata[2] >> 20 & 0x3ff, ringdata[0] >> 13 & 0x1,
+ ringdata[2] >> 10 & 0x3ff, ringdata[0] >> 12 & 0x1,
+ ringdata[2] & 0x3ff, ringdata[0] >> 11 & 0x1);
+ return 0;
+}
+
+static int cmd_gfx_urb_state(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: gfx urb state: size=%d entries=%d\n",
+ ringdata[1] >> 4 & 0xf, ringdata[1] & 0x7);
+ return (ringdata[0] & 0xff) + 2;
+}
+
+static int cmd_gfx_constant_buffer(X3100State *state, uint32_t *ringdata)
+{
+ return (ringdata[0] & 0xff) + 2;
+}
+
+static int cmd_gfx_state_prefetch(X3100State *state, uint32_t *ringdata)
+{
+ return (ringdata[0] & 0xff) + 2;
+}
+
+static int cmd_gfx_state_base_addr(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: 2d gfx state base: (gen %x %d) (surface %x %d) "
+ "(indirect %x %d) (genupper %x %d) (indirect upper %x %d)\n",
+ ringdata[1] & ~0xfff, ringdata[1] & 0x1,
+ ringdata[2] & ~0xfff, ringdata[2] & 0x1,
+ ringdata[3] & ~0xfff, ringdata[3] & 0x1,
+ ringdata[4] & ~0xfff, ringdata[4] & 0x1,
+ ringdata[5] & ~0xfff, ringdata[5] & 0x1);
+ return 0;
+}
+
+static int cmd_gfx_state_sip(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: 2d gfx state SIP: %x\n",
+ ringdata[1] >> 4);
+ return 0;
+}
+
+static int cmd_gfx_pipeline_select(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: 2d gfx pipeline select: %s\n",
+ (ringdata[0] & 0x1) ? "media" : "3D");
+ return 0;
+}
+
+static int cmd_3d_drawing_rectangle(X3100State *state, uint32_t *ringdata)
+{
+ state->ff.cliprect.y1 = ringdata[1] >> 16;
+ state->ff.cliprect.x1 = ringdata[1] & 0xffff;
+ state->ff.cliprect.y2 = ringdata[2] >> 16;
+ state->ff.cliprect.x2 = ringdata[2] & 0xffff;
+ state->ff.cliprect.yorigin = ringdata[3] >> 16;
+ state->ff.cliprect.xorigin = ringdata[3] & 0xffff;
+
+ x3100_dbg(DBG_CLASS_MI, "MI: 3d drawing rectangle: "
+ "min=(%d,%d) max=(%d,%d) origin=(%d,%d)\n",
+ state->ff.cliprect.x1, state->ff.cliprect.y1,
+ state->ff.cliprect.x2, state->ff.cliprect.y2,
+ state->ff.cliprect.xorigin, state->ff.cliprect.yorigin);
+ return 0;
+}
+
+static int cmd_3d_pipelined_ptrs(X3100State *state, uint32_t *ringdata)
+{
+ int got_diff = 0;
+
+ /* a bit ugly, but useful to not repeat useless debugging message. */
+ #define SET_DIFF(var, newval) \
+ if ((var) != (newval)) { (var) = (newval); got_diff = 1; }
+ SET_DIFF(state->ff.vs, ringdata[1] & ~0x1f);
+ SET_DIFF(state->ff.gs, ringdata[2] & ~0x1f);
+ SET_DIFF(state->ff.gs_enable, ringdata[2] & 0x1);
+ SET_DIFF(state->ff.clip, ringdata[3] & ~0x1f);
+ SET_DIFF(state->ff.clip_enable, ringdata[3] & 0x1);
+ SET_DIFF(state->ff.sf, ringdata[4] & ~0x1f);
+ SET_DIFF(state->ff.wm, ringdata[5] & ~0x1f);
+ SET_DIFF(state->ff.color, ringdata[6] & ~0x3f);
+ #undef SET_DIFF
+
+ if (got_diff)
+ x3100_dbg(DBG_CLASS_MI, "MI: 3d pipelined ptrs: vs=%x gs=%x,%d "
+ "clip=%x,%d sf=%x wm=%x color=%x\n",
+ state->ff.vs, state->ff.gs, state->ff.gs_enable,
+ state->ff.clip, state->ff.clip_enable,
+ state->ff.sf, state->ff.wm, state->ff.color);
+ return 0;
+}
+
+static int cmd_3d_binding_table_ptrs(X3100State *state, uint32_t *ringdata)
+{
+ int got_diff = 0;
+ /* a bit ugly, but useful to not repeat useless debugging message. */
+ #define SET_DIFF(var, newval) \
+ if ((var) != (newval)) { (var) = (newval); got_diff = 1; }
+ SET_DIFF(state->ff.bt.vs, ringdata[1] & ~0x1f);
+ SET_DIFF(state->ff.bt.gs, ringdata[2] & ~0x1f);
+ SET_DIFF(state->ff.bt.clip, ringdata[3] & ~0x1f);
+ SET_DIFF(state->ff.bt.sf, ringdata[4] & ~0x1f);
+ SET_DIFF(state->ff.bt.ps, ringdata[5] & ~0x1f);
+ #undef SET_DIFF
+
+ if (got_diff)
+ x3100_dbg(DBG_CLASS_MI, "MI: 3d binding table ptrs: "
+ "vs=%x gs=%x clip=%x sf=%x ps=%x\n",
+ state->ff.bt.vs, state->ff.bt.gs, state->ff.bt.clip,
+ state->ff.bt.sf, state->ff.bt.ps);
+ return 0;
+}
+
+static int cmd_3d_vertex_buffers(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: 3d vertex buffers: len=%d\n", (ringdata[1] & 0xff) + 2);
+ return (ringdata[1] & 0xff) + 2; /* 4n-1 */
+}
+
+static int cmd_3d_vertex_elements(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: 3d vertex elements: \n");
+ return (ringdata[1] & 0xff) + 2; /* 4n-1 */
+}
+
+static int cmd_3d_index_buffer(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: 3d index buffer: \n");
+ return 0;
+}
+
+static int cmd_3d_vf_statistics(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: 3d vf statistics: \n");
+ return 0;
+}
+
+static int cmd_3d_pipe_control(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: 3d pipe control: dest=(%x,%d) imm=(%x %x)\n",
+ ringdata[1] & ~0xf, (ringdata[1] >> 2) & 0x1,
+ ringdata[2], ringdata[3]);
+ return 0;
+}
+
+static int cmd_3d_primitive(X3100State *state, uint32_t *ringdata)
+{
+ x3100_dbg(DBG_CLASS_MI, "MI: 3d primitive: access=%s, prim_type=%x, vertex#=%d, start=%x, base=%x\n",
+ (ringdata[0] >> 16 & 0x1) ? "random" : "sequential",
+ ringdata[0] >> 10 & 0xf, ringdata[1], ringdata[2], ringdata[5]
+ );
+ return 0;
+}
+
+/********************************************************************************/
+/********************************************************************************/
+/********************************************************************************/
+static struct handler_fct cmds_mi[] =
+{
+ [CMD_MI_NOP] = { NULL, 1, 1 },
+ [CMD_MI_USER_INT] = { NULL, 1, 1 },
+ [CMD_MI_WAIT_FOR_EVENT] = { NULL, 1, 1 },
+ [CMD_MI_FLUSH] = { NULL, 1, 1 },
+ [CMD_MI_ARB_CHECK] = { NULL, 1, 1 },
+ [CMD_MI_REPORT_HEAD] = { NULL, 1, 1 },
+ [CMD_MI_BATCH_END] = { NULL, 1, 1 },
+ [CMD_MI_OVERLAY_FLIP] = { NULL, 2, 1 },
+ [CMD_MI_LOAD_SL_INCL] = { NULL, 2, 1 },
+ [CMD_MI_LOAD_SL_EXCL] = { NULL, 2, 1 },
+ [CMD_MI_DISP_FLIP] = { cmd_mi_display_flip, 0, 0 },
+ [CMD_MI_SET_CONTEXT] = { cmd_mi_set_context, 2, 0 },
+ [CMD_MI_STORE_DATA_IMM] = { NULL, 5, 1 },
+ [CMD_MI_STORE_DATA_INDEX] = { NULL, 4, 1 },
+ [CMD_MI_LOAD_REG] = { NULL, 3, 1 },
+ [CMD_MI_STORE_REG_MEM] = { NULL, 3, 1 },
+ [CMD_MI_BATCH_START] = { NULL, 2, 0 },
+};
+
+static struct handler_fct cmds_2d[] =
+{
+ [CMD_2D_COLOR_BLT] = { cmd_2d_color_blt, 5, 0 },
+ [CMD_2D_SRC_COPY_BLT] = { cmd_2d_src_copy_blt, 6, 0 },
+ [CMD_2D_XY_SETUP_BLT] = { NULL, 8, 0 },
+ [CMD_2D_XY_SETUP_MONO_PATTERN_SL_BLT] = { NULL, 9, 0 },
+ [CMD_2D_XY_SETUP_CLIP_BLT] = { NULL, 3, 0 },
+ [CMD_2D_XY_PIXEL_BLT] = { NULL, 2, 0 },
+ [CMD_2D_XY_SCANLINES_BLT] = { NULL, 3, 0 },
+ [CMD_2D_XY_TEXT_BLT] = { NULL, 4, 0 },
+ [CMD_2D_XY_TEXT_IMMEDIATE_BLT] = { NULL, 6, 0 },
+ [CMD_2D_XY_COLOR_BLT] = { cmd_2d_xy_color_blt, 6, 0 },
+ [CMD_2D_XY_PAT_BLT] = { NULL, 6, 0 },
+ [CMD_2D_XY_PAT_CHROMA_BLT] = { NULL, 8, 0 },
+ [CMD_2D_XY_PAT_BLT_IMMEDIATE] = { cmd_2d_xy_pat_blt_immediate, 8, 0 },
+ [CMD_2D_XY_PAT_CHROMA_BLT_IMMEDIATE] = { NULL, 10, 0 },
+ [CMD_2D_XY_MONO_PAT_BLT] = { cmd_2d_xy_mono_pat_blt, 9, 0 },
+ [CMD_2D_XY_MONO_PAT_FIXED_BLT] = { NULL, 7, 0 },
+ [CMD_2D_XY_SRC_COPY_BLT] = { cmd_2d_xy_src_copy_blt, 8, 0 },
+ [CMD_2D_XY_SRC_COPY_CHROMA_BLT] = { NULL, 10, 0 },
+ [CMD_2D_XY_MONO_SRC_COPY_BLT] = { cmd_2d_xy_mono_src_copy_blt, 8, 0 },
+ [CMD_2D_XY_MONO_SRC_COPY_IMMEDIATE_BLT] = { NULL, 10, 0 },
+ [CMD_2D_XY_FULL_BLT] = { NULL, 9, 0 },
+ [CMD_2D_XY_FULL_IMMEDIATE_PATTERN_BLT] = { NULL, 11, 0 },
+ [CMD_2D_XY_FULL_MONO_SRC_BLT] = { NULL, 9, 0 },
+ [CMD_2D_XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT] = { NULL, 10, 0 },
+ [CMD_2D_XY_FULL_MONO_PATTERN_BLT] = { NULL, 12, 0 },
+ [CMD_2D_XY_FULL_MONO_PATTERN_MONO_SRC_BLT] = { NULL, 12, 0 },
+};
+
+static struct handler_fct cmds_gfxpipe_common_pipelined[] =
+{
+ [CMD_GFX_URB_FENCE] = { cmd_gfx_urb_fence, 3, 0 },
+ [CMD_GFX_URB_STATE] = { cmd_gfx_urb_state, 0, 0 },
+ [CMD_GFX_CONSTANT_BUFFER] = { cmd_gfx_constant_buffer, 0, 0 },
+ [CMD_GFX_STATE_PREFETCH] = { cmd_gfx_state_prefetch, 0, 0 },
+};
+
+static struct handler_fct cmds_gfxpipe_common_npipelined[] =
+{
+ [CMD_GFX_STATE_BASE_ADDR] = { cmd_gfx_state_base_addr, 6, 0 },
+ [CMD_GFX_STATE_SIP] = { cmd_gfx_state_sip, 2, 0 },
+ [CMD_GFX_PIPELINE_SELECT] = { cmd_gfx_pipeline_select, 1, 0 },
+};
+
+static struct handler_fct cmds_gfxpipe_3d_pipelined[] =
+{
+ [CMD_3D_PIPELINED_PTRS] = { cmd_3d_pipelined_ptrs, 7, 0 },
+ [CMD_3D_BINDING_TABLE_PTRS] = { cmd_3d_binding_table_ptrs, 6, 0 },
+ [CMD_3D_VERTEX_BUFFERS] = { cmd_3d_vertex_buffers, 0, 0 },
+ [CMD_3D_VERTEX_ELEMENTS] = { cmd_3d_vertex_elements, 0, 0 },
+ [CMD_3D_INDEX_BUFFER] = { cmd_3d_index_buffer, 4, 0 },
+ [CMD_3D_VF_STATISTICS] = { cmd_3d_vf_statistics, 0, 0 },
+};
+
+static struct handler_fct cmds_gfxpipe_3d_npipelined[] =
+{
+ [CMD_3D_DRAWING_RECTANGLE] = { cmd_3d_drawing_rectangle, 4, 0 },
+};
+
+static struct handler_fct cmds_gfxpipe_3d_pipe_ctrl[] =
+{
+ [0] = { cmd_3d_pipe_control, 4, 0 },
+};
+
+static struct handler_fct cmds_gfxpipe_3d_primitive[] =
+{
+ [0] = { cmd_3d_primitive, 6, 0 },
+};
+
+static int call_on_table(X3100State *state, struct handler_fct *table, char *ty,
+ int array_sz, int index, uint32_t *ringdata)
+{
+ struct handler_fct *h;
+ if (index < 0 || index >= array_sz) {
+ x3100_dbg(DBG_CLASS_MI, "MI: %s : index not handled %d\n",
+ ty, index);
+ return 0;
+ }
+
+ h = &table[index];
+ if (h->ignore)
+ return h->dword;
+ if (!h->f) {
+ x3100_dbg(DBG_CLASS_MI, "MI: %s cmd not handled (header %x)\n",
+ ty, ringdata[0]);
+ return 0;
+ }
+
+ if (h->dword > 0) {
+ h->f(state, ringdata);
+ return h->dword;
+ } else
+ return h->f(state, ringdata);
+}
+
+void x3100_ring_process(X3100State *state)
+{
+ int tmp;
+ uint32_t *ringdata;
+
+ if (!state->ring.enable)
+ return;
+ //printf("ring: head %x => tail %x\n", state->ring.head, state->ring.tail);
+#define DOHANDLER(index, tbl, ty) \
+ dword = call_on_table(state, tbl, ty, ARRAY_SIZE(tbl), index, \
+ ringdata + (tmp / 4))
+
+ ringdata = (uint32_t *) (state->ram + state->ring.start);
+
+ tmp = state->ring.head;
+ while (tmp < state->ring.tail) {
+ uint32_t header = ringdata[tmp / 4];
+ int dword = 0;
+
+ switch (HDR_TYPE(header)) {
+ case CMD_TYPE_MI:
+ DOHANDLER(HDR_MI_OP(header), cmds_mi, "mi");
+ break;
+ case CMD_TYPE_2D:
+ DOHANDLER(HDR_2D_OP(header), cmds_2d, "2D");
+ break;
+ case CMD_TYPE_GFXPIPE:
+ switch (HDR_GFXPIPE_PIPELINE(header)) {
+ case GFXPIPE_COMMON:
+ switch (HDR_GFXPIPE_OP(header)) {
+ case COMMON_OP_PIPELINED:
+ DOHANDLER(HDR_GFXPIPE_SUBOP(header),
+ cmds_gfxpipe_common_pipelined, "GFX COM PIPE");
+ break;
+ case COMMON_OP_NPIPELINED:
+ DOHANDLER(HDR_GFXPIPE_SUBOP(header),
+ cmds_gfxpipe_common_npipelined, "GFX COM NPIPE");
+ break;
+ default:
+ break;
+ }
+ break;
+ case GFXPIPE_3D:
+ switch (HDR_GFXPIPE_OP(header)) {
+ case G3D_OP_PIPELINED:
+ DOHANDLER(HDR_GFXPIPE_SUBOP(header),
+ cmds_gfxpipe_3d_pipelined, "GFX 3D PIPE");
+ break;
+ case G3D_OP_NPIPELINED:
+ DOHANDLER(HDR_GFXPIPE_SUBOP(header),
+ cmds_gfxpipe_3d_npipelined, "GFX 3D NPIPE");
+ break;
+ case G3D_OP_PIPE_CTRL:
+ DOHANDLER(HDR_GFXPIPE_SUBOP(header),
+ cmds_gfxpipe_3d_pipe_ctrl, "GFX 3D PIPE CTRL");
+ break;
+ case G3D_OP_PRIMITIVE:
+ DOHANDLER(HDR_GFXPIPE_SUBOP(header),
+ cmds_gfxpipe_3d_primitive, "GFX 3D PRIMITIVE");
+ break;
+ default:
+ break;
+ }
+
+ break;
+ default:
+ break;
+ }
+ break;
+ default: /* reserved */
+ break;
+ }
+ if (!dword) {
+ x3100_dbg(DBG_CLASS_MI, "MI: unknown header %x (ty=%x)\n",
+ header, HDR_TYPE(header));
+ dword = 1;
+ }
+ tmp += dword * 4;
+ }
+
+ state->ring.head = state->ring.tail;
+#undef DOHANDLER
+}
+
+static uint32_t x3100_mi_readb(void *opaque, target_phys_addr_t addr)
+{
+ X3100State *state = opaque;
+ addr -= state->mi_start;
+ return *(state->ram + addr);
+}
+
+static uint32_t x3100_mi_readw(void *opaque, target_phys_addr_t addr)
+{
+ X3100State *state = opaque;
+ addr -= state->mi_start;
+ return *((uint16_t *) (state->ram + addr));
+}
+
+static uint32_t x3100_mi_readl(void *opaque, target_phys_addr_t addr)
+{
+ X3100State *state = opaque;
+ addr -= state->mi_start;
+ return *((uint32_t *) (state->ram + addr));
+}
+
+static void x3100_mi_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ X3100State *state = opaque;
+
+ if (state->dsp[0].enable && addr >= state->fb_start && addr < state->fb_end) {
+ x3100_fb_write(state, 1, addr - state->fb_start, val & 0xff);
+ }
+ addr -= state->mi_start;
+ *((uint8_t *) (state->ram + addr)) = val & 0xff;
+ cpu_physical_memory_set_dirty(state->ram_offset + addr);
+}
+
+static void x3100_mi_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ X3100State *state = opaque;
+ addr -= state->mi_start;
+ *((uint16_t *) (state->ram + addr)) = val & 0xffff;
+ cpu_physical_memory_set_dirty(state->ram_offset + addr);
+}
+
+static void x3100_mi_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ X3100State *state = opaque;
+
+ if (state->dsp[0].enable && addr >= state->fb_start && addr < state->fb_end) {
+ x3100_fb_write(state, 4, addr - state->fb_start, val);
+ }
+ addr -= state->mi_start;
+ *((uint32_t *) (state->ram + addr)) = val;
+ cpu_physical_memory_set_dirty(state->ram_offset + addr);
+}
+
+CPUReadMemoryFunc *x3100_mi_read[3] = {
+ x3100_mi_readb, x3100_mi_readw, x3100_mi_readl,
+};
+
+CPUWriteMemoryFunc *x3100_mi_write[3] = {
+ x3100_mi_writeb, x3100_mi_writew, x3100_mi_writel,
+};
diff --git a/hw/x3100_mi.h b/hw/x3100_mi.h
new file mode 100644
index 0000000..99bbd3c
--- /dev/null
+++ b/hw/x3100_mi.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2008 Vincent Hanquez
+ *
+ * QEMU Intel X3100 emulation
+ */
+
+#define HDR_TYPE(x) (x >> 29)
+#define HDR_MI_OP(x) ((x >> 23) & 0x3f)
+#define HDR_2D_OP(x) ((x >> 22) & 0x7f)
+
+#define HDR_GFXPIPE_PIPELINE(x) ((x >> 27) & 0x3)
+#define HDR_GFXPIPE_OP(x) ((x >> 24) & 0x7)
+#define HDR_GFXPIPE_SUBOP(x) ((x >> 16) & 0xff)
+
+
+#define CMD_TYPE_MI 0x0
+#define CMD_TYPE_2D 0x2
+#define CMD_TYPE_GFXPIPE 0x3
+
+#define CMD_MI_NOP 0x00
+#define CMD_MI_USER_INT 0x02
+#define CMD_MI_WAIT_FOR_EVENT 0x03
+#define CMD_MI_FLUSH 0x04
+#define CMD_MI_ARB_CHECK 0x05
+#define CMD_MI_REPORT_HEAD 0x07
+#define CMD_MI_BATCH_END 0x0A
+#define CMD_MI_OVERLAY_FLIP 0x11
+#define CMD_MI_LOAD_SL_INCL 0x12
+#define CMD_MI_LOAD_SL_EXCL 0x13
+#define CMD_MI_DISP_FLIP 0x14
+#define CMD_MI_SET_CONTEXT 0x18
+#define CMD_MI_STORE_DATA_IMM 0x20
+#define CMD_MI_STORE_DATA_INDEX 0x21
+#define CMD_MI_LOAD_REG 0x22
+#define CMD_MI_STORE_REG_MEM 0x24
+#define CMD_MI_BATCH_START 0x31
+
+#define CMD_2D_XY_SETUP_BLT 0x01
+#define CMD_2D_XY_SETUP_CLIP_BLT 0x03
+#define CMD_2D_XY_SETUP_MONO_PATTERN_SL_BLT 0x11
+#define CMD_2D_XY_PIXEL_BLT 0x24
+#define CMD_2D_XY_SCANLINES_BLT 0x25
+#define CMD_2D_XY_TEXT_BLT 0x26
+#define CMD_2D_XY_TEXT_IMMEDIATE_BLT 0x31
+#define CMD_2D_COLOR_BLT 0x40
+#define CMD_2D_SRC_COPY_BLT 0x43
+#define CMD_2D_XY_COLOR_BLT 0x50
+#define CMD_2D_XY_PAT_BLT 0x51
+#define CMD_2D_XY_MONO_PAT_BLT 0x52
+#define CMD_2D_XY_SRC_COPY_BLT 0x53
+#define CMD_2D_XY_MONO_SRC_COPY_BLT 0x54
+#define CMD_2D_XY_FULL_BLT 0x55
+#define CMD_2D_XY_FULL_MONO_SRC_BLT 0x56
+#define CMD_2D_XY_FULL_MONO_PATTERN_BLT 0x57
+#define CMD_2D_XY_FULL_MONO_PATTERN_MONO_SRC_BLT 0x58
+#define CMD_2D_XY_MONO_PAT_FIXED_BLT 0x59
+#define CMD_2D_XY_MONO_SRC_COPY_IMMEDIATE_BLT 0x71
+#define CMD_2D_XY_PAT_BLT_IMMEDIATE 0x72
+#define CMD_2D_XY_SRC_COPY_CHROMA_BLT 0x73
+#define CMD_2D_XY_FULL_IMMEDIATE_PATTERN_BLT 0x74
+#define CMD_2D_XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT 0x75
+#define CMD_2D_XY_PAT_CHROMA_BLT 0x76
+#define CMD_2D_XY_PAT_CHROMA_BLT_IMMEDIATE 0x77
+
+#define GFXPIPE_COMMON 0x0
+# define COMMON_OP_PIPELINED 0x0
+# define CMD_GFX_URB_FENCE 0x0
+# define CMD_GFX_URB_STATE 0x1
+# define CMD_GFX_CONSTANT_BUFFER 0x2
+# define CMD_GFX_STATE_PREFETCH 0x3
+# define COMMON_OP_NPIPELINED 0x1
+# define CMD_GFX_STATE_BASE_ADDR 0x1
+# define CMD_GFX_STATE_SIP 0x2
+# define CMD_GFX_PIPELINE_SELECT 0x4
+#define GFXPIPE_3D 0x3
+# define G3D_OP_PIPELINED 0x0
+# define CMD_3D_PIPELINED_PTRS 0x00
+# define CMD_3D_BINDING_TABLE_PTRS 0x01
+# define CMD_3D_VERTEX_BUFFERS 0x08
+# define CMD_3D_VERTEX_ELEMENTS 0x09
+# define CMD_3D_INDEX_BUFFER 0x0A
+# define CMD_3D_VF_STATISTICS 0x0B
+# define G3D_OP_NPIPELINED 0x1
+# define CMD_3D_DRAWING_RECTANGLE 0x00
+# define CMD_3D_CONSTANT_COLOR 0x01
+# define CMD_3D_SAMPLER_PALETTE_LOAD 0x02
+# define CMD_3D_CHROMA_KEY 0x04
+# define CMD_3D_DEPTH_BUFFER 0x05
+# define CMD_3D_POLY_STIPPLE_OFFSET 0x06
+# define CMD_3D_POLY_STIPPLE_PATTERN 0x07
+# define CMD_3D_LINE_STIPPLE 0x08
+# define CMD_3D_GLOBAL_DEPTH_OFFSET_CLAMP 0x09
+# define CMD_3D_AA_LINE_PARAMS 0x0A
+# define CMD_3D_GS_SVB_INDEX 0x0B
+# define G3D_OP_PIPE_CTRL 0x2
+# define G3D_OP_PRIMITIVE 0x3
+
+typedef enum {
+ PRIM3D_POINTLIST = 0x01,
+ PRIM3D_LINELIST = 0x02,
+ PRIM3D_LINESTRIP = 0x03,
+ PRIM3D_TRILIST = 0x04,
+ PRIM3D_TRISTRIP = 0x05,
+ PRIM3D_TRIFAN = 0x06,
+ PRIM3D_QUADLIST = 0x07,
+ PRIM3D_QUADSTRIP = 0x08,
+ PRIM3D_TRISTRIP_REVERSE = 0x0D,
+ PRIM3D_POLYGON = 0x0E,
+ PRIM3D_RECTLIST = 0x0F,
+ PRIM3D_LINELOOP = 0x10,
+ PRIM3D_POINTLIST_BF = 0x11,
+ PRIM3D_LINESTRIP_CONT = 0x12,
+ PRIM3D_LINESTRIP_BF = 0x13,
+ PRIM3D_LINESTRIP_CONT_BF = 0x14,
+ PRIM3D_TRIFAN_NOSTIPPLE = 0x16,
+} prim3d_types;
diff --git a/hw/x3100_regs.c b/hw/x3100_regs.c
new file mode 100644
index 0000000..f258478
--- /dev/null
+++ b/hw/x3100_regs.c
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2008 Vincent Hanquez
+ *
+ * QEMU Intel X3100 emulation
+ */
+
+#include "x3100.h"
+#include "x3100_regs.h"
+
+typedef struct mmio_reg_fct {
+ uint32_t (*read)(X3100State *state, int addr);
+ void (*write)(X3100State *state, int addr, uint32_t val);
+} mmio_reg_fct;
+
+struct mmio_reg_range
+{
+ int start;
+ int end;
+ mmio_reg_fct *fct;
+ char *desc;
+};
+
+/********************************************************************/
+
+static void reserved_mmio_write(X3100State *state, int addr, uint32_t val)
+{
+ x3100_dbg(DBG_CLASS_REG, "reserved: w(%x,%x)\n", addr, val);
+}
+
+static uint32_t reserved_mmio_read(X3100State *state, int addr)
+{
+ x3100_dbg(DBG_CLASS_REG, "reserved: r(%x)\n", addr);
+ return 0x0;
+}
+
+static mmio_reg_fct reserved_mmio =
+{
+ .read = reserved_mmio_read,
+ .write = reserved_mmio_write,
+};
+
+static void unimplemented_mmio_write(X3100State *state, int addr, uint32_t val)
+{
+}
+
+static uint32_t unimplemented_mmio_read(X3100State *state, int addr)
+{
+ return 0x0;
+}
+
+static mmio_reg_fct unimplemented_mmio =
+{
+ .read = unimplemented_mmio_read,
+ .write = unimplemented_mmio_write,
+};
+
+static void dummy_mmio_write(X3100State *state, int addr, uint32_t val)
+{
+ *((uint32_t *) (state->mmio_regs + addr)) = val;
+}
+
+static uint32_t dummy_mmio_read(X3100State *state, int addr)
+{
+ uint32_t ret;
+ ret = *((uint32_t *) (state->mmio_regs + addr));
+ return ret;
+}
+
+static mmio_reg_fct dummy_mmio =
+{
+ .read = dummy_mmio_read,
+ .write = dummy_mmio_write,
+};
+
+/********************************************************************/
+static void imi_mmio_write(X3100State *state, int addr, uint32_t val)
+{
+ int handled = 1;
+
+ switch (addr) {
+ case REG_IMI_PGTBL_CTL:
+ state->gtt_enable = (val & 1);
+ switch ((val & 0xf) >> 1) {
+ case 0: state->gtt_size_kb = 512; break;
+ case 1: state->gtt_size_kb = 256; break;
+ case 2: state->gtt_size_kb = 128; break;
+ case 3: case 4: case 5: default:
+ state->gtt_enable = 0; break;
+ }
+ state->gtt_base_addr = (val >> 4 & 0xf) << 32
+ || (val & 0xfffff000);
+ break;
+ case REG_IMI_PRB0_TAIL:
+ state->ring.tail = val;
+ //printf("ring tail %x\n", val);
+ state->eventpending |= X3100_EVENT_RING;
+ break;
+ case REG_IMI_PRB0_HEAD:
+ state->ring.headcount = val >> 17;
+ state->ring.head = val & 0x1ffffc;
+ printf("ring head %x count %x\n",
+ state->ring.head, state->ring.headcount);
+ break;
+ case REG_IMI_PRB0_START:
+ state->ring.start = val;
+ printf("ring start %x\n", state->ring.start);
+ break;
+ case REG_IMI_PRB0_CTL:
+ state->ring.enable = val & 0x1;
+ state->ring.autoreport = (val >> 1) & 0x3;
+ state->ring.length = (((val >> 12) & 0x1ff) + 1) * 4096;
+ printf("ring enable %d autoreport %x length %d (val %x)\n",
+ state->ring.enable, state->ring.autoreport,
+ state->ring.length, val);
+ break;
+ case REG_IMI_IER:
+ state->ier = val;
+ printf("ier: %.8x\n", val);
+ break;
+ case REG_IMI_IIR:
+ state->iir = val;
+ printf("iir: %.8x\n", val);
+ break;
+ case REG_IMI_IMR:
+ state->imr = val;
+ printf("imr: %.8x\n", val);
+ break;
+ case REG_IMI_ISR:
+ state->isr = val;
+ printf("isr: %.8x\n", val);
+ break;
+ default:
+ handled = 0;
+ *((uint32_t *) (state->mmio_regs + addr)) = val;
+ break;
+ }
+ //fprintf(out, "imi write at %x <- %x\n", addr, val);
+}
+
+static uint32_t imi_mmio_read(X3100State *state, int addr)
+{
+ uint32_t ret;
+ int handled = 1;
+
+ switch (addr) {
+ case REG_IMI_PGTBL_CTL:
+ ret = state->gtt_enable == 1;
+ ret |= ((state->gtt_size_kb == 512) ? 0
+ : (state->gtt_size_kb == 256) ? 1
+ : (state->gtt_size_kb == 128) ? 2 : 0) << 1;
+ ret |= (state->gtt_base_addr & 0xfffff000);
+ break;
+ case REG_IMI_PRB0_TAIL:
+ ret = state->ring.tail;
+ break;
+ case REG_IMI_PRB0_HEAD:
+ ret = state->ring.headcount << 17 | state->ring.head;
+ break;
+ case REG_IMI_PRB0_START:
+ ret = state->ring.start;
+ break;
+ case REG_IMI_PRB0_CTL:
+ ret = (((state->ring.length / 4096) - 1) << 12)
+ | (state->ring.autoreport << 1)
+ | (state->ring.enable);
+ break;
+ case REG_IMI_IER: ret = state->ier; break;
+ case REG_IMI_IIR: ret = state->iir; break;
+ case REG_IMI_IMR: ret = state->imr; break;
+ case REG_IMI_ISR: ret = state->isr; break;
+ default:
+ handled = 0;
+ ret = *((uint32_t *) (state->mmio_regs + addr));
+ break;
+ }
+ //fprintf(out, "imi read at %x (value %x) (handled = %d)\n", addr, ret, handled);
+ return ret;
+}
+
+static mmio_reg_fct imi_mmio =
+{
+ .read = imi_mmio_read,
+ .write = imi_mmio_write,
+};
+
+/********************************************************************/
+static void fence_mmio_write(X3100State *state, int addr, uint32_t val)
+{
+ int handled = 1;
+
+ if (addr >= FENCE_START && addr < FENCE_END) {
+ int fence_offset = (addr - FENCE_START) / 8;
+ switch ((addr - FENCE_START) % 8) {
+ case 0:
+ printf("fence %d start: %.8x\n", fence_offset, val);
+ state->fences[fence_offset].start = val;
+ break;
+ case 1:
+ printf("fence %d end: %.8x\n", fence_offset, val);
+ state->fences[fence_offset].end = val;
+ break;
+ }
+ return;
+ }
+ switch (addr) {
+ default:
+ handled = 0;
+ *((uint32_t *) (state->mmio_regs + addr)) = val;
+ break;
+ }
+}
+
+static uint32_t fence_mmio_read(X3100State *state, int addr)
+{
+ uint32_t ret;
+ int handled = 1;
+
+ switch (addr) {
+ default:
+ handled = 0;
+ ret = *((uint32_t *) (state->mmio_regs + addr));
+ break;
+ }
+ return ret;
+}
+
+static mmio_reg_fct fence_mmio =
+{
+ .read = fence_mmio_read,
+ .write = fence_mmio_write,
+};
+
+/********************************************************************/
+static void ioc_mmio_write(X3100State *state, int addr, uint32_t val)
+{
+ int handled = 1;
+
+ switch (addr) {
+ case REG_IOC_GPIOCTL_0:
+ state->gpioctl[0] = val;
+ break;
+ default:
+ handled = 0;
+ break;
+ }
+}
+
+static uint32_t ioc_mmio_read(X3100State *state, int addr)
+{
+ uint32_t ret;
+ int handled = 1;
+
+ switch (addr) {
+ case REG_IOC_GPIOCTL_0:
+ return state->gpioctl[0] & ~(0x4 | 0x100 | 0x400);
+ break;
+ default:
+ handled = 0;
+ break;
+ }
+ return ret;
+}
+
+static mmio_reg_fct ioc_mmio =
+{
+ .read = ioc_mmio_read,
+ .write = ioc_mmio_write,
+};
+/********************************************************************/
+
+
+static void display_engine_mmio_write(X3100State *state, int addr, uint32_t val)
+{
+ if (addr > REG_DE_TV_start && addr <= REG_DE_TV_end)
+ return;
+ switch (addr) {
+ case REG_DE_HTOTAL_A:
+ printf("htotal: total=%d active=%d\n", (val >> 16) & 0x1fff, val & 0xfff);
+ break;
+ case REG_DE_HBLANK_A:
+ printf("hblank: end=%d start=%d\n", (val >> 16) & 0x1fff, val & 0x1fff);
+ break;
+ case REG_DE_HSYNC_A:
+ printf("hsync: end=%d start=%d\n", (val >> 16) & 0x1fff, val & 0x1fff);
+ break;
+ case REG_DE_VTOTAL_A:
+ printf("vtotal: total=%d active=%d\n", (val >> 16) & 0x1fff, val & 0xfff);
+ break;
+ case REG_DE_VBLANK_A:
+ printf("vblank: end=%d start=%d\n", (val >> 16) & 0x1fff, val & 0x1fff);
+ break;
+ case REG_DE_VSYNC_A:
+ printf("vsync: end=%d start=%d\n", (val >> 16) & 0x1fff, val & 0x1fff);
+ break;
+ case REG_DE_PIPEASRC:
+ printf("pipe size set %dx%d\n", ((val >> 16) & 0xfff) + 1, (val & 0xfff) + 1);
+ state->dsp[0].out_width = ((val >> 16) & 0xfff) + 1;
+ state->dsp[0].out_height = (val & 0xfff) + 1;
+ break;
+ case REG_DE_PORT_HOTPLUG_EN:
+ if (val & 0x8) {
+ *((uint32_t *) (state->mmio_regs + REG_DE_PORT_HOTPLUG_STAT)) = 3 << 8;
+ }
+ break;
+ default:
+ break;
+ }
+ *((uint32_t *) (state->mmio_regs + addr)) = val;
+}
+
+static uint32_t display_engine_mmio_read(X3100State *state, int addr)
+{
+ uint32_t ret;
+ //if (addr > REG_DE_TV_start && addr <= REG_DE_TV_end)
+ // return;
+ switch (addr) {
+ case REG_DE_PORT_HOTPLUG_EN:
+ ret = *((uint32_t *) (state->mmio_regs + addr));
+ return ret;
+ case REG_DE_TV_out_control: return 0x20; /* disable TV */
+ }
+ ret = *((uint32_t *) (state->mmio_regs + addr));
+ return ret;
+}
+
+static mmio_reg_fct display_engine_mmio =
+{
+ .read = display_engine_mmio_read,
+ .write = display_engine_mmio_write,
+};
+/********************************************************************/
+
+static void clock_mmio_write(X3100State *state, int addr, uint32_t val)
+{
+ *((uint32_t *) (state->mmio_regs + addr)) = val;
+}
+
+static uint32_t clock_mmio_read(X3100State *state, int addr)
+{
+ uint32_t ret;
+ int handled = 1;
+
+ switch (addr) {
+ case REG_CR_VGA0: ret = REG_CR_VGA0_DEFAULT; break;
+ case REG_CR_VGA1: ret = REG_CR_VGA1_DEFAULT; break;
+ case REG_CR_VGA_PD: ret = REG_CR_VGA_PD_DEFAULT; break;
+ case REG_CR_DPLLA_CTRL: ret = REG_CR_DPLLA_CTRL_DEFAULT; break;
+ case REG_CR_DPLLB_CTRL: ret = REG_CR_DPLLB_CTRL_DEFAULT; break;
+ case REG_CR_DPLLAMD: ret = REG_CR_DPLLAMD_DEFAULT; break;
+ case REG_CR_DPLLBMD: ret = REG_CR_DPLLBMD_DEFAULT; break;
+ case REG_CR_FPA0: ret = REG_CR_FPA0_DEFAULT; break;
+ case REG_CR_FPA1: ret = REG_CR_FPA1_DEFAULT; break;
+ case REG_CR_FPB0: ret = REG_CR_FPB0_DEFAULT; break;
+ case REG_CR_FPB1: ret = REG_CR_FPB1_DEFAULT; break;
+ case REG_CR_DPLL_TEST: ret = REG_CR_DPLL_TEST_DEFAULT; break;
+ case REG_CR_D_STATE: ret = REG_CR_D_STATE_DEFAULT; break;
+ case REG_CR_DSPCLK_GATE_D: ret = REG_CR_DSPCLK_GATE_D_DEFAULT; break;
+ case REG_CR_RENCLK_GATE_D1: ret = REG_CR_RENCLK_GATE_D1_DEFAULT; break;
+ case REG_CR_RENDCLK_GATE_D2: ret = REG_CR_RENDCLK_GATE_D2_DEFAULT; break;
+ case REG_CR_RAMCLK_GATE_D: ret = REG_CR_RAMCLK_GATE_D_DEFAULT; break;
+ default:
+ handled = 0;
+ ret = *((uint32_t *) (state->mmio_regs + addr));
+ break;
+ }
+ return ret;
+}
+
+static mmio_reg_fct clock_mmio =
+{
+ .read = clock_mmio_read,
+ .write = clock_mmio_write,
+};
+
+/********************************************************************/
+static void display_mmio_write(X3100State *state, int addr, uint32_t val)
+{
+ int handled = 1;
+
+ switch (addr) {
+ case REG_DR_VGACNTRL:
+ printf("%sing VGA\n", (val & 0x80000000) ? "disabl" : "enabl");
+ break;
+ case REG_DR_CURACNTR:
+ state->mouse_show = (val & 0x27) != 0;
+ state->eventpending |= X3100_EVENT_MOUSE_UPDATE;
+ break;
+ case REG_DR_CURAPOS:
+ state->mouse_y = ((val & 0x80000000) ? -1 : 1) * ((val >> 16) & 0xfff);
+ state->mouse_x = ((val & 0x8000) ? -1 : 1) * (val & 0xfff);
+ state->eventpending |= X3100_EVENT_MOUSE_UPDATE;
+ break;
+ case REG_DR_DSPACNTR:
+ printf("display: %d gamma: %d format: %d tiled: %d rotated: %d\n",
+ (val >> 31) & 0x1, (val >> 30) & 0x1,
+ (val >> 26) & 0xf, (val >> 15 & 0x1),
+ (val >> 10) & 0x1);
+ state->dsp[0].enable = (val >> 31) & 0x1;
+ state->dsp[0].gamma = (val >> 30) & 0x1;
+ state->dsp[0].format = (val >> 26) & 0xf;
+ state->dsp[0].tiled = (val >> 15) & 0x1;
+ state->dsp[0].rotated = (val >> 10) & 0x1;
+ if (state->dsp[0].enable) {
+ state->eventpending |= X3100_EVENT_RESIZE;
+
+ switch (state->dsp[0].format) {
+ case FORMAT_BGRX_32: state->dsp[0].cpp = 4; break;
+ case FORMAT_BGRX_16: state->dsp[0].cpp = 2; break;
+ default: state->dsp[0].cpp = 4; /* FIXME */
+ }
+
+ state->dsp[0].width = state->dsp[0].stride / state->dsp[0].cpp;
+
+ /* FIXME: hardcoded height based on width.
+ * need to find a better way to actually have the actual value */
+ switch (state->dsp[0].width) {
+ case 320: state->dsp[0].height = 240; break;
+ case 640: state->dsp[0].height = 480; break;
+ case 800: state->dsp[0].height = 600; break;
+ case 1024: state->dsp[0].height = 768; break;
+ case 1280: state->dsp[0].height = 1024; break;
+ case 1600: state->dsp[0].height = 1200; break;
+ case 1900: state->dsp[0].height = 1200; break;
+ default: state->dsp[0].height = 200;
+ }
+ printf("dsp enabled (width=%d,height=%d,fmt=%d,cpp=%d)\n",
+ state->dsp[0].width, state->dsp[0].height,
+ state->dsp[0].format, state->dsp[0].cpp);
+ } else {
+ state->fb_start = state->fb_end = 0;
+ }
+ break;
+ case REG_DR_DSPALINOFF: state->dsp[0].addr_offset = val; break;
+ case REG_DR_DSPASTRIDE: state->dsp[0].stride = val; break;
+ case REG_DR_DSPASURF:
+ state->dsp[0].addr_start = val;
+ state->fb_start = state->mi_start + state->dsp[0].addr_start;
+ state->fb_end = state->fb_start +
+ (state->dsp[0].stride * state->dsp[0].out_height);
+ printf("framebuffer start: %lx end: %lx\n", state->fb_start, state->fb_end);
+ break;
+ case REG_DR_DSPATILEOFF:
+ printf("tileoff: %x\n", val);
+ break;
+ default:
+ handled = 0;
+ break;
+ }
+ *((uint32_t *) (state->mmio_regs + addr)) = val;
+}
+
+static uint32_t display_mmio_read(X3100State *state, int addr)
+{
+ uint32_t ret;
+ int handled = 1;
+
+ switch (addr) {
+ case REG_DR_DSPALINOFF: ret = state->dsp[0].addr_offset; break;
+ case REG_DR_DSPASURF: ret = state->dsp[0].addr_start; break;
+ default:
+ handled = 0;
+ ret = *((uint32_t *) (state->mmio_regs + addr));
+ break;
+ }
+ return ret;
+}
+
+static mmio_reg_fct display_mmio =
+{
+ .read = display_mmio_read,
+ .write = display_mmio_write,
+};
+
+/********************************************************************/
+struct mmio_reg_range mmio_regs_table[23];
+
+void x3100_regs_init(X3100State *state)
+{
+ state->gpioctl[0] = 0x808;
+ state->imr = 0xfffedfff;
+ state->mmio_regs = malloc(512 * 1024);
+ memset(state->mmio_regs, '\0', 512 * 1024);
+
+ /* FIXME: would be better as some kind of radix tree */
+ #define D(i,s,e,d,f) mmio_regs_table[i].start = s; \
+ mmio_regs_table[i].end = e; \
+ mmio_regs_table[i].fct = &f; \
+ mmio_regs_table[i].desc = d
+ D(0, 0x00000, 0x00FFF, "VGA", unimplemented_mmio);
+ D(1, 0x01000, 0x01FFF, "reserved", reserved_mmio);
+ D(2, 0x02000, 0x02FFF, "Instruction/Memory/Interrupt", imi_mmio);
+ D(3, 0x03000, 0x031FF, "Fence & PP GTT control", fence_mmio);
+ D(4, 0x03200, 0x03FFF, "Frame buffer compression", unimplemented_mmio);
+ D(5, 0x04000, 0x043FF, "reserved", reserved_mmio);
+ D(6, 0x04400, 0x04FFF, "reserved", reserved_mmio);
+ D(7, 0x05000, 0x05FFF, "I/O control", ioc_mmio);
+ D(8, 0x06000, 0x06FFF, "Clock control", clock_mmio);
+ D(9, 0x07000, 0x073FF, "3D internal debug", unimplemented_mmio);
+ D(10, 0x07400, 0x088FF, "GPE debug", unimplemented_mmio);
+ D(11, 0x08900, 0x08FFF, "reserved", reserved_mmio);
+ D(12, 0x09000, 0x09FFF, "reserved", reserved_mmio);
+ D(13, 0x0A000, 0x0AFFF, "Display palette", unimplemented_mmio);
+ D(14, 0x0B000, 0x0FFFF, "reserved", reserved_mmio);
+ D(15, 0x10000, 0x13FFF, "MMIO MCHBAR", unimplemented_mmio);
+ D(16, 0x14000, 0x2FFFF, "reserved", reserved_mmio);
+ D(17, 0x30000, 0x3FFFF, "Overlay", unimplemented_mmio);
+ D(18, 0x40000, 0x5FFFF, "reserved", reserved_mmio);
+ D(19, 0x60000, 0x6FFFF, "Display engine pipeline", display_engine_mmio);
+ D(20, 0x70000, 0x72FFF, "Display and cursor", display_mmio);
+ D(21, 0x73000, 0x73FFF, "Performance counters", unimplemented_mmio);
+ D(22, 0x74000, 0x7FFFF, "reserved", reserved_mmio);
+ #undef D
+}
+
+
+static struct mmio_reg_range * get_reg_range(int addr)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mmio_regs_table); i++)
+ if (addr >= mmio_regs_table[i].start &&
+ addr <= mmio_regs_table[i].end)
+ break;
+ return (i < ARRAY_SIZE(mmio_regs_table)) ? &mmio_regs_table[i] : NULL;
+}
+
+void x3100_regs_write(X3100State *state, int addr, uint32_t val)
+{
+ struct mmio_reg_range *range;
+
+ range = get_reg_range(addr);
+ if (!range)
+ return;
+ x3100_dbg(DBG_CLASS_REG, "REG: w(%x,%x) [%s]\n", addr, val, range->desc);
+ (range->fct->write)(state, addr, val);
+
+ /* check if we got events, and process them if any */
+ if (state->eventpending) {
+ if ((state->eventpending & X3100_EVENT_MOUSE_UPDATE) &&
+ (state->ds->mouse_set != NULL)) {
+ state->ds->mouse_set(state->mouse_x, state->mouse_y, state->mouse_show);
+ }
+
+ if ((state->eventpending & X3100_EVENT_RESIZE) &&
+ (state->ds->dpy_resize != NULL)) {
+ state->ds->dpy_resize(state->ds,
+ state->dsp[0].out_width,
+ state->dsp[0].out_height);
+ }
+
+ if (state->eventpending & X3100_EVENT_RING) {
+ x3100_ring_process(state);
+ }
+ /* reset the event pending */
+ state->eventpending = 0;
+ }
+}
+
+uint32_t x3100_regs_read(X3100State *state, int addr)
+{
+ struct mmio_reg_range *range;
+ uint32_t ret;
+ static int previous_addr = -1;
+ static int previous_ret = -1;
+ static int last_previous = 0;
+
+ range = get_reg_range(addr);
+ if (!range)
+ return 0xdeadbeef;
+ ret = (range->fct->read)(state, addr);
+ if (addr != previous_addr || previous_ret != ret) {
+ if (last_previous > 0)
+ x3100_dbg(DBG_CLASS_REG, "REG: last read repeated %d times\n",
+ last_previous);
+ x3100_dbg(DBG_CLASS_REG, "REG: r(%x) = %x [%s]\n", addr, ret, range->desc);
+ previous_addr = addr;
+ previous_ret = ret;
+ last_previous = 0;
+ } else
+ last_previous++;
+ return ret;
+}
+
+static uint32_t x3100_mmio_readb(void *opaque, target_phys_addr_t addr)
+{
+ addr &= 0x7ffff;
+ if (addr >= 0 && addr < 0x1000)
+ return x3100_vga_ioport_read(opaque, addr);
+
+ printf("MMIO R(1) = %lx\n", addr);
+ return -1;
+}
+
+static uint32_t x3100_mmio_readw(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t ret;
+
+ addr &= 0x7ffff;
+ ret = x3100_regs_read(opaque, addr & ~0x3);
+ switch (addr % 2) {
+ case 0: ret &= 0xffff; break;
+ case 1: ret >>= 16; break;
+ }
+ return ret;
+}
+
+static uint32_t x3100_mmio_readl(void *opaque, target_phys_addr_t addr)
+{
+ addr &= 0x7ffff;
+ return x3100_regs_read(opaque, addr);
+}
+
+static void x3100_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ addr &= 0x7ffff;
+ if (addr >= 0 && addr < 0x1000) {
+ x3100_vga_ioport_write(opaque, addr, val);
+ return;
+ }
+ printf("MMIO W(1) = %lx -> %x\n", addr, val);
+}
+
+static void x3100_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ uint32_t ret;
+ addr &= 0x7ffff;
+ ret = x3100_regs_read(opaque, addr & ~0x3);
+ switch (addr % 2) {
+ case 0: val = (ret & ~0xffff) | (val & 0xffff); break;
+ case 1: val = (ret & 0xffff) | (val << 16); break;
+ }
+ x3100_regs_write(opaque, addr & ~0x3, val);
+}
+
+static void x3100_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ addr &= 0x7ffff;
+ x3100_regs_write(opaque, addr, val);
+}
+
+CPUReadMemoryFunc *x3100_mmio_read[3] = {
+ x3100_mmio_readb, x3100_mmio_readw, x3100_mmio_readl,
+};
+
+CPUWriteMemoryFunc *x3100_mmio_write[3] = {
+ x3100_mmio_writeb, x3100_mmio_writew, x3100_mmio_writel,
+};
diff --git a/hw/x3100_regs.h b/hw/x3100_regs.h
new file mode 100644
index 0000000..4cd9493
--- /dev/null
+++ b/hw/x3100_regs.h
@@ -0,0 +1,206 @@
+#ifndef QEMU_X3100_REGS_H
+#define QEMU_X3100_REGS_H
+
+/* instruction memory interrupt */
+#define REG_IMI_PGTBL_CTL 0x02020
+#define REG_IMI_PGTBL_ER 0x02024
+#define REG_IMI_EXCC 0x02028
+#define REG_IMI_PRB0_TAIL 0x02030
+#define REG_IMI_PRB0_HEAD 0x02034
+#define REG_IMI_PRB0_START 0x02038
+#define REG_IMI_PRB0_CTL 0x0203C
+#define REG_IMI_HW_MEMRD 0x02060
+#define REG_IMI_IPEIR 0x02064
+#define REG_IMI_IPEHR 0x02068
+#define REG_IMI_INSTDONE 0x0206C
+#define REG_IMI_INSTPS 0x02070
+#define REG_IMI_ACTHD 0x02074
+#define REG_IMI_DMA_FADD_P 0x02078
+#define REG_IMI_INSTDONE_1 0x0207C
+#define REG_IMI_HWS_PGA 0x02080
+#define REG_IMI_PWRCTXA 0x02088
+#define REG_IMI_NOPID 0x02094
+#define REG_IMI_HWSTAM 0x02098
+#define REG_IMI_MI_MODE 0x0209C
+#define REG_IMI_IER 0x020A0
+#define REG_IMI_IIR 0x020A4
+#define REG_IMI_IMR 0x020A8
+#define REG_IMI_ISR 0x020AC
+#define REG_IMI_EIR 0x020B0
+#define REG_IMI_EMR 0x020B4
+#define REG_IMI_ESR 0x020B8
+#define REG_IMI_INSTPM 0x020C0
+#define REG_IMI_PGTBL_CTL2 0x020C4
+#define REG_IMI_PGTBL_STR2 0x020C8
+#define REG_IMI_MI_DISPLAY_POWER_DOWN 0x020E0
+#define REG_IMI_MI_ARB_STATE 0x020E4
+#define REG_IMI_MI_RDRET_STATE 0x020FC
+#define REG_IMI_CACHE_MODE_0 0x02120
+#define REG_IMI_CACHE_MODE_1 0x02124
+#define REG_IMI_UHPTR 0x02134
+#define REG_IMI_BB_ADDR 0x02140
+#define REG_IMI_BB_STATE 0x02148
+#define REG_IMI_GFX_FLSH_CNTL 0x02170
+#define REG_IMI_CCID0 0x02180
+#define REG_IMI_CXT_SIZE 0x021A0
+#define REG_IMI_CXT_SIZE_NOEXT 0x021A4
+#define REG_IMI_ECOSKPD 0x021D0
+#define REG_IMI_CSFLFSM 0x02200
+#define REG_IMI_CSFLFLAG 0x02204
+#define REG_IMI_CSFLTRK 0x02208
+#define REG_IMI_CSCMDOP 0x0220C
+#define REG_IMI_CSCMDVLD 0x02210
+#define REG_IMI_PS_DEPTH_COUNT 0x02350
+#define REG_IMI_TIMESTAMP 0x02358
+#define REG_IMI_CLKCMP 0x02360
+#define REG_IMI_VFDC 0x02450
+#define REG_IMI_VFSKPD 0x02470
+
+#define FENCE_START 0x03000
+#define FENCE_END 0x0307F
+
+/* gmbus & io control */
+#define REG_IOC_GPIOCTL_0 0x05010
+#define REG_IOC_GPIOCTL_1 0x05014
+#define REG_IOC_GPIOCTL_2 0x05018
+#define REG_IOC_GPIOCTL_3 0x0501C
+#define REG_IOC_GPIOCTL_4 0x05020
+#define REG_IOC_GPIOCTL_5 0x05024
+#define REG_IOC_GPIOCTL_6 0x05028
+#define REG_IOC_GPIOCTL_7 0x0502C
+
+/* clock */
+#define REG_CR_VGA0 0x06000
+#define REG_CR_VGA0_DEFAULT 0x00031108
+#define REG_CR_VGA1 0x06004
+#define REG_CR_VGA1_DEFAULT 0x00031406
+#define REG_CR_VGA_PD 0x06010
+#define REG_CR_VGA_PD_DEFAULT 0x00020002
+#define REG_CR_DPLLA_CTRL 0x06014
+#define REG_CR_DPLLA_CTRL_DEFAULT 0x04020C00
+#define REG_CR_DPLLB_CTRL 0x06018
+#define REG_CR_DPLLB_CTRL_DEFAULT 0x04020C00
+#define REG_CR_DPLLAMD 0x0601C
+#define REG_CR_DPLLAMD_DEFAULT 0x00000003
+#define REG_CR_DPLLBMD 0x06020
+#define REG_CR_DPLLBMD_DEFAULT 0x00000003
+#define REG_CR_FPA0 0x06040
+#define REG_CR_FPA0_DEFAULT 0x00031108
+#define REG_CR_FPA1 0x06044
+#define REG_CR_FPA1_DEFAULT 0x00031108
+#define REG_CR_FPB0 0x06048
+#define REG_CR_FPB0_DEFAULT 0x00031108
+#define REG_CR_FPB1 0x0604C
+#define REG_CR_FPB1_DEFAULT 0x00031108
+#define REG_CR_DPLL_TEST 0x0606C
+#define REG_CR_DPLL_TEST_DEFAULT 0x00010001
+#define REG_CR_D_STATE 0x06104
+#define REG_CR_D_STATE_DEFAULT 0x00000000
+#define REG_CR_DSPCLK_GATE_D 0x06200
+#define REG_CR_DSPCLK_GATE_D_DEFAULT 0x10000000
+#define REG_CR_RENCLK_GATE_D1 0x06204
+#define REG_CR_RENCLK_GATE_D1_DEFAULT 0x00000000
+#define REG_CR_RENDCLK_GATE_D2 0x06208
+#define REG_CR_RENDCLK_GATE_D2_DEFAULT 0x00000000
+#define REG_CR_RAMCLK_GATE_D 0x06210
+#define REG_CR_RAMCLK_GATE_D_DEFAULT 0x00000000
+
+/* display engine */
+#define REG_DE_HTOTAL_A 0x60000
+#define REG_DE_HBLANK_A 0x60004
+#define REG_DE_HSYNC_A 0x60008
+#define REG_DE_VTOTAL_A 0x6000C
+#define REG_DE_VBLANK_A 0x60010
+#define REG_DE_VSYNC_A 0x60014
+#define REG_DE_PIPEASRC 0x6001C
+#define REG_DE_BCLRPAT_A 0x60020
+#define REG_DE_VSYNCSHIFT_A 0x60028
+#define REG_DE_CRCCtrlColorA 0x60050
+#define REG_DE_HTOTAL_B 0x61000
+#define REG_DE_HBLANK_B 0x61004
+#define REG_DE_HSYNC_B 0x61008
+#define REG_DE_VTOTAL_B 0x6100C
+#define REG_DE_VBLANK_B 0x61010
+#define REG_DE_VSYNC_B 0x61014
+#define REG_DE_PIPEBSRC 0x6101C
+#define REG_DE_BCLRPAT_B 0x61020
+#define REG_DE_VSYNCSHIFT_B 0x61028
+
+
+#define REG_DE_ADPA 0x61100
+#define REG_DE_PORT_HOTPLUG_EN 0x61110
+#define REG_DE_PORT_HOTPLUG_STAT 0x61114
+
+#define REG_DE_TV_start 0x68000
+#define REG_DE_TV_out_control REG_DE_TV_start
+#define REG_DE_TV_end 0x68500
+
+/* display register */
+#define REG_DR_PIPEA_DSL 0x70000
+#define REG_DR_PIPEA_SLC 0x70004
+#define REG_DR_PIPEACONF 0x70008
+
+#define REG_DR_CURACNTR 0x70080
+#define REG_DR_CURABASE 0x70084
+#define REG_DR_CURAPOS 0x70088
+
+#define REG_DR_DSPACNTR 0x70180
+#define REG_DR_DSPALINOFF 0x70184
+#define REG_DR_DSPASTRIDE 0x70188
+#define REG_DR_DSPAKEYVAL 0x70194
+#define REG_DR_DSPAKEYMSK 0x70198
+#define REG_DR_DSPASURF 0x7019C
+#define REG_DR_DSPATILEOFF 0x701A4
+#define REG_DR_DSPAFLPQSTAT 0x70200
+
+#define REG_DR_SWF00 0x70410
+#define REG_DR_SWF01 0x70414
+#define REG_DR_SWF02 0x70418
+#define REG_DR_SWF03 0x7041C
+#define REG_DR_SWF04 0x70420
+#define REG_DR_SWF05 0x70424
+#define REG_DR_SWF06 0x70428
+#define REG_DR_SWF07 0x7042C
+#define REG_DR_SWF08 0x70430
+#define REG_DR_SWF09 0x70434
+#define REG_DR_SWF0A 0x70438
+#define REG_DR_SWF0B 0x7043C
+#define REG_DR_SWF0C 0x70440
+#define REG_DR_SWF0D 0x70444
+#define REG_DR_SWF0E 0x70448
+#define REG_DR_SWF0F 0x7044C
+
+#define REG_DR_DSPBCNTR 0x71180
+#define REG_DR_DSPBLINOFFSET 0x71184
+#define REG_DR_DSPBSTRIDE 0x71188
+#define REG_DR_DSPBKEYVAL 0x71194
+#define REG_DR_DSPBKEYMSK 0x71198
+#define REG_DR_DSPBSURF 0x7119C
+#define REG_DR_DSPBTILEOFF 0x711A4
+#define REG_DR_DSPBFLPQSTAT 0x71200
+
+#define REG_DR_VGACNTRL 0x71400
+#define REG_DR_SWF10 0x71410
+#define REG_DR_SWF11 0x71414
+#define REG_DR_SWF12 0x71418
+#define REG_DR_SWF13 0x7141C
+#define REG_DR_SWF14 0x71420
+#define REG_DR_SWF15 0x71424
+#define REG_DR_SWF16 0x71428
+#define REG_DR_SWF17 0x7142C
+#define REG_DR_SWF18 0x71430
+#define REG_DR_SWF19 0x71434
+#define REG_DR_SWF1A 0x71438
+#define REG_DR_SWF1B 0x7143C
+#define REG_DR_SWF1C 0x71440
+#define REG_DR_SWF1D 0x71444
+#define REG_DR_SWF1E 0x71448
+#define REG_DR_SWF1F 0x7144C
+#define REG_DR_SWF30 0x72414
+#define REG_DR_SWF31 0x72418
+#define REG_DR_SWF32 0x7241C
+
+#define FORMAT_BGRX_16 0x5
+#define FORMAT_BGRX_32 0x6
+
+#endif
diff --git a/hw/x3100_vga.c b/hw/x3100_vga.c
new file mode 100644
index 0000000..31295e3
--- /dev/null
+++ b/hw/x3100_vga.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2008 Vincent Hanquez
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * QEMU Intel X3100 emulation
+ * VGA Part copied from vga.c, but different file to add later
+ * proper hooks to interact with the X3100 in VGA mode.
+ *
+ */
+#include "x3100.h"
+
+uint32_t x3100_vga_ioport_read(void *opaque, uint32_t addr)
+{
+ X3100State *s = opaque;
+ int v;
+ switch (addr) {
+ case 0x3c0: return (s->ar_flip_flop == 0) ? s->ar_index : 0;
+ case 0x3c1: return ((s->ar_index & 0x1f) < 21) ? s->ar[s->ar_index & 0x1f] : 0;
+ case 0x3c2: return s->st00;
+ case 0x3c4: return s->sr_index;
+ case 0x3c5: return s->sr[s->sr_index];
+ case 0x3c7: return s->dac_state;
+ case 0x3c8: return s->dac_write_index;
+ case 0x3c9:
+ v = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
+ if (++s->dac_sub_index == 3) {
+ s->dac_sub_index = 0; s->dac_read_index++;
+ }
+ return v;
+ case 0x3ca: return s->fcr;
+ case 0x3cc: return s->msr;
+ case 0x3ce: return s->gr_index;
+ case 0x3cf: return s->gr[s->gr_index];
+ case 0x3b4: case 0x3d4: return s->cr_index;
+ case 0x3b5: case 0x3d5: return s->cr[s->cr_index];
+ case 0x3ba: case 0x3da:
+ s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
+ v = s->st01;
+ s->ar_flip_flop = 0;
+ return v;
+ default:
+ printf("vga ioport R: %x\n", addr);
+ return 0xff;
+ }
+}
+
+void x3100_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ X3100State *s = opaque;
+ int index;
+
+ switch (addr) {
+ case 0x3c0:
+ if (s->ar_flip_flop == 0) {
+ val &= 0x3f;
+ s->ar_index = val;
+ } else {
+ index = s->ar_index & 0x1f;
+ switch (index) {
+ case 0x00 ... 0x0f:
+ s->ar[index] = val & 0x3f;
+ break;
+ case 0x10:
+ s->ar[index] = val & ~0x10;
+ break;
+ case 0x11:
+ s->ar[index] = val;
+ break;
+ case 0x12:
+ s->ar[index] = val & ~0xc0;
+ break;
+ case 0x13:
+ s->ar[index] = val & ~0xf0;
+ break;
+ case 0x14:
+ s->ar[index] = val & ~0xf0;
+ break;
+ default:
+ break;
+ }
+ }
+ s->ar_flip_flop ^= 1;
+ break;
+ case 0x3c2:
+ s->msr = val & ~0x10;
+ break;
+ case 0x3c4:
+ s->sr_index = val;
+ break;
+ case 0x3c5:
+ s->sr[s->sr_index] = val & sr_mask[s->sr_index];
+ break;
+ case 0x3c7:
+ s->dac_read_index = val;
+ s->dac_sub_index = 0;
+ s->dac_state = 3;
+ break;
+ case 0x3c8:
+ s->dac_write_index = val;
+ s->dac_sub_index = 0;
+ s->dac_state = 0;
+ break;
+ case 0x3c9:
+ s->dac_cache[s->dac_sub_index] = val;
+ if (++s->dac_sub_index == 3) {
+ memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
+ s->dac_sub_index = 0;
+ s->dac_write_index++;
+ }
+ break;
+ case 0x3ce:
+ s->gr_index = val;
+ break;
+ case 0x3cf:
+ s->gr[s->gr_index] = val & gr_mask[s->gr_index];
+ break;
+ case 0x3b4:
+ case 0x3d4:
+ s->cr_index = val;
+ break;
+ case 0x3b5:
+ case 0x3d5:
+ 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);
+ return;
+ }
+ switch (s->cr_index) {
+ case 0x01: /* horizontal display end */
+ case 0x07:
+ case 0x09:
+ case 0x0c:
+ case 0x0d:
+ case 0x12: /* vertical display end */
+ s->cr[s->cr_index] = val;
+ break;
+
+ default:
+ s->cr[s->cr_index] = val;
+ break;
+ }
+ break;
+ case 0x3ba:
+ case 0x3da:
+ s->fcr = val & 0x10;
+ break;
+ default:
+ printf("vga ioport W: %x:%x\n", addr, val);
+ }
+}
+
+static uint32_t x3100_vga_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+ X3100State *s = opaque;
+ return vga_mem_readb(s, addr);
+}
+
+static uint32_t x3100_vga_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = x3100_vga_mem_readb(opaque, addr) << 8;
+ v |= x3100_vga_mem_readb(opaque, addr + 1);
+#else
+ v = x3100_vga_mem_readb(opaque, addr);
+ v |= x3100_vga_mem_readb(opaque, addr + 1) << 8;
+#endif
+ return v;
+}
+
+static uint32_t x3100_vga_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = x3100_vga_mem_readb(opaque, addr) << 24;
+ v |= x3100_vga_mem_readb(opaque, addr + 1) << 16;
+ v |= x3100_vga_mem_readb(opaque, addr + 2) << 8;
+ v |= x3100_vga_mem_readb(opaque, addr + 3);
+#else
+ v = x3100_vga_mem_readb(opaque, addr);
+ v |= x3100_vga_mem_readb(opaque, addr + 1) << 8;
+ v |= x3100_vga_mem_readb(opaque, addr + 2) << 16;
+ v |= x3100_vga_mem_readb(opaque, addr + 3) << 24;
+#endif
+ return v;
+}
+
+static void x3100_vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ X3100State *s = opaque;
+ vga_mem_writeb(s, addr, val);
+ return;
+}
+
+static void x3100_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ x3100_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
+ x3100_vga_mem_writeb(opaque, addr + 1, val & 0xff);
+#else
+ x3100_vga_mem_writeb(opaque, addr, val & 0xff);
+ x3100_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+#endif
+}
+
+static void x3100_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ x3100_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
+ x3100_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
+ x3100_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
+ x3100_vga_mem_writeb(opaque, addr + 3, val & 0xff);
+#else
+ x3100_vga_mem_writeb(opaque, addr, val & 0xff);
+ x3100_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+ x3100_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+ x3100_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+#endif
+}
+
+CPUReadMemoryFunc *x3100_vga_mem_read[3] = {
+ x3100_vga_mem_readb, x3100_vga_mem_readw, x3100_vga_mem_readl,
+};
+
+CPUWriteMemoryFunc *x3100_vga_mem_write[3] = {
+ x3100_vga_mem_writeb, x3100_vga_mem_writew, x3100_vga_mem_writel,
+};
diff --git a/sysemu.h b/sysemu.h
index 0f18e04..fe6baf7 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -76,6 +76,8 @@ void do_info_slirp(void);
extern int ram_size;
extern int bios_size;
extern int cirrus_vga_enabled;
+extern int x3100_enabled;
+extern int x3100_debug;
extern int vmsvga_enabled;
extern int graphic_width;
extern int graphic_height;
diff --git a/vl.c b/vl.c
index 82f84db..b848873 100644
--- a/vl.c
+++ b/vl.c
@@ -183,6 +183,8 @@ int vm_running;
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
int cirrus_vga_enabled = 1;
+int x3100_enabled = 0;
+int x3100_debug = 0;
int vmsvga_enabled = 0;
#ifdef TARGET_SPARC
int graphic_width = 1024;
@@ -7713,6 +7715,7 @@ static void help(int exitcode)
#ifdef TARGET_I386
"-std-vga simulate a standard VGA card with VESA Bochs Extensions\n"
" (default is CL-GD5446 PCI VGA)\n"
+ "-x3100 simulate a x3100 graphic card\n"
"-no-acpi disable ACPI\n"
#endif
#ifdef CONFIG_CURSES
@@ -7805,6 +7808,8 @@ enum {
QEMU_OPTION_vmsvga,
QEMU_OPTION_g,
QEMU_OPTION_std_vga,
+ QEMU_OPTION_x3100,
+ QEMU_OPTION_x3100_debug,
QEMU_OPTION_echr,
QEMU_OPTION_monitor,
QEMU_OPTION_serial,
@@ -7904,6 +7909,8 @@ const QEMUOption qemu_options[] = {
#endif
{ "localtime", 0, QEMU_OPTION_localtime },
{ "std-vga", 0, QEMU_OPTION_std_vga },
+ { "x3100", 0, QEMU_OPTION_x3100 },
+ { "x3100-dbg", 0, QEMU_OPTION_x3100_debug },
{ "echr", HAS_ARG, QEMU_OPTION_echr },
{ "monitor", HAS_ARG, QEMU_OPTION_monitor },
{ "serial", HAS_ARG, QEMU_OPTION_serial },
@@ -8598,6 +8605,14 @@ int main(int argc, char **argv)
cirrus_vga_enabled = 0;
vmsvga_enabled = 0;
break;
+ case QEMU_OPTION_x3100:
+ cirrus_vga_enabled = 0;
+ x3100_enabled = 1;
+ vga_ram_size += X3100_RAM_SIZE;
+ break;
+ case QEMU_OPTION_x3100_debug:
+ x3100_debug = 1;
+ break;
case QEMU_OPTION_g:
{
const char *p;
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 194 bytes --]
^ permalink raw reply related [flat|nested] 4+ messages in thread