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