qemu/hw/display/ati.c
<<
>>
Prefs
   1/*
   2 * QEMU ATI SVGA emulation
   3 *
   4 * Copyright (c) 2019 BALATON Zoltan
   5 *
   6 * This work is licensed under the GNU GPL license version 2 or later.
   7 */
   8
   9/*
  10 * WARNING:
  11 * This is very incomplete and only enough for Linux console and some
  12 * unaccelerated X output at the moment.
  13 * Currently it's little more than a frame buffer with minimal functions,
  14 * other more advanced features of the hardware are yet to be implemented.
  15 * We only aim for Rage 128 Pro (and some RV100) and 2D only at first,
  16 * No 3D at all yet (maybe after 2D works, but feel free to improve it)
  17 */
  18
  19#include "qemu/osdep.h"
  20#include "ati_int.h"
  21#include "ati_regs.h"
  22#include "vga_regs.h"
  23#include "qemu/log.h"
  24#include "qemu/module.h"
  25#include "qemu/error-report.h"
  26#include "qapi/error.h"
  27#include "hw/hw.h"
  28#include "ui/console.h"
  29#include "hw/display/i2c-ddc.h"
  30#include "trace.h"
  31
  32#define ATI_DEBUG_HW_CURSOR 0
  33
  34static const struct {
  35    const char *name;
  36    uint16_t dev_id;
  37} ati_model_aliases[] = {
  38    { "rage128p", PCI_DEVICE_ID_ATI_RAGE128_PF },
  39    { "rv100", PCI_DEVICE_ID_ATI_RADEON_QY },
  40};
  41
  42enum { VGA_MODE, EXT_MODE };
  43
  44static void ati_vga_switch_mode(ATIVGAState *s)
  45{
  46    DPRINTF("%d -> %d\n",
  47            s->mode, !!(s->regs.crtc_gen_cntl & CRTC2_EXT_DISP_EN));
  48    if (s->regs.crtc_gen_cntl & CRTC2_EXT_DISP_EN) {
  49        /* Extended mode enabled */
  50        s->mode = EXT_MODE;
  51        if (s->regs.crtc_gen_cntl & CRTC2_EN) {
  52            /* CRT controller enabled, use CRTC values */
  53            uint32_t offs = s->regs.crtc_offset & 0x07ffffff;
  54            int stride = (s->regs.crtc_pitch & 0x7ff) * 8;
  55            int bpp = 0;
  56            int h, v;
  57
  58            if (s->regs.crtc_h_total_disp == 0) {
  59                s->regs.crtc_h_total_disp = ((640 / 8) - 1) << 16;
  60            }
  61            if (s->regs.crtc_v_total_disp == 0) {
  62                s->regs.crtc_v_total_disp = (480 - 1) << 16;
  63            }
  64            h = ((s->regs.crtc_h_total_disp >> 16) + 1) * 8;
  65            v = (s->regs.crtc_v_total_disp >> 16) + 1;
  66            switch (s->regs.crtc_gen_cntl & CRTC_PIX_WIDTH_MASK) {
  67            case CRTC_PIX_WIDTH_4BPP:
  68                bpp = 4;
  69                break;
  70            case CRTC_PIX_WIDTH_8BPP:
  71                bpp = 8;
  72                break;
  73            case CRTC_PIX_WIDTH_15BPP:
  74                bpp = 15;
  75                break;
  76            case CRTC_PIX_WIDTH_16BPP:
  77                bpp = 16;
  78                break;
  79            case CRTC_PIX_WIDTH_24BPP:
  80                bpp = 24;
  81                break;
  82            case CRTC_PIX_WIDTH_32BPP:
  83                bpp = 32;
  84                break;
  85            default:
  86                qemu_log_mask(LOG_UNIMP, "Unsupported bpp value\n");
  87            }
  88            assert(bpp != 0);
  89            DPRINTF("Switching to %dx%d %d %d @ %x\n", h, v, stride, bpp, offs);
  90            vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
  91            vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED);
  92            s->vga.big_endian_fb = false;
  93            /* reset VBE regs then set up mode */
  94            s->vga.vbe_regs[VBE_DISPI_INDEX_XRES] = h;
  95            s->vga.vbe_regs[VBE_DISPI_INDEX_YRES] = v;
  96            s->vga.vbe_regs[VBE_DISPI_INDEX_BPP] = bpp;
  97            /* enable mode via ioport so it updates vga regs */
  98            vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
  99            vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_ENABLED |
 100                VBE_DISPI_LFB_ENABLED | VBE_DISPI_NOCLEARMEM |
 101                (s->regs.dac_cntl & DAC_8BIT_EN ? VBE_DISPI_8BIT_DAC : 0));
 102            /* now set offset and stride after enable as that resets these */
 103            if (stride) {
 104                vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_VIRT_WIDTH);
 105                vbe_ioport_write_data(&s->vga, 0, stride);
 106                if (offs % stride == 0) {
 107                    vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_Y_OFFSET);
 108                    vbe_ioport_write_data(&s->vga, 0, offs / stride);
 109                } else {
 110                    /* FIXME what to do with this? */
 111                    error_report("VGA offset is not multiple of pitch, "
 112                                 "expect bad picture");
 113                }
 114            }
 115        }
 116    } else {
 117        /* VGA mode enabled */
 118        s->mode = VGA_MODE;
 119        vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
 120        vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED);
 121    }
 122}
 123
 124/* Used by host side hardware cursor */
 125static void ati_cursor_define(ATIVGAState *s)
 126{
 127    uint8_t data[1024];
 128    uint8_t *src;
 129    int i, j, idx = 0;
 130
 131    if ((s->regs.cur_offset & BIT(31)) || s->cursor_guest_mode) {
 132        return; /* Do not update cursor if locked or rendered by guest */
 133    }
 134    /* FIXME handle cur_hv_offs correctly */
 135    src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) +
 136          s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
 137          (s->regs.cur_hv_offs & 0xffff) * 16;
 138    for (i = 0; i < 64; i++) {
 139        for (j = 0; j < 8; j++, idx++) {
 140            data[idx] = src[i * 16 + j];
 141            data[512 + idx] = src[i * 16 + j + 8];
 142        }
 143    }
 144    if (!s->cursor) {
 145        s->cursor = cursor_alloc(64, 64);
 146    }
 147    cursor_set_mono(s->cursor, s->regs.cur_color1, s->regs.cur_color0,
 148                    &data[512], 1, &data[0]);
 149    dpy_cursor_define(s->vga.con, s->cursor);
 150}
 151
 152/* Alternatively support guest rendered hardware cursor */
 153static void ati_cursor_invalidate(VGACommonState *vga)
 154{
 155    ATIVGAState *s = container_of(vga, ATIVGAState, vga);
 156    int size = (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) ? 64 : 0;
 157
 158    if (s->regs.cur_offset & BIT(31)) {
 159        return; /* Do not update cursor if locked */
 160    }
 161    if (s->cursor_size != size ||
 162        vga->hw_cursor_x != s->regs.cur_hv_pos >> 16 ||
 163        vga->hw_cursor_y != (s->regs.cur_hv_pos & 0xffff) ||
 164        s->cursor_offset != s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
 165        (s->regs.cur_hv_offs & 0xffff) * 16) {
 166        /* Remove old cursor then update and show new one if needed */
 167        vga_invalidate_scanlines(vga, vga->hw_cursor_y, vga->hw_cursor_y + 63);
 168        vga->hw_cursor_x = s->regs.cur_hv_pos >> 16;
 169        vga->hw_cursor_y = s->regs.cur_hv_pos & 0xffff;
 170        s->cursor_offset = s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
 171                           (s->regs.cur_hv_offs & 0xffff) * 16;
 172        s->cursor_size = size;
 173        if (size) {
 174            vga_invalidate_scanlines(vga,
 175                                     vga->hw_cursor_y, vga->hw_cursor_y + 63);
 176        }
 177    }
 178}
 179
 180static void ati_cursor_draw_line(VGACommonState *vga, uint8_t *d, int scr_y)
 181{
 182    ATIVGAState *s = container_of(vga, ATIVGAState, vga);
 183    uint8_t *src;
 184    uint32_t *dp = (uint32_t *)d;
 185    int i, j, h;
 186
 187    if (!(s->regs.crtc_gen_cntl & CRTC2_CUR_EN) ||
 188        scr_y < vga->hw_cursor_y || scr_y >= vga->hw_cursor_y + 64 ||
 189        scr_y > s->regs.crtc_v_total_disp >> 16) {
 190        return;
 191    }
 192    /* FIXME handle cur_hv_offs correctly */
 193    src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) +
 194          s->cursor_offset + (scr_y - vga->hw_cursor_y) * 16;
 195    dp = &dp[vga->hw_cursor_x];
 196    h = ((s->regs.crtc_h_total_disp >> 16) + 1) * 8;
 197    for (i = 0; i < 8; i++) {
 198        uint32_t color;
 199        uint8_t abits = src[i];
 200        uint8_t xbits = src[i + 8];
 201        for (j = 0; j < 8; j++, abits <<= 1, xbits <<= 1) {
 202            if (abits & BIT(7)) {
 203                if (xbits & BIT(7)) {
 204                    color = dp[i * 8 + j] ^ 0xffffffff; /* complement */
 205                } else {
 206                    continue; /* transparent, no change */
 207                }
 208            } else {
 209                color = (xbits & BIT(7) ? s->regs.cur_color1 :
 210                                          s->regs.cur_color0) << 8 | 0xff;
 211            }
 212            if (vga->hw_cursor_x + i * 8 + j >= h) {
 213                return; /* end of screen, don't span to next line */
 214            }
 215            dp[i * 8 + j] = color;
 216        }
 217    }
 218}
 219
 220static uint64_t ati_i2c(bitbang_i2c_interface *i2c, uint64_t data, int base)
 221{
 222    bool c = (data & BIT(base + 17) ? !!(data & BIT(base + 1)) : 1);
 223    bool d = (data & BIT(base + 16) ? !!(data & BIT(base)) : 1);
 224
 225    bitbang_i2c_set(i2c, BITBANG_I2C_SCL, c);
 226    d = bitbang_i2c_set(i2c, BITBANG_I2C_SDA, d);
 227
 228    data &= ~0xf00ULL;
 229    if (c) {
 230        data |= BIT(base + 9);
 231    }
 232    if (d) {
 233        data |= BIT(base + 8);
 234    }
 235    return data;
 236}
 237
 238static inline uint64_t ati_reg_read_offs(uint32_t reg, int offs,
 239                                         unsigned int size)
 240{
 241    if (offs == 0 && size == 4) {
 242        return reg;
 243    } else {
 244        return extract32(reg, offs * BITS_PER_BYTE, size * BITS_PER_BYTE);
 245    }
 246}
 247
 248static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
 249{
 250    ATIVGAState *s = opaque;
 251    uint64_t val = 0;
 252
 253    switch (addr) {
 254    case MM_INDEX:
 255        val = s->regs.mm_index;
 256        break;
 257    case MM_DATA ... MM_DATA + 3:
 258        /* indexed access to regs or memory */
 259        if (s->regs.mm_index & BIT(31)) {
 260            uint32_t idx = s->regs.mm_index & ~BIT(31);
 261            if (idx <= s->vga.vram_size - size) {
 262                val = ldn_le_p(s->vga.vram_ptr + idx, size);
 263            }
 264        } else {
 265            val = ati_mm_read(s, s->regs.mm_index + addr - MM_DATA, size);
 266        }
 267        break;
 268    case BIOS_0_SCRATCH ... BUS_CNTL - 1:
 269    {
 270        int i = (addr - BIOS_0_SCRATCH) / 4;
 271        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF && i > 3) {
 272            break;
 273        }
 274        val = ati_reg_read_offs(s->regs.bios_scratch[i],
 275                                addr - (BIOS_0_SCRATCH + i * 4), size);
 276        break;
 277    }
 278    case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
 279        val = ati_reg_read_offs(s->regs.crtc_gen_cntl,
 280                                addr - CRTC_GEN_CNTL, size);
 281        break;
 282    case CRTC_EXT_CNTL ... CRTC_EXT_CNTL + 3:
 283        val = ati_reg_read_offs(s->regs.crtc_ext_cntl,
 284                                addr - CRTC_EXT_CNTL, size);
 285        break;
 286    case DAC_CNTL:
 287        val = s->regs.dac_cntl;
 288        break;
 289    case GPIO_VGA_DDC:
 290        val = s->regs.gpio_vga_ddc;
 291        break;
 292    case GPIO_DVI_DDC:
 293        val = s->regs.gpio_dvi_ddc;
 294        break;
 295    case GPIO_MONID ... GPIO_MONID + 3:
 296        val = ati_reg_read_offs(s->regs.gpio_monid,
 297                                addr - GPIO_MONID, size);
 298        break;
 299    case PALETTE_INDEX:
 300        /* FIXME unaligned access */
 301        val = vga_ioport_read(&s->vga, VGA_PEL_IR) << 16;
 302        val |= vga_ioport_read(&s->vga, VGA_PEL_IW) & 0xff;
 303        break;
 304    case PALETTE_DATA:
 305        val = vga_ioport_read(&s->vga, VGA_PEL_D);
 306        break;
 307    case CNFG_MEMSIZE:
 308        val = s->vga.vram_size;
 309        break;
 310    case MC_STATUS:
 311        val = 5;
 312        break;
 313    case RBBM_STATUS:
 314    case GUI_STAT:
 315        val = 64; /* free CMDFIFO entries */
 316        break;
 317    case CRTC_H_TOTAL_DISP:
 318        val = s->regs.crtc_h_total_disp;
 319        break;
 320    case CRTC_H_SYNC_STRT_WID:
 321        val = s->regs.crtc_h_sync_strt_wid;
 322        break;
 323    case CRTC_V_TOTAL_DISP:
 324        val = s->regs.crtc_v_total_disp;
 325        break;
 326    case CRTC_V_SYNC_STRT_WID:
 327        val = s->regs.crtc_v_sync_strt_wid;
 328        break;
 329    case CRTC_OFFSET:
 330        val = s->regs.crtc_offset;
 331        break;
 332    case CRTC_OFFSET_CNTL:
 333        val = s->regs.crtc_offset_cntl;
 334        break;
 335    case CRTC_PITCH:
 336        val = s->regs.crtc_pitch;
 337        break;
 338    case 0xf00 ... 0xfff:
 339        val = pci_default_read_config(&s->dev, addr - 0xf00, size);
 340        break;
 341    case CUR_OFFSET:
 342        val = s->regs.cur_offset;
 343        break;
 344    case CUR_HORZ_VERT_POSN:
 345        val = s->regs.cur_hv_pos;
 346        val |= s->regs.cur_offset & BIT(31);
 347        break;
 348    case CUR_HORZ_VERT_OFF:
 349        val = s->regs.cur_hv_offs;
 350        val |= s->regs.cur_offset & BIT(31);
 351        break;
 352    case CUR_CLR0:
 353        val = s->regs.cur_color0;
 354        break;
 355    case CUR_CLR1:
 356        val = s->regs.cur_color1;
 357        break;
 358    case DST_OFFSET:
 359        val = s->regs.dst_offset;
 360        break;
 361    case DST_PITCH:
 362        val = s->regs.dst_pitch;
 363        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
 364            val &= s->regs.dst_tile << 16;
 365        }
 366        break;
 367    case DST_WIDTH:
 368        val = s->regs.dst_width;
 369        break;
 370    case DST_HEIGHT:
 371        val = s->regs.dst_height;
 372        break;
 373    case SRC_X:
 374        val = s->regs.src_x;
 375        break;
 376    case SRC_Y:
 377        val = s->regs.src_y;
 378        break;
 379    case DST_X:
 380        val = s->regs.dst_x;
 381        break;
 382    case DST_Y:
 383        val = s->regs.dst_y;
 384        break;
 385    case DP_GUI_MASTER_CNTL:
 386        val = s->regs.dp_gui_master_cntl;
 387        break;
 388    case SRC_OFFSET:
 389        val = s->regs.src_offset;
 390        break;
 391    case SRC_PITCH:
 392        val = s->regs.src_pitch;
 393        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
 394            val &= s->regs.src_tile << 16;
 395        }
 396        break;
 397    case DP_BRUSH_BKGD_CLR:
 398        val = s->regs.dp_brush_bkgd_clr;
 399        break;
 400    case DP_BRUSH_FRGD_CLR:
 401        val = s->regs.dp_brush_frgd_clr;
 402        break;
 403    case DP_SRC_FRGD_CLR:
 404        val = s->regs.dp_src_frgd_clr;
 405        break;
 406    case DP_SRC_BKGD_CLR:
 407        val = s->regs.dp_src_bkgd_clr;
 408        break;
 409    case DP_CNTL:
 410        val = s->regs.dp_cntl;
 411        break;
 412    case DP_DATATYPE:
 413        val = s->regs.dp_datatype;
 414        break;
 415    case DP_MIX:
 416        val = s->regs.dp_mix;
 417        break;
 418    case DP_WRITE_MASK:
 419        val = s->regs.dp_write_mask;
 420        break;
 421    case DEFAULT_OFFSET:
 422        val = s->regs.default_offset;
 423        if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
 424            val >>= 10;
 425            val |= s->regs.default_pitch << 16;
 426            val |= s->regs.default_tile << 30;
 427        }
 428        break;
 429    case DEFAULT_PITCH:
 430        val = s->regs.default_pitch;
 431        val |= s->regs.default_tile << 16;
 432        break;
 433    case DEFAULT_SC_BOTTOM_RIGHT:
 434        val = s->regs.default_sc_bottom_right;
 435        break;
 436    default:
 437        break;
 438    }
 439    if (addr < CUR_OFFSET || addr > CUR_CLR1 || ATI_DEBUG_HW_CURSOR) {
 440        trace_ati_mm_read(size, addr, ati_reg_name(addr & ~3ULL), val);
 441    }
 442    return val;
 443}
 444
 445static inline void ati_reg_write_offs(uint32_t *reg, int offs,
 446                                      uint64_t data, unsigned int size)
 447{
 448    if (offs == 0 && size == 4) {
 449        *reg = data;
 450    } else {
 451        *reg = deposit32(*reg, offs * BITS_PER_BYTE, size * BITS_PER_BYTE,
 452                         data);
 453    }
 454}
 455
 456static void ati_mm_write(void *opaque, hwaddr addr,
 457                           uint64_t data, unsigned int size)
 458{
 459    ATIVGAState *s = opaque;
 460
 461    if (addr < CUR_OFFSET || addr > CUR_CLR1 || ATI_DEBUG_HW_CURSOR) {
 462        trace_ati_mm_write(size, addr, ati_reg_name(addr & ~3ULL), data);
 463    }
 464    switch (addr) {
 465    case MM_INDEX:
 466        s->regs.mm_index = data;
 467        break;
 468    case MM_DATA ... MM_DATA + 3:
 469        /* indexed access to regs or memory */
 470        if (s->regs.mm_index & BIT(31)) {
 471            uint32_t idx = s->regs.mm_index & ~BIT(31);
 472            if (idx <= s->vga.vram_size - size) {
 473                stn_le_p(s->vga.vram_ptr + idx, size, data);
 474            }
 475        } else {
 476            ati_mm_write(s, s->regs.mm_index + addr - MM_DATA, data, size);
 477        }
 478        break;
 479    case BIOS_0_SCRATCH ... BUS_CNTL - 1:
 480    {
 481        int i = (addr - BIOS_0_SCRATCH) / 4;
 482        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF && i > 3) {
 483            break;
 484        }
 485        ati_reg_write_offs(&s->regs.bios_scratch[i],
 486                           addr - (BIOS_0_SCRATCH + i * 4), data, size);
 487        break;
 488    }
 489    case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
 490    {
 491        uint32_t val = s->regs.crtc_gen_cntl;
 492        ati_reg_write_offs(&s->regs.crtc_gen_cntl,
 493                           addr - CRTC_GEN_CNTL, data, size);
 494        if ((val & CRTC2_CUR_EN) != (s->regs.crtc_gen_cntl & CRTC2_CUR_EN)) {
 495            if (s->cursor_guest_mode) {
 496                s->vga.force_shadow = !!(s->regs.crtc_gen_cntl & CRTC2_CUR_EN);
 497            } else {
 498                if (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) {
 499                    ati_cursor_define(s);
 500                }
 501                dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
 502                              s->regs.cur_hv_pos & 0xffff,
 503                              (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) != 0);
 504            }
 505        }
 506        if ((val & (CRTC2_EXT_DISP_EN | CRTC2_EN)) !=
 507            (s->regs.crtc_gen_cntl & (CRTC2_EXT_DISP_EN | CRTC2_EN))) {
 508            ati_vga_switch_mode(s);
 509        }
 510        break;
 511    }
 512    case CRTC_EXT_CNTL ... CRTC_EXT_CNTL + 3:
 513    {
 514        uint32_t val = s->regs.crtc_ext_cntl;
 515        ati_reg_write_offs(&s->regs.crtc_ext_cntl,
 516                           addr - CRTC_EXT_CNTL, data, size);
 517        if (s->regs.crtc_ext_cntl & CRT_CRTC_DISPLAY_DIS) {
 518            DPRINTF("Display disabled\n");
 519            s->vga.ar_index &= ~BIT(5);
 520        } else {
 521            DPRINTF("Display enabled\n");
 522            s->vga.ar_index |= BIT(5);
 523            ati_vga_switch_mode(s);
 524        }
 525        if ((val & CRT_CRTC_DISPLAY_DIS) !=
 526            (s->regs.crtc_ext_cntl & CRT_CRTC_DISPLAY_DIS)) {
 527            ati_vga_switch_mode(s);
 528        }
 529        break;
 530    }
 531    case DAC_CNTL:
 532        s->regs.dac_cntl = data & 0xffffe3ff;
 533        s->vga.dac_8bit = !!(data & DAC_8BIT_EN);
 534        break;
 535    case GPIO_VGA_DDC:
 536        if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
 537            /* FIXME: Maybe add a property to select VGA or DVI port? */
 538        }
 539        break;
 540    case GPIO_DVI_DDC:
 541        if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
 542            s->regs.gpio_dvi_ddc = ati_i2c(&s->bbi2c, data, 0);
 543        }
 544        break;
 545    case GPIO_MONID ... GPIO_MONID + 3:
 546        /* FIXME What does Radeon have here? */
 547        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
 548            ati_reg_write_offs(&s->regs.gpio_monid,
 549                               addr - GPIO_MONID, data, size);
 550            /*
 551             * Rage128p accesses DDC used to get EDID via these bits.
 552             * Only touch i2c when write overlaps 3rd byte because some
 553             * drivers access this reg via multiple partial writes and
 554             * without this spurious bits would be sent.
 555             */
 556            if ((s->regs.gpio_monid & BIT(25)) &&
 557                addr <= GPIO_MONID + 2 && addr + size > GPIO_MONID + 2) {
 558                s->regs.gpio_monid = ati_i2c(&s->bbi2c, s->regs.gpio_monid, 1);
 559            }
 560        }
 561        break;
 562    case PALETTE_INDEX ... PALETTE_INDEX + 3:
 563        if (size == 4) {
 564            vga_ioport_write(&s->vga, VGA_PEL_IR, (data >> 16) & 0xff);
 565            vga_ioport_write(&s->vga, VGA_PEL_IW, data & 0xff);
 566        } else {
 567            if (addr == PALETTE_INDEX) {
 568                vga_ioport_write(&s->vga, VGA_PEL_IW, data & 0xff);
 569            } else {
 570                vga_ioport_write(&s->vga, VGA_PEL_IR, data & 0xff);
 571            }
 572        }
 573        break;
 574    case PALETTE_DATA ... PALETTE_DATA + 3:
 575        data <<= addr - PALETTE_DATA;
 576        data = bswap32(data) >> 8;
 577        vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
 578        data >>= 8;
 579        vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
 580        data >>= 8;
 581        vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
 582        break;
 583    case CRTC_H_TOTAL_DISP:
 584        s->regs.crtc_h_total_disp = data & 0x07ff07ff;
 585        break;
 586    case CRTC_H_SYNC_STRT_WID:
 587        s->regs.crtc_h_sync_strt_wid = data & 0x17bf1fff;
 588        break;
 589    case CRTC_V_TOTAL_DISP:
 590        s->regs.crtc_v_total_disp = data & 0x0fff0fff;
 591        break;
 592    case CRTC_V_SYNC_STRT_WID:
 593        s->regs.crtc_v_sync_strt_wid = data & 0x9f0fff;
 594        break;
 595    case CRTC_OFFSET:
 596        s->regs.crtc_offset = data & 0xc7ffffff;
 597        break;
 598    case CRTC_OFFSET_CNTL:
 599        s->regs.crtc_offset_cntl = data; /* FIXME */
 600        break;
 601    case CRTC_PITCH:
 602        s->regs.crtc_pitch = data & 0x07ff07ff;
 603        break;
 604    case 0xf00 ... 0xfff:
 605        /* read-only copy of PCI config space so ignore writes */
 606        break;
 607    case CUR_OFFSET:
 608        if (s->regs.cur_offset != (data & 0x87fffff0)) {
 609            s->regs.cur_offset = data & 0x87fffff0;
 610            ati_cursor_define(s);
 611        }
 612        break;
 613    case CUR_HORZ_VERT_POSN:
 614        s->regs.cur_hv_pos = data & 0x3fff0fff;
 615        if (data & BIT(31)) {
 616            s->regs.cur_offset |= data & BIT(31);
 617        } else if (s->regs.cur_offset & BIT(31)) {
 618            s->regs.cur_offset &= ~BIT(31);
 619            ati_cursor_define(s);
 620        }
 621        if (!s->cursor_guest_mode &&
 622            (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(data & BIT(31))) {
 623            dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
 624                          s->regs.cur_hv_pos & 0xffff, 1);
 625        }
 626        break;
 627    case CUR_HORZ_VERT_OFF:
 628        s->regs.cur_hv_offs = data & 0x3f003f;
 629        if (data & BIT(31)) {
 630            s->regs.cur_offset |= data & BIT(31);
 631        } else if (s->regs.cur_offset & BIT(31)) {
 632            s->regs.cur_offset &= ~BIT(31);
 633            ati_cursor_define(s);
 634        }
 635        break;
 636    case CUR_CLR0:
 637        if (s->regs.cur_color0 != (data & 0xffffff)) {
 638            s->regs.cur_color0 = data & 0xffffff;
 639            ati_cursor_define(s);
 640        }
 641        break;
 642    case CUR_CLR1:
 643        /*
 644         * Update cursor unconditionally here because some clients set up
 645         * other registers before actually writing cursor data to memory at
 646         * offset so we would miss cursor change unless always updating here
 647         */
 648        s->regs.cur_color1 = data & 0xffffff;
 649        ati_cursor_define(s);
 650        break;
 651    case DST_OFFSET:
 652        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
 653            s->regs.dst_offset = data & 0xfffffff0;
 654        } else {
 655            s->regs.dst_offset = data & 0xfffffc00;
 656        }
 657        break;
 658    case DST_PITCH:
 659        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
 660            s->regs.dst_pitch = data & 0x3fff;
 661            s->regs.dst_tile = (data >> 16) & 1;
 662        } else {
 663            s->regs.dst_pitch = data & 0x3ff0;
 664        }
 665        break;
 666    case DST_TILE:
 667        if (s->dev_id == PCI_DEVICE_ID_ATI_RADEON_QY) {
 668            s->regs.dst_tile = data & 3;
 669        }
 670        break;
 671    case DST_WIDTH:
 672        s->regs.dst_width = data & 0x3fff;
 673        ati_2d_blt(s);
 674        break;
 675    case DST_HEIGHT:
 676        s->regs.dst_height = data & 0x3fff;
 677        break;
 678    case SRC_X:
 679        s->regs.src_x = data & 0x3fff;
 680        break;
 681    case SRC_Y:
 682        s->regs.src_y = data & 0x3fff;
 683        break;
 684    case DST_X:
 685        s->regs.dst_x = data & 0x3fff;
 686        break;
 687    case DST_Y:
 688        s->regs.dst_y = data & 0x3fff;
 689        break;
 690    case SRC_PITCH_OFFSET:
 691        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
 692            s->regs.src_offset = (data & 0x1fffff) << 5;
 693            s->regs.src_pitch = (data & 0x7fe00000) >> 21;
 694            s->regs.src_tile = data >> 31;
 695        } else {
 696            s->regs.src_offset = (data & 0x3fffff) << 10;
 697            s->regs.src_pitch = (data & 0x3fc00000) >> 16;
 698            s->regs.src_tile = (data >> 30) & 1;
 699        }
 700        break;
 701    case DST_PITCH_OFFSET:
 702        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
 703            s->regs.dst_offset = (data & 0x1fffff) << 5;
 704            s->regs.dst_pitch = (data & 0x7fe00000) >> 21;
 705            s->regs.dst_tile = data >> 31;
 706        } else {
 707            s->regs.dst_offset = (data & 0x3fffff) << 10;
 708            s->regs.dst_pitch = (data & 0x3fc00000) >> 16;
 709            s->regs.dst_tile = data >> 30;
 710        }
 711        break;
 712    case SRC_Y_X:
 713        s->regs.src_x = data & 0x3fff;
 714        s->regs.src_y = (data >> 16) & 0x3fff;
 715        break;
 716    case DST_Y_X:
 717        s->regs.dst_x = data & 0x3fff;
 718        s->regs.dst_y = (data >> 16) & 0x3fff;
 719        break;
 720    case DST_HEIGHT_WIDTH:
 721        s->regs.dst_width = data & 0x3fff;
 722        s->regs.dst_height = (data >> 16) & 0x3fff;
 723        ati_2d_blt(s);
 724        break;
 725    case DP_GUI_MASTER_CNTL:
 726        s->regs.dp_gui_master_cntl = data & 0xf800000f;
 727        s->regs.dp_datatype = (data & 0x0f00) >> 8 | (data & 0x30f0) << 4 |
 728                              (data & 0x4000) << 16;
 729        s->regs.dp_mix = (data & GMC_ROP3_MASK) | (data & 0x7000000) >> 16;
 730        break;
 731    case DST_WIDTH_X:
 732        s->regs.dst_x = data & 0x3fff;
 733        s->regs.dst_width = (data >> 16) & 0x3fff;
 734        ati_2d_blt(s);
 735        break;
 736    case SRC_X_Y:
 737        s->regs.src_y = data & 0x3fff;
 738        s->regs.src_x = (data >> 16) & 0x3fff;
 739        break;
 740    case DST_X_Y:
 741        s->regs.dst_y = data & 0x3fff;
 742        s->regs.dst_x = (data >> 16) & 0x3fff;
 743        break;
 744    case DST_WIDTH_HEIGHT:
 745        s->regs.dst_height = data & 0x3fff;
 746        s->regs.dst_width = (data >> 16) & 0x3fff;
 747        ati_2d_blt(s);
 748        break;
 749    case DST_HEIGHT_Y:
 750        s->regs.dst_y = data & 0x3fff;
 751        s->regs.dst_height = (data >> 16) & 0x3fff;
 752        break;
 753    case SRC_OFFSET:
 754        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
 755            s->regs.src_offset = data & 0xfffffff0;
 756        } else {
 757            s->regs.src_offset = data & 0xfffffc00;
 758        }
 759        break;
 760    case SRC_PITCH:
 761        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
 762            s->regs.src_pitch = data & 0x3fff;
 763            s->regs.src_tile = (data >> 16) & 1;
 764        } else {
 765            s->regs.src_pitch = data & 0x3ff0;
 766        }
 767        break;
 768    case DP_BRUSH_BKGD_CLR:
 769        s->regs.dp_brush_bkgd_clr = data;
 770        break;
 771    case DP_BRUSH_FRGD_CLR:
 772        s->regs.dp_brush_frgd_clr = data;
 773        break;
 774    case DP_CNTL:
 775        s->regs.dp_cntl = data;
 776        break;
 777    case DP_DATATYPE:
 778        s->regs.dp_datatype = data & 0xe0070f0f;
 779        break;
 780    case DP_MIX:
 781        s->regs.dp_mix = data & 0x00ff0700;
 782        break;
 783    case DP_WRITE_MASK:
 784        s->regs.dp_write_mask = data;
 785        break;
 786    case DEFAULT_OFFSET:
 787        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
 788            s->regs.default_offset = data & 0xfffffff0;
 789        } else {
 790            /* Radeon has DEFAULT_PITCH_OFFSET here like DST_PITCH_OFFSET */
 791            s->regs.default_offset = (data & 0x3fffff) << 10;
 792            s->regs.default_pitch = (data & 0x3fc00000) >> 16;
 793            s->regs.default_tile = data >> 30;
 794        }
 795        break;
 796    case DEFAULT_PITCH:
 797        if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
 798            s->regs.default_pitch = data & 0x3fff;
 799            s->regs.default_tile = (data >> 16) & 1;
 800        }
 801        break;
 802    case DEFAULT_SC_BOTTOM_RIGHT:
 803        s->regs.default_sc_bottom_right = data & 0x3fff3fff;
 804        break;
 805    default:
 806        break;
 807    }
 808}
 809
 810static const MemoryRegionOps ati_mm_ops = {
 811    .read = ati_mm_read,
 812    .write = ati_mm_write,
 813    .endianness = DEVICE_LITTLE_ENDIAN,
 814};
 815
 816static void ati_vga_realize(PCIDevice *dev, Error **errp)
 817{
 818    ATIVGAState *s = ATI_VGA(dev);
 819    VGACommonState *vga = &s->vga;
 820
 821    if (s->model) {
 822        int i;
 823        for (i = 0; i < ARRAY_SIZE(ati_model_aliases); i++) {
 824            if (!strcmp(s->model, ati_model_aliases[i].name)) {
 825                s->dev_id = ati_model_aliases[i].dev_id;
 826                break;
 827            }
 828        }
 829        if (i >= ARRAY_SIZE(ati_model_aliases)) {
 830            warn_report("Unknown ATI VGA model name, "
 831                        "using default rage128p");
 832        }
 833    }
 834    if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF &&
 835        s->dev_id != PCI_DEVICE_ID_ATI_RADEON_QY) {
 836        error_setg(errp, "Unknown ATI VGA device id, "
 837                   "only 0x5046 and 0x5159 are supported");
 838        return;
 839    }
 840    pci_set_word(dev->config + PCI_DEVICE_ID, s->dev_id);
 841
 842    if (s->dev_id == PCI_DEVICE_ID_ATI_RADEON_QY &&
 843        s->vga.vram_size_mb < 16) {
 844        warn_report("Too small video memory for device id");
 845        s->vga.vram_size_mb = 16;
 846    }
 847
 848    /* init vga bits */
 849    vga_common_init(vga, OBJECT(s));
 850    vga_init(vga, OBJECT(s), pci_address_space(dev),
 851             pci_address_space_io(dev), true);
 852    vga->con = graphic_console_init(DEVICE(s), 0, s->vga.hw_ops, &s->vga);
 853    if (s->cursor_guest_mode) {
 854        vga->cursor_invalidate = ati_cursor_invalidate;
 855        vga->cursor_draw_line = ati_cursor_draw_line;
 856    }
 857
 858    /* ddc, edid */
 859    I2CBus *i2cbus = i2c_init_bus(DEVICE(s), "ati-vga.ddc");
 860    bitbang_i2c_init(&s->bbi2c, i2cbus);
 861    I2CSlave *i2cddc = I2C_SLAVE(qdev_create(BUS(i2cbus), TYPE_I2CDDC));
 862    i2c_set_slave_address(i2cddc, 0x50);
 863
 864    /* mmio register space */
 865    memory_region_init_io(&s->mm, OBJECT(s), &ati_mm_ops, s,
 866                          "ati.mmregs", 0x4000);
 867    /* io space is alias to beginning of mmregs */
 868    memory_region_init_alias(&s->io, OBJECT(s), "ati.io", &s->mm, 0, 0x100);
 869
 870    pci_register_bar(dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
 871    pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
 872    pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mm);
 873}
 874
 875static void ati_vga_reset(DeviceState *dev)
 876{
 877    ATIVGAState *s = ATI_VGA(dev);
 878
 879    /* reset vga */
 880    vga_common_reset(&s->vga);
 881    s->mode = VGA_MODE;
 882}
 883
 884static void ati_vga_exit(PCIDevice *dev)
 885{
 886    ATIVGAState *s = ATI_VGA(dev);
 887
 888    graphic_console_close(s->vga.con);
 889}
 890
 891static Property ati_vga_properties[] = {
 892    DEFINE_PROP_UINT32("vgamem_mb", ATIVGAState, vga.vram_size_mb, 16),
 893    DEFINE_PROP_STRING("model", ATIVGAState, model),
 894    DEFINE_PROP_UINT16("x-device-id", ATIVGAState, dev_id,
 895                       PCI_DEVICE_ID_ATI_RAGE128_PF),
 896    DEFINE_PROP_BOOL("guest_hwcursor", ATIVGAState, cursor_guest_mode, false),
 897    DEFINE_PROP_END_OF_LIST()
 898};
 899
 900static void ati_vga_class_init(ObjectClass *klass, void *data)
 901{
 902    DeviceClass *dc = DEVICE_CLASS(klass);
 903    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
 904
 905    dc->reset = ati_vga_reset;
 906    dc->props = ati_vga_properties;
 907    dc->hotpluggable = false;
 908    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
 909
 910    k->class_id = PCI_CLASS_DISPLAY_VGA;
 911    k->vendor_id = PCI_VENDOR_ID_ATI;
 912    k->device_id = PCI_DEVICE_ID_ATI_RAGE128_PF;
 913    k->romfile = "vgabios-ati.bin";
 914    k->realize = ati_vga_realize;
 915    k->exit = ati_vga_exit;
 916}
 917
 918static const TypeInfo ati_vga_info = {
 919    .name = TYPE_ATI_VGA,
 920    .parent = TYPE_PCI_DEVICE,
 921    .instance_size = sizeof(ATIVGAState),
 922    .class_init = ati_vga_class_init,
 923    .interfaces = (InterfaceInfo[]) {
 924          { INTERFACE_CONVENTIONAL_PCI_DEVICE },
 925          { },
 926    },
 927};
 928
 929static void ati_vga_register_types(void)
 930{
 931    type_register_static(&ati_vga_info);
 932}
 933
 934type_init(ati_vga_register_types)
 935