* [Qemu-devel] qemu X3100 project
@ 2008-03-20 19:32 Vincent Hanquez
2008-07-01 11:47 ` René Rebe
0 siblings, 1 reply; 8+ messages in thread
From: Vincent Hanquez @ 2008-03-20 19:32 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1738 bytes --]
Hello QEMU ML,
I'm please to announce my qemu x3100 project. The ultimate goal is fully
emulating an intel x3100 graphic card (also known as GMA965), to be able
to hopefully support 3D in qemu guests (and any user of qemu code base).
However, the emulation is not complete yet; This is a long task, and
lots of things need to be done, fixed and better integrated. I've
started a month and a half, and at this point I think it would be useful
to share it to the qemu mailing list, since it's got some basic features
done, maybe people will be interested in helping ;)
So what does works ?
- VGA mode :)
- linux - intel drv 2.2.1 - non accelerated (32 bits depth only)
- linux - intel drv 2.2.1 - XAA acceleration (32 bits depth only)
- linux - intel drv 2.2.1 - partial EXA (32 bits only)
(missing some text unfortunately see below)
So what doesn't works yet:
- Anything that's related to 3d.
- tiled surfaces.
- some text in EXA since driver is using 3d engine to do some 2d stuff.
- GART, only faked at the moment.
- Windows guests when using intel drivers.
- VESA emulation.
- better switch back to VGA mode (corrupted background color ATM).
if you want to try the card, just apply the patch in attachment,
recompile, and start qemu using your usual command line and adding
-x3100. make sure you are using a 32 bits color depth in your linux
guest, and by default Xorg Intel driver will use EXA; to switch to XAA,
add in your xorg.conf near the intel driver declaration:
Option "AccelMethod" "XAA"
There's a lots to be done, and the code need also cleanup (using correct
types, remove some ugly macros, remove bugs, etc), hence I appreciate
any encouragement, comments and/or patches ;)
--
Vincent
[-- Attachment #2: qemu-x3100.patch --]
[-- Type: text/x-diff, Size: 85703 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;
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] qemu X3100 project
2008-03-20 19:32 [Qemu-devel] qemu X3100 project Vincent Hanquez
@ 2008-07-01 11:47 ` René Rebe
2008-07-02 9:54 ` Vincent Hanquez
0 siblings, 1 reply; 8+ messages in thread
From: René Rebe @ 2008-07-01 11:47 UTC (permalink / raw)
To: qemu-devel, tab
Hi Vincent,
did you continue on this great undertaking? Maybe you have a new version
of the patch already implementing some more bits?
I specifically ask if you have a new version to avoid duplicate work, as I
consider getting into this to get smoother graphic for my Qemu VM
instances :-)
Yours,
René
Vincent Hanquez wrote:
> Hello QEMU ML,
>
> I'm please to announce my qemu x3100 project. The ultimate goal is fully
> emulating an intel x3100 graphic card (also known as GMA965), to be able
> to hopefully support 3D in qemu guests (and any user of qemu code base).
>
> However, the emulation is not complete yet; This is a long task, and
> lots of things need to be done, fixed and better integrated. I've
> started a month and a half, and at this point I think it would be useful
> to share it to the qemu mailing list, since it's got some basic features
> done, maybe people will be interested in helping ;)
>
> So what does works ?
> - VGA mode :)
> - linux - intel drv 2.2.1 - non accelerated (32 bits depth only)
> - linux - intel drv 2.2.1 - XAA acceleration (32 bits depth only)
> - linux - intel drv 2.2.1 - partial EXA (32 bits only)
> (missing some text unfortunately see below)
>
> So what doesn't works yet:
> - Anything that's related to 3d.
> - tiled surfaces.
> - some text in EXA since driver is using 3d engine to do some 2d stuff.
> - GART, only faked at the moment.
> - Windows guests when using intel drivers.
> - VESA emulation.
> - better switch back to VGA mode (corrupted background color ATM).
>
> if you want to try the card, just apply the patch in attachment,
> recompile, and start qemu using your usual command line and adding
> -x3100. make sure you are using a 32 bits color depth in your linux
> guest, and by default Xorg Intel driver will use EXA; to switch to XAA,
> add in your xorg.conf near the intel driver declaration:
>
> Option "AccelMethod" "XAA"
>
> There's a lots to be done, and the code need also cleanup (using correct
> types, remove some ugly macros, remove bugs, etc), hence I appreciate
> any encouragement, comments and/or patches ;)
>
--
René Rebe - ExactCODE GmbH - Europe, Germany, Berlin
http://exactcode.de | http://t2-project.org | http://rene.rebe.name
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] qemu X3100 project
2008-07-01 11:47 ` René Rebe
@ 2008-07-02 9:54 ` Vincent Hanquez
2008-07-02 11:13 ` Alexey Eremenko
0 siblings, 1 reply; 8+ messages in thread
From: Vincent Hanquez @ 2008-07-02 9:54 UTC (permalink / raw)
To: qemu-devel; +Cc: René Rebe
On Tue, Jul 01, 2008 at 01:47:01PM +0200, René Rebe wrote:
> Hi Vincent,
>
> did you continue on this great undertaking? Maybe you have a new version
> of the patch already implementing some more bits?
>
> I specifically ask if you have a new version to avoid duplicate work, as I
> consider getting into this to get smoother graphic for my Qemu VM
> instances :-)
Hi René,
i've got a slightly newer version; mainly with few bugfixes around
2d mode, a stubbed 3d instruction decoder.
however the main problem which i'm kind of stuck on, is the programmed
units (which is the most important 3d part), which involve having a
x3100 assembly decoder & interpreter. i don't believe this part is hard,
but the question is what to do with the instructions at this point :)
in the Intel driver, you can find thoses programs in file with
extensions g4a (assembly mnemonics) and g4b (encoded version).
anyhow, I can send you an updated version if you're interested, and i'll
be glad to discuss more about it (probably offlist to not bore qemu's people).
Cheers,
--
Vincent
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] qemu X3100 project
2008-07-02 9:54 ` Vincent Hanquez
@ 2008-07-02 11:13 ` Alexey Eremenko
2008-07-02 11:51 ` René Rebe
2008-07-02 14:54 ` Vincent Hanquez
0 siblings, 2 replies; 8+ messages in thread
From: Alexey Eremenko @ 2008-07-02 11:13 UTC (permalink / raw)
To: qemu-devel
That's very interesting undertaking indeed.
I always dreamt of playing 3D games in VMs. And I hope, that with the
help of your project, in may become a reality.
I don't know if it's possible to achieve good performance with
emulated 3D hardware - to the point where 3D games would run.
--
-Alexey Eromenko "Technologov"
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] qemu X3100 project
2008-07-02 11:13 ` Alexey Eremenko
@ 2008-07-02 11:51 ` René Rebe
2008-07-02 14:54 ` Vincent Hanquez
1 sibling, 0 replies; 8+ messages in thread
From: René Rebe @ 2008-07-02 11:51 UTC (permalink / raw)
To: qemu-devel
Alexey Eremenko wrote:
> That's very interesting undertaking indeed.
>
> I always dreamt of playing 3D games in VMs. And I hope, that with the
> help of your project, in may become a reality.
>
> I don't know if it's possible to achieve good performance with
> emulated 3D hardware - to the point where 3D games would run.
>
From the performance point of few I doubt it will yield performance to
run 3D games. For such "high-performance" demands some dedicated
"para-virtualized" direct 3D command passing would be required, there
already where some attempts to do so.
I'd like some decent emulated hardware nonetheless, mostly for OS
development, and probably for the nowadays common desktop 3D
effects that I hope the Intel GMA emulation could reach useful
performance.
Yours,
--
René Rebe - ExactCODE GmbH - Europe, Germany, Berlin
http://exactcode.de | http://t2-project.org | http://rene.rebe.nam
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] qemu X3100 project
2008-07-02 11:13 ` Alexey Eremenko
2008-07-02 11:51 ` René Rebe
@ 2008-07-02 14:54 ` Vincent Hanquez
2008-07-18 13:37 ` Alexander Graf
1 sibling, 1 reply; 8+ messages in thread
From: Vincent Hanquez @ 2008-07-02 14:54 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Eremenko
On Wed, Jul 02, 2008 at 02:13:35PM +0300, Alexey Eremenko wrote:
> That's very interesting undertaking indeed.
>
> I always dreamt of playing 3D games in VMs. And I hope, that with the
> help of your project, in may become a reality.
>
> I don't know if it's possible to achieve good performance with
> emulated 3D hardware - to the point where 3D games would run.
I can't predict about performance. I can't even predict about
the total feasibility to be honest.
Performance depends on how the 3d operations can be offloaded to actual
3d chips. for example, having a "translator" from the intel 3d operation
to OpenGL. or maybe something more feasible, to Gallium.
I'll open a public git repository based on my private one if people are
interested in working on the card emulation. however people should not
expect to be end-user (or testing) material anytime soon. not that i
want to scare people off ;)
Cheers,
--
Vincent
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] qemu X3100 project
2008-07-02 14:54 ` Vincent Hanquez
@ 2008-07-18 13:37 ` Alexander Graf
2008-07-20 19:20 ` Vincent Hanquez
0 siblings, 1 reply; 8+ messages in thread
From: Alexander Graf @ 2008-07-18 13:37 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Eremenko
On Jul 2, 2008, at 4:54 PM, Vincent Hanquez wrote:
> On Wed, Jul 02, 2008 at 02:13:35PM +0300, Alexey Eremenko wrote:
>> That's very interesting undertaking indeed.
>>
>> I always dreamt of playing 3D games in VMs. And I hope, that with the
>> help of your project, in may become a reality.
>>
>> I don't know if it's possible to achieve good performance with
>> emulated 3D hardware - to the point where 3D games would run.
>
> I can't predict about performance. I can't even predict about
> the total feasibility to be honest.
>
> Performance depends on how the 3d operations can be offloaded to
> actual
> 3d chips. for example, having a "translator" from the intel 3d
> operation
> to OpenGL. or maybe something more feasible, to Gallium.
>
> I'll open a public git repository based on my private one if people
> are
> interested in working on the card emulation. however people should not
> expect to be end-user (or testing) material anytime soon. not that i
> want to scare people off ;)
Could you please do that? I'd be really interested in getting to work
on that soon.
Thank you,
Alex
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] qemu X3100 project
2008-07-18 13:37 ` Alexander Graf
@ 2008-07-20 19:20 ` Vincent Hanquez
0 siblings, 0 replies; 8+ messages in thread
From: Vincent Hanquez @ 2008-07-20 19:20 UTC (permalink / raw)
To: qemu-devel; +Cc: Alexey Eremenko, René Rebe, Alexander Graf
On Fri, Jul 18, 2008 at 03:37:19PM +0200, Alexander Graf wrote:
> Could you please do that? I'd be really interested in getting to work on
> that soon.
>
> Thank you,
it's finally available at git://git.snarc.org/x3100.git
it's totally rebased on top of today's head, on top of qemu at
git://git.kernel.dk/qemu.git, so the x3100 history is gone (not really
interesting tho), but it's much easier for me to track newer versions.
sorry for the delay,
--
Vincent
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2008-07-20 19:21 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-20 19:32 [Qemu-devel] qemu X3100 project Vincent Hanquez
2008-07-01 11:47 ` René Rebe
2008-07-02 9:54 ` Vincent Hanquez
2008-07-02 11:13 ` Alexey Eremenko
2008-07-02 11:51 ` René Rebe
2008-07-02 14:54 ` Vincent Hanquez
2008-07-18 13:37 ` Alexander Graf
2008-07-20 19:20 ` Vincent Hanquez
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).