qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [RFC v2 23/23] 40p: Add an IBM 8514/A graphics card


From: Blue Swirl
Subject: Re: [Qemu-devel] [RFC v2 23/23] 40p: Add an IBM 8514/A graphics card
Date: Sat, 18 Jun 2011 23:42:44 +0300

On Thu, Jun 16, 2011 at 3:02 AM, Andreas Färber <address@hidden> wrote:
> 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 <address@hidden>
>
> Fixed off-by-one drawing issue.
> Replaced hardcoded color for RECT.
> Separate I/O debug output for readability.
> Start cleaning up the naming s3 vs. ibm8514.
> Prepare support for DAC_MASK, DAC_R_INDEX, DAC_W_INDEX, DAC_DATA regs.
>
> Cc: Roy Tam <address@hidden>
> Signed-off-by: Andreas Färber <address@hidden>
> ---
>  Makefile.objs                   |    1 +
>  default-configs/ppc-softmmu.mak |    1 +
>  hw/pci_ids.h                    |    3 +
>  hw/ppc_prep.c                   |    2 +
>  hw/vga-ibm8514.c                |  780 
> +++++++++++++++++++++++++++++++++++++++
>  5 files changed, 787 insertions(+), 0 deletions(-)
>  create mode 100644 hw/vga-ibm8514.c
>
> diff --git a/Makefile.objs b/Makefile.objs
> index 7ceeee5..95dcd91 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -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_IBM8514) += vga-ibm8514.o
>  hw-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
>  hw-obj-$(CONFIG_VMMOUSE) += vmmouse.o
>
> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> index 303929f..f9c97b7 100644
> --- a/default-configs/ppc-softmmu.mak
> +++ b/default-configs/ppc-softmmu.mak
> @@ -6,6 +6,7 @@ CONFIG_ISA_MMIO=y
>  CONFIG_ESCC=y
>  CONFIG_M48T59=y
>  CONFIG_VGA_PCI=y
> +CONFIG_VGA_IBM8514=y
>  CONFIG_SERIAL=y
>  CONFIG_PARALLEL=y
>  CONFIG_I8254=y
> diff --git a/hw/pci_ids.h b/hw/pci_ids.h
> index d3bef0e..821421c 100644
> --- a/hw/pci_ids.h
> +++ b/hw/pci_ids.h
> @@ -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
> diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
> index 6ae1635..c215b0f 100644
> --- a/hw/ppc_prep.c
> +++ b/hw/ppc_prep.c
> @@ -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-vision864");
> +
>     /* Super I/O (parallel + serial ports) */
>     isa = isa_create("isa-pc87312");
>     qdev_prop_set_chr(&isa->qdev, "parallel", parallel_hds[0]);
> diff --git a/hw/vga-ibm8514.c b/hw/vga-ibm8514.c
> new file mode 100644
> index 0000000..a87afe1
> --- /dev/null
> +++ b/hw/vga-ibm8514.c
> @@ -0,0 +1,780 @@
> +/*
> + * 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

C89 comments?

> +
> +typedef struct IBM8514State {
> +    VGACommonState vga;
> +    uint16_t maj_axis, min_axis;
> +
> +    uint8_t dac_mask; /* 02ea */
> +    uint8_t dac_r_index; /* 02eb */
> +    uint8_t dac_w_index; /* 02ec */
> +    uint8_t dac_state[4];
> +
> +    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 dac_byte dac_state[3]
> +
> +#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 VMStateDescription vmstate_ibm8514 = {
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField []) {
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> +
> +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 uint32_t ibm8514_ramdac_ioport_readb(void *opaque, uint32_t addr)
> +{
> +    IBM8514State *s = opaque;
> +    uint32_t val;
> +
> +    switch (addr) {
> +        case 0x02ea:
> +            val = s->dac_mask;
> +            break;
> +        case 0x02eb:
> +            val = s->dac_r_index;
> +            break;
> +        case 0x02ec:
> +            val = s->dac_w_index;
> +            break;
> +        case 0x02ed:
> +            if (s->dac_byte == 0) {
> +                // XXX load dac_state[0-2] from palette
> +            }
> +            val = s->dac_state[s->dac_byte];
> +            s->dac_byte = (s->dac_byte + 1) % 3;
> +            if (s->dac_byte == 0) {
> +                s->dac_r_index++;
> +                s->dac_w_index++;
> +            }
> +            break;
> +        default:
> +            BADF("%s: invalid register at 0x%04x\n", __func__, addr);
> +            val = 0;
> +            break;
> +    }
> +    DPRINTF_IO("%s: read %02x at %04x\n", __func__, val, addr);
> +    return val;
> +}
> +
> +static void ibm8514_ramdac_ioport_writeb(void *opaque, uint32_t addr, 
> uint32_t val)
> +{
> +    IBM8514State *s = opaque;
> +
> +    DPRINTF_IO("%s: write %02x at %04x\n", __func__, val, addr);
> +    switch (addr) {
> +        case 0x02ea:
> +            s->dac_mask = val & 0xff;
> +            break;
> +        case 0x02eb:
> +            s->dac_r_index = val & 0xff;
> +            s->dac_byte = 0;
> +            break;
> +        case 0x02ec:
> +            s->dac_w_index = val & 0xff;
> +            s->dac_byte = 0;
> +            break;
> +        case 0x02ed:
> +            s->dac_state[s->dac_byte] = val & 0xff;
> +            s->dac_byte = (s->dac_byte + 1) % 3;
> +            if (s->dac_byte == 0) {
> +                // XXX store s->dac_state[0-2] to palette
> +                s->dac_r_index++;
> +                s->dac_w_index++;
> +            }
> +            break;
> +        default:
> +            BADF("%s: invalid register at 0x%04x\n", __func__, addr);
> +            break;
> +    }
> +}
> +
> +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_ramdac_port(IBM8514State *s, uint32_t addr)
> +{
> +    register_ioport_read(addr, 1, 1, ibm8514_ramdac_ioport_readb, s);
> +    register_ioport_write(addr, 1, 1, ibm8514_ramdac_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);

Please take a look at tcx.c for a 8 bit mode frame buffer with palette
translation. Also VGA_DIRTY bit handling should be added to this loop
to speed it up.

> +            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_ramdac_port(s, 0x02ea);
> +    ibm8514_register_ramdac_port(s, 0x02eb);
> +    ibm8514_register_ramdac_port(s, 0x02ec);
> +    ibm8514_register_ramdac_port(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 s3_vision864_write_config(PCIDevice *d,
> +                                      uint32_t address, uint32_t val, int 
> len)
> +{
> +    BADF("%s: 0x%08" PRIx32 "\n", __func__, address);
> +}
> +
> +static int s3_vision864_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 s3_vision864_info = {
> +    .qdev.name    = "s3-vision864",
> +    .qdev.size    = sizeof(PCIIBM8514State),
> +    .qdev.vmsd    = &vmstate_ibm8514,
> +    // XXX these depend on mst's PCI tree
> +#if 0
> +    .vendor_id    = PCI_VENDOR_ID_S3,
> +    .device_id    = PCI_DEVICE_ID_S3_864,
> +    .class_id     = PCI_CLASS_DISPLAY_VGA,
> +#endif
> +    .init         = s3_vision864_init,
> +    .config_write = s3_vision864_write_config,
> +    .qdev.props   = (Property[]) {
> +        DEFINE_PROP_END_OF_LIST()
> +    },
> +};
> +
> +static void ibm8514_register(void)
> +{
> +    pci_qdev_register(&s3_vision864_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
> +
> +*/
> --
> 1.7.5.3
>
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]