@@ -270,6 +270,7 @@ hw-obj-y += qdev-addr.o
hw-obj-$(CONFIG_VGA_PCI) += vga-pci.o
hw-obj-$(CONFIG_VGA_ISA) += vga-isa.o
hw-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o
+hw-obj-$(CONFIG_VGA_S3) += vga-s3.o
hw-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
hw-obj-$(CONFIG_VMMOUSE) += vmmouse.o
@@ -6,6 +6,7 @@ CONFIG_ISA_MMIO=y
CONFIG_ESCC=y
CONFIG_M48T59=y
CONFIG_VGA_PCI=y
+CONFIG_VGA_S3=y
CONFIG_SERIAL=y
CONFIG_PARALLEL=y
CONFIG_I8254=y
@@ -97,6 +97,9 @@
#define PCI_VENDOR_ID_FREESCALE 0x1957
#define PCI_DEVICE_ID_MPC8533E 0x0030
+#define PCI_VENDOR_ID_S3 0x5333
+#define PCI_DEVICE_ID_S3_864 0x88c0
+
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_INTEL_82378 0x0484
#define PCI_DEVICE_ID_INTEL_82441 0x1237
@@ -747,6 +747,8 @@ static void ibm_40p_init(ram_addr_t ram_size,
qdev_prop_set_uint8(&isa->qdev, "board-identification", 0xfc);
qdev_init_nofail(&isa->qdev);
+ pci_create_simple(pci_bus, PCI_DEVFN(2, 0), "S3-864");
+
/* Super I/O (parallel + serial ports) */
isa = isa_create("isa-pc87312");
qdev_prop_set_chr(&isa->qdev, "parallel", parallel_hds[0]);
new file mode 100644
@@ -0,0 +1,694 @@
+/*
+ * QEMU PCI IBM 8514/A Emulator.
+ *
+ * Copyright (c) 2010 Hervé Poussineau
+ * Copyright (c) 2010-2011 Andreas Färber
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* Documentation available at
+ * http://www.datasheetarchive.com/Indexer/Datasheet-06/DSA0091551.html
+ */
+
+#include "console.h"
+#include "pci.h"
+#include "vga_int.h"
+#include "pixel_ops.h"
+
+//#define DEBUG_8514
+//#define DEBUG_8514_IO
+
+#ifdef DEBUG_8514
+#define DPRINTF(fmt, ...) \
+do { printf("8514: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while (0)
+#endif
+#ifdef DEBUG_8514_IO
+#define DPRINTF_IO(fmt, ...) \
+do { printf("8514: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF_IO(fmt, ...) do {} while (0)
+#endif
+#define BADF(fmt, ...) \
+do { fprintf(stderr, "8514 ERROR: " fmt , ## __VA_ARGS__);} while (0)
+
+enum {
+ REG_CMD = 0x9AE8,
+ REG_PIX_TRANS = 0xE2E8,
+};
+
+#define GP_STAT_BUSY 0x0200
+
+#define CMD_WRTDATA 0x0001
+#define CMD_PLANAR 0x0002
+#define CMD_LASTPIX 0x0004
+#define CMD_LINETYPE 0x0008
+#define CMD_DRAW 0x0010
+#define CMD_INC_X 0x0020
+#define CMD_YMAJAXIS 0x0040
+#define CMD_INC_Y 0x0080
+#define CMD_PCDATA 0x0100
+#define CMD_16BIT 0x0200
+#define CMD_BYTSEQ 0x1000
+#define CMD_CMD_MASK 0xE000
+
+#define CMD_CMD_NOP 0x0000
+#define CMD_CMD_LINE 0x2000
+#define CMD_CMD_RECT 0x4000
+#define CMD_CMD_RECTV1 0x6000
+#define CMD_CMD_RECTV2 0x8000
+#define CMD_CMD_LINEAF 0xA000
+#define CMD_CMD_BITBLT 0xC000
+
+#define BKGD_MIX_BSS_MASK 0x0060
+enum {
+ BKGD_MIX_BSS_BKGD = 0x0000,
+ BKGD_MIX_BSS_FRGD = 0x0020,
+ BKGD_MIX_BSS_PIX = 0x0040,
+ BKGD_MIX_BSS_BMP = 0x0060,
+};
+
+#define FRGD_MIX_FSS_MASK 0x0060
+enum {
+ FRGD_MIX_FSS_BKGD = 0x0000,
+ FRGD_MIX_FSS_FRGD = 0x0020,
+ FRGD_MIX_FSS_PIX = 0x0040,
+ FRGD_MIX_FSS_BMP = 0x0060,
+};
+
+#define PIX_CNTL_MIXSEL_MASK 0x00C0
+enum {
+ PIX_CNTL_MIXSEL_FOREMIX = 0x0000,
+ PIX_CNTL_MIXSEL_PATTERN = 0x0040,
+ PIX_CNTL_MIXSEL_VAR = 0x0080,
+ PIX_CNTL_MIXSEL_TRANS = 0x00C0,
+};
+
+// 40f3 = CMD_CMD_RECT | CMD_INC_Y | CMD_YMAJAXIS | CMD_INC_X | CMD_DRAW | CMD_PLANAR | CMD_WRTDATA
+// 4331 = CMD_CMD_RECT | CMD_16BIT | CMD_PCDATA | CMD_INC_X | CMD_DRAW | CMD_WRTDATA
+// c0b3 = CMD_CMD_BITBLT | CMD_INC_Y | CMD_INC_X | CMD_DRAW | CMD_PLANAR | CMD_WRTDATA
+
+typedef struct IBM8514State {
+ VGACommonState vga;
+ uint16_t maj_axis, min_axis;
+
+ uint16_t disp_stat; /* 02e8 */
+ uint16_t h_disp; /* 06e8 */
+ uint16_t h_sync_strt; /* 0ae8 */
+ uint16_t h_sync_wid; /* 0ee8 */
+ uint16_t v_total; /* 12e8 */
+ uint16_t v_disp; /* 16e8 */
+ uint16_t v_sync_strt; /* 1ae8 */
+ uint16_t v_sync_wid; /* 1ee8 */
+ uint16_t disp_cntl; /* 22e8 */
+ uint16_t h_total; /* 26e8 */
+ uint16_t subsys_cntl; /* 42e8 (W) */
+ uint16_t subsys_stat; /* 42e8 (R) */
+ uint16_t rom_page_sel; /* 46e8 */
+ uint16_t advfunc_cntl; /* 4ae8 */
+ uint16_t cur_y; /* 82e8 */
+ uint16_t cur_x; /* 86e8 */
+ uint16_t desty_axstep; /* 8ae8 */
+ uint16_t destx_diastp; /* 8ee8 */
+ uint16_t err_term; /* 92e8 */
+ uint16_t maj_axis_pcnt; /* 96e8 */
+ uint16_t gp_stat; /* 9ae8 (R) */
+ uint16_t cmd; /* 9ae8 (W) */
+ uint16_t short_stroke; /* 9ee8 */
+ uint16_t bkgd_color; /* a2e8 */
+ uint16_t frgd_color; /* a6e8 */
+ uint16_t wrt_mask; /* aae8 */
+ uint16_t rd_mask; /* aee8 */
+ uint16_t color_cmp; /* b2e8 */
+ uint16_t bkgd_mix; /* b6e8 */
+ uint16_t frgd_mix; /* bae8 */
+ uint16_t mfc[16]; /* bee8 */
+ uint16_t pix_trans; /* e2e8 */
+} IBM8514State;
+
+#define min_axis_pcnt mfc[0]
+#define scissors_t mfc[1]
+#define scissors_l mfc[2]
+#define scissors_b mfc[3]
+#define scissors_r mfc[4]
+#define mem_cntl mfc[5]
+#define pattern_l mfc[8]
+#define pattern_h mfc[9]
+#define pix_cntl mfc[10]
+
+static inline void do_cmd_done(IBM8514State *s)
+{
+ s->gp_stat &= ~GP_STAT_BUSY;
+}
+
+static void do_cmd_write_pixel(IBM8514State *s, uint16_t value)
+{
+ uint16_t maj_axis_pcnt = s->maj_axis_pcnt + 1;
+ uint8_t* p8 = s->vga.vram_ptr + (s->cur_y * 640 + s->cur_x) * 4;
+ int dx = s->cmd & CMD_INC_X ? 1 : -1;
+ int dy = s->cmd & CMD_INC_Y ? 1 : -1;
+
+ if (!(s->gp_stat & GP_STAT_BUSY)) {
+ return;
+ }
+
+ ++s->maj_axis;
+ if ((s->maj_axis < maj_axis_pcnt) ||
+ (s->maj_axis == maj_axis_pcnt && !(s->cmd & CMD_LASTPIX))) {
+ p8[0] = p8[1] = p8[2] = p8[3] = value;
+ }
+ if (s->maj_axis < maj_axis_pcnt) {
+ s->cur_x += dx;
+ } else if (s->maj_axis == maj_axis_pcnt) {
+ if ((maj_axis_pcnt % 2 == 0) || !(s->cmd & CMD_16BIT)) {
+ s->maj_axis = 0;
+ }
+ s->cur_x -= (s->maj_axis_pcnt) * dx;
+ s->cur_y += dy;
+ s->min_axis++;
+ if (s->min_axis == s->min_axis_pcnt + 1) {
+ do_cmd_done(s);
+ }
+ } else {
+ //DPRINTF("%s: (skip - maj_axis = %u, maj_axis_pcnt = %u)\n",
+ // __func__, s->maj_axis, maj_axis_pcnt);
+ s->maj_axis = 0;
+ }
+}
+
+static uint16_t get_source_operand(IBM8514State *s)
+{
+ switch (s->pix_cntl & PIX_CNTL_MIXSEL_MASK) {
+ case PIX_CNTL_MIXSEL_FOREMIX:
+ switch (s->frgd_mix & FRGD_MIX_FSS_MASK) {
+ case FRGD_MIX_FSS_BKGD:
+ return s->bkgd_color & 0xff;
+ case FRGD_MIX_FSS_FRGD:
+ return s->frgd_color & 0xff;
+ default:
+ BADF("%s: Unimplemented FSS %x\n",
+ __func__, (s->frgd_mix & FRGD_MIX_FSS_MASK) >> 5);
+ return 0;
+ }
+ default:
+ BADF("%s: Unimplemented MIXSEL %x\n",
+ __func__, (s->pix_cntl & PIX_CNTL_MIXSEL_MASK) >> 6);
+ return 0;
+ }
+}
+
+static void do_cmd_init(IBM8514State *s)
+{
+ s->gp_stat |= GP_STAT_BUSY;
+ s->maj_axis = 0;
+ s->min_axis = 0;
+
+ if ((s->cmd & CMD_CMD_MASK) == CMD_CMD_RECT) {
+ DPRINTF("cmd RECT: cur_x=%d cur_y=%d inc_x=%d inc_y=%d width=%d height=%d\n",
+ s->cur_x, s->cur_y,
+ s->cmd & CMD_INC_X ? 1 : -1, s->cmd & CMD_INC_Y ? 1 : -1,
+ s->maj_axis_pcnt, s->min_axis_pcnt);
+
+ if (!(s->cmd & CMD_PCDATA)) {
+ while (s->gp_stat & GP_STAT_BUSY) {
+ do_cmd_write_pixel(s, get_source_operand(s));
+ }
+ }
+ }
+}
+
+static void do_cmd(IBM8514State *s)
+{
+ DPRINTF("%s: execute cmd %04x\n", __func__, s->cmd);
+
+ do_cmd_init(s);
+}
+
+static uint16_t* ibm8514_get_register(IBM8514State *s, uint32_t addr, int is_write, uint32_t* val_if_write)
+{
+ uint16_t *p;
+
+ switch (addr) {
+ case 0x02e8:
+ p = is_write ? &s->h_total : &s->disp_stat;
+ break;
+ case 0x06e8:
+ p = is_write ? &s->h_disp : NULL;
+ break;
+ case 0x0ae8:
+ p = is_write ? &s->h_sync_strt : NULL;
+ break;
+ case 0x0ee8:
+ p = is_write ? &s->h_sync_wid : NULL;
+ break;
+ case 0x12e8:
+ p = is_write ? &s->v_total : NULL;
+ break;
+ case 0x16e8:
+ p = is_write ? &s->v_disp : NULL;
+ break;
+ case 0x1ae8:
+ p = is_write ? &s->v_sync_strt : NULL;
+ break;
+ case 0x1ee8:
+ p = is_write ? &s->v_sync_wid : NULL;
+ break;
+ case 0x22e8:
+ p = is_write ? &s->disp_cntl : NULL;
+ break;
+ case 0x26e8:
+ p = is_write ? NULL: &s->h_total;
+ break;
+ case 0x42e8:
+ p = is_write ? &s->subsys_cntl : &s->subsys_stat;
+ break;
+ case 0x46e8:
+ p = is_write ? &s->rom_page_sel : NULL;
+ break;
+ case 0x4ae8:
+ p = is_write ? &s->advfunc_cntl : NULL;
+ break;
+ case 0x82e8:
+ p = &s->cur_y;
+ break;
+ case 0x86e8:
+ p = &s->cur_x;
+ break;
+ case 0x8ae8:
+ p = is_write ? &s->desty_axstep : NULL;
+ break;
+ case 0x8ee8:
+ p = is_write ? &s->destx_diastp : NULL;
+ break;
+ case 0x92e8:
+ p = &s->err_term;
+ break;
+ case 0x96e8:
+ p = is_write ? &s->maj_axis_pcnt : NULL;
+ break;
+ case 0x9ae8:
+ p = is_write ? &s->cmd : &s->gp_stat;
+ break;
+ case 0x9ee8:
+ p = is_write ? &s->short_stroke : NULL;
+ break;
+ case 0xa2e8:
+ p = is_write ? &s->bkgd_color : NULL;
+ break;
+ case 0xa6e8:
+ p = is_write ? &s->frgd_color : NULL;
+ break;
+ case 0xaae8:
+ p = is_write ? &s->wrt_mask : NULL;
+ break;
+ case 0xaee8:
+ p = is_write ? &s->rd_mask : NULL;
+ break;
+ case 0xb2e8:
+ p = is_write ? &s->color_cmp : NULL;
+ break;
+ case 0xb6e8:
+ p = is_write ? &s->bkgd_mix : NULL;
+ break;
+ case 0xbae8:
+ p = is_write ? &s->frgd_mix : NULL;
+ break;
+ case 0xbee8:
+ if (is_write) {
+ p = &s->mfc[(*val_if_write >> 12) & 0xf];
+ *val_if_write &= 0x0fff;
+ } else {
+ p = NULL;
+ }
+ break;
+ case 0xe2e8:
+ p = &s->pix_trans;
+ break;
+ default:
+ BADF("%s: invalid register at 0x%x\n", __func__, addr);
+ p = NULL;
+ break;
+ }
+
+ return p;
+}
+
+static uint32_t ibm8514_ioport_readb(void *opaque, uint32_t addr)
+{
+ IBM8514State *s = opaque;
+ uint32_t val;
+ uint16_t *p;
+
+ p = ibm8514_get_register(s, addr & ~0x1, 0, NULL);
+
+ if (p) {
+ val = (be16_to_cpu(*p) >> ((~addr & 1) * 8)) & 0xff;
+ } else {
+ val = 0;
+ }
+
+ DPRINTF_IO("%s: read %x at %x\n", __func__, val, addr);
+ return val;
+}
+
+static uint32_t ibm8514_ioport_readw(void *opaque, uint32_t addr)
+{
+ IBM8514State *s = opaque;
+ uint32_t val;
+ uint16_t *p;
+
+ p = ibm8514_get_register(s, addr, 0, NULL);
+
+ if (p) {
+ val = be16_to_cpu(*p);
+ } else {
+ val = 0;
+ }
+
+ DPRINTF_IO("%s: read %x at %x\n", __func__, val, addr);
+ return val;
+}
+
+static void ibm8514_ioport_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ IBM8514State *s = opaque;
+ uint16_t *p;
+ uint8_t *c;
+
+ DPRINTF_IO("%s: write %x at %x\n", __func__, val, addr);
+ p = ibm8514_get_register(s, addr & ~0x1, 1, &val);
+
+ if (p) {
+ c = (uint8_t*)p;
+ c[~addr & 1] = val;
+ }
+ if ((addr & ~0x1) == REG_CMD) {
+ do_cmd(s);
+ } else if ((addr & ~0x1) == REG_PIX_TRANS) {
+ BADF("%s: ibm8514: 8-byte PIX_TRANS access (0x%08" PRIx32 ")\n",
+ __func__, addr);
+ }
+}
+
+static void ibm8514_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+ IBM8514State *s = opaque;
+ uint16_t *p;
+
+ val = cpu_to_be16(val);
+ DPRINTF_IO("%s: write %x at %x\n", __func__, val, addr);
+ p = ibm8514_get_register(s, addr, 1, &val);
+
+ if (p) {
+ *p = val & 0xffff;
+ }
+ if (addr == REG_CMD) {
+ do_cmd(s);
+ } else if (addr == REG_PIX_TRANS) {
+ if (!(s->cmd & CMD_16BIT)) {
+ do_cmd_write_pixel(s, val & 0xff);
+ } else if (s->cmd & CMD_BYTSEQ) {
+ do_cmd_write_pixel(s, val & 0xff);
+ do_cmd_write_pixel(s, val >> 8);
+ } else {
+ do_cmd_write_pixel(s, val >> 8);
+ do_cmd_write_pixel(s, val & 0xff);
+ }
+ }
+}
+
+static void ibm8514_register_port_one(IBM8514State *s, uint32_t addr)
+{
+ register_ioport_read(addr, 1, 1, ibm8514_ioport_readb, s);
+ register_ioport_write(addr, 1, 1, ibm8514_ioport_writeb, s);
+}
+
+static void ibm8514_register_port(IBM8514State *s, uint32_t addr)
+{
+ register_ioport_read(addr, 2, 1, ibm8514_ioport_readb, s);
+ register_ioport_read(addr, 1, 2, ibm8514_ioport_readw, s);
+ register_ioport_write(addr, 2, 1, ibm8514_ioport_writeb, s);
+ register_ioport_write(addr, 1, 2, ibm8514_ioport_writew, s);
+}
+
+static void my_update_display(void *opaque)
+{
+ VGACommonState *s = opaque;
+ int w;
+ uint8_t *vram;
+ uint8_t *data_display, *dd;
+ int x, y;
+ unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned int b);
+
+ if (ds_get_width(s->ds) != 640 || ds_get_height(s->ds) != 480) {
+ qemu_console_resize(s->ds, 640, 480);
+ }
+
+ switch (ds_get_bits_per_pixel(s->ds)) {
+ case 8:
+ rgb_to_pixel = rgb_to_pixel8;
+ w = 1;
+ break;
+ case 15:
+ rgb_to_pixel = rgb_to_pixel15;
+ w = 2;
+ break;
+ case 16:
+ rgb_to_pixel = rgb_to_pixel16;
+ w = 2;
+ break;
+ case 32:
+ rgb_to_pixel = rgb_to_pixel32;
+ w = 4;
+ break;
+ default:
+ BADF("unknown host depth %d\n", ds_get_bits_per_pixel(s->ds));
+ return;
+ }
+
+ vram = s->vram_ptr;
+ /* XXX: out of range in vram? */
+ data_display = dd = ds_get_data(s->ds);
+ for (y = 0; y < 480; y++) {
+ for (x = 0; x < 640; x++) {
+ unsigned int color;
+ color = (*rgb_to_pixel)(vram[0], vram[1], vram[2]);
+ memcpy(dd, &color, w);
+ dd += w;
+ vram += 4;
+ }
+ data_display = dd = data_display + ds_get_linesize(s->ds);
+ }
+
+ dpy_update(s->ds, 0, 0, 640, 480);
+}
+
+static void ibm8514_init(IBM8514State *s)
+{
+ VGACommonState *vga = &s->vga;
+
+ vga->vram_size = 0x200000;
+
+ /* vga + console init */
+ vga_common_init(vga, vga->vram_size);
+ vga_init(vga);
+
+ vga->ds = graphic_console_init(/*vga->update*/my_update_display, vga->invalidate,
+ vga->screen_dump, vga->text_update,
+ vga);
+
+ ibm8514_register_port(s, 0x02e8);
+ ibm8514_register_port_one(s, 0x02ea);
+ ibm8514_register_port_one(s, 0x02eb);
+ ibm8514_register_port_one(s, 0x02ec);
+ ibm8514_register_port_one(s, 0x02ed);
+ ibm8514_register_port(s, 0x06e8);
+ ibm8514_register_port(s, 0x0ae8);
+ ibm8514_register_port(s, 0x0ee8);
+ ibm8514_register_port(s, 0x12e8);
+ ibm8514_register_port(s, 0x16e8);
+ ibm8514_register_port(s, 0x1ae8);
+ ibm8514_register_port(s, 0x1ee8);
+ ibm8514_register_port(s, 0x22e8);
+ ibm8514_register_port(s, 0x26e8);
+ ibm8514_register_port(s, 0x42e8);
+ ibm8514_register_port(s, 0x46e8);
+ ibm8514_register_port(s, 0x4ae8);
+ ibm8514_register_port(s, 0x82e8);
+ ibm8514_register_port(s, 0x86e8);
+ ibm8514_register_port(s, 0x8ae8);
+ ibm8514_register_port(s, 0x8ee8);
+ ibm8514_register_port(s, 0x92e8);
+ ibm8514_register_port(s, 0x96e8);
+ ibm8514_register_port(s, 0x9ae8);
+ ibm8514_register_port(s, 0x9ae8);
+ ibm8514_register_port(s, 0x9ee8);
+ ibm8514_register_port(s, 0xa2e8);
+ ibm8514_register_port(s, 0xa6e8);
+ ibm8514_register_port(s, 0xaae8);
+ ibm8514_register_port(s, 0xaee8);
+ ibm8514_register_port(s, 0xb2e8);
+ ibm8514_register_port(s, 0xb6e8);
+ ibm8514_register_port(s, 0xbae8);
+ ibm8514_register_port(s, 0xbee8);
+ ibm8514_register_port(s, 0xe2e8);
+
+ cpu_register_physical_memory(isa_mem_base + 0x02800000, vga->vram_size, vga->vram_offset);
+ qemu_register_coalesced_mmio(isa_mem_base + 0x02800000, vga->vram_size);
+}
+
+typedef struct PCIIBM8514State {
+ PCIDevice dev;
+ IBM8514State state;
+} PCIIBM8514State;
+
+static void pci_ibm8514_write_config(PCIDevice *d,
+ uint32_t address, uint32_t val, int len)
+{
+ BADF("%s: 0x%08" PRIx32 "\n", __func__, address);
+}
+
+static int pci_ibm8514_init(PCIDevice *dev)
+{
+ PCIIBM8514State *pci = DO_UPCAST(PCIIBM8514State, dev, dev);
+ IBM8514State *s = &pci->state;
+ uint8_t *pci_conf = dev->config;
+
+ DPRINTF("%s\n", __func__);
+
+ pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_S3);
+ pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_S3_864);
+ pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
+
+ ibm8514_init(s);
+
+ return 0;
+}
+
+static PCIDeviceInfo ibm8514_info = {
+ .qdev.name = "S3-864",
+ .qdev.size = sizeof(PCIIBM8514State),
+ //.qdev.vmsd = &vmstate_ibm8514_pci,
+ .init = pci_ibm8514_init,
+ .config_write = pci_ibm8514_write_config,
+ .qdev.props = (Property[]) {
+ //DEFINE_PROP_HEX32("bios-offset", PCIVGAState, state.bios_offset, 0),
+ //DEFINE_PROP_HEX32("bios-size", PCIVGAState, state.bios_size, 0),
+ DEFINE_PROP_END_OF_LIST()
+ }
+};
+
+static void ibm8514_register(void)
+{
+ pci_qdev_register(&ibm8514_info);
+}
+
+device_init(ibm8514_register);
+
+/*
+21:
+ DEVICE_ID
+ BusId = PCI
+ DevId = 0x41d00909 (PNP0909)
+ SerialNum = 0x00000000
+ Flags = 0x000061c5
+ : Output
+ : ConsoleOut
+ : PowerManaged
+ : Disableable
+ : Configurable
+ : Integrated
+ : Enabled
+ BaseType = DisplayController (3)
+ SubType = SVGAController (1)
+ Interface = GeneralSVGA (0)
+ BUS_ACCESS
+ info0 = 0
+ info1 = 112
+ AllocatedOffset = 0x00000767
+ IRQ: 15
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x102 size 0x1 bytes
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x3b4 size 0x2 bytes
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x3b8 size 0x4 bytes
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x3bf size 0xc bytes
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x3cc size 0x1 bytes
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x3ce size 0x2 bytes
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x3d4 size 0x2 bytes
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x3d8 size 0x5 bytes
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x42e8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x46e8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x4ae8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x82e8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x86e8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x8ae8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x8ee8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x92e8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x96e8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x9ae8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0x9ee8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0xa2e8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0xa6e8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0xaae8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0xaee8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0xb2e8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0xb6e8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0xbae8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0xbee8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0xe2e8 size 0x1 bytes ok
+ LargeVendorItem: Generic Address
+ I/O address (32 bits), at 0xe2ea size 0x1 bytes
+ LargeVendorItem: Generic Address
+ Memory address (32 bits), at 0x2800000 size 0x200000 bytes ok
+ LargeVendorItem: Display
+ 01 00 80 02 e0 01 80 02 00 00 80 c2 00 00 00 00
+ 00 00 20 00 00 00 00 00 78
+ PossibleOffset = 0x00000a58
+ CompatibleOffset = 0x00000a59
+
+*/
The IBM E15 is equivalent to an S3 Vision864. Lacking S3 SDAC (86C716) support, the DAC indizes are translated to greyscale colors. This works sufficiently to observe firmware boot progress. Cc: Hervé Poussineau <hpoussin@reactos.org> Fixed off-by-one drawing issue. Replaced hardcoded color for RECT. Separate I/O debug output for readability. Signed-off-by: Andreas Färber <andreas.faerber@web.de> --- Makefile.objs | 1 + default-configs/ppc-softmmu.mak | 1 + hw/pci_ids.h | 3 + hw/ppc_prep.c | 2 + hw/vga-s3.c | 694 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 701 insertions(+), 0 deletions(-) create mode 100644 hw/vga-s3.c