qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "C.W. Betts" <computers57@hotmail.com>
To: Chris Gregan <chris.gregan@canonical.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] xserver-xorg-video-intel
Date: Fri, 28 Mar 2008 11:06:39 -0600	[thread overview]
Message-ID: <BAY110-DAV134F0DC571857FB5824031B9F90@phx.gbl> (raw)
Message-ID: <200803281106.59074.computers57@hotmail.com> (raw)
In-Reply-To: <47EBF216.2080101@canonical.com>


[-- 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 --]

      reply	other threads:[~2008-03-28 17:07 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-26 21:01 [Qemu-devel] xserver-xorg-video-intel Chris Gregan
     [not found] ` <200803262146.23498.computers57@hotmail.com>
2008-03-27  3:36   ` C.W. Betts
2008-03-27 19:14     ` Chris Gregan
     [not found]       ` <200803281106.59074.computers57@hotmail.com>
2008-03-28 17:06         ` C.W. Betts [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=BAY110-DAV134F0DC571857FB5824031B9F90@phx.gbl \
    --to=computers57@hotmail.com \
    --cc=chris.gregan@canonical.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).