qemu/hw/display/cirrus_vga.c
<<
>>
Prefs
   1/*
   2 * QEMU Cirrus CLGD 54xx VGA Emulator.
   3 *
   4 * Copyright (c) 2004 Fabrice Bellard
   5 * Copyright (c) 2004 Makoto Suzuki (suzu)
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25/*
  26 * Reference: Finn Thogersons' VGADOC4b:
  27 *
  28 *  http://web.archive.org/web/20021019054927/http://home.worldonline.dk/finth/
  29 *
  30 * VGADOC4b.ZIP content available at:
  31 *
  32 *  https://pdos.csail.mit.edu/6.828/2005/readings/hardware/vgadoc
  33 */
  34
  35#include "qemu/osdep.h"
  36#include "qemu/module.h"
  37#include "qemu/units.h"
  38#include "qemu/log.h"
  39#include "sysemu/reset.h"
  40#include "qapi/error.h"
  41#include "trace.h"
  42#include "hw/pci/pci.h"
  43#include "hw/qdev-properties.h"
  44#include "migration/vmstate.h"
  45#include "ui/pixel_ops.h"
  46#include "cirrus_vga_internal.h"
  47
  48/*
  49 * TODO:
  50 *    - destination write mask support not complete (bits 5..7)
  51 *    - optimize linear mappings
  52 *    - optimize bitblt functions
  53 */
  54
  55//#define DEBUG_CIRRUS
  56
  57/***************************************
  58 *
  59 *  definitions
  60 *
  61 ***************************************/
  62
  63// sequencer 0x07
  64#define CIRRUS_SR7_BPP_VGA            0x00
  65#define CIRRUS_SR7_BPP_SVGA           0x01
  66#define CIRRUS_SR7_BPP_MASK           0x0e
  67#define CIRRUS_SR7_BPP_8              0x00
  68#define CIRRUS_SR7_BPP_16_DOUBLEVCLK  0x02
  69#define CIRRUS_SR7_BPP_24             0x04
  70#define CIRRUS_SR7_BPP_16             0x06
  71#define CIRRUS_SR7_BPP_32             0x08
  72#define CIRRUS_SR7_ISAADDR_MASK       0xe0
  73
  74// sequencer 0x0f
  75#define CIRRUS_MEMSIZE_512k        0x08
  76#define CIRRUS_MEMSIZE_1M          0x10
  77#define CIRRUS_MEMSIZE_2M          0x18
  78#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled.
  79
  80// sequencer 0x12
  81#define CIRRUS_CURSOR_SHOW         0x01
  82#define CIRRUS_CURSOR_HIDDENPEL    0x02
  83#define CIRRUS_CURSOR_LARGE        0x04 // 64x64 if set, 32x32 if clear
  84
  85// sequencer 0x17
  86#define CIRRUS_BUSTYPE_VLBFAST   0x10
  87#define CIRRUS_BUSTYPE_PCI       0x20
  88#define CIRRUS_BUSTYPE_VLBSLOW   0x30
  89#define CIRRUS_BUSTYPE_ISA       0x38
  90#define CIRRUS_MMIO_ENABLE       0x04
  91#define CIRRUS_MMIO_USE_PCIADDR  0x40   // 0xb8000 if cleared.
  92#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
  93
  94// control 0x0b
  95#define CIRRUS_BANKING_DUAL             0x01
  96#define CIRRUS_BANKING_GRANULARITY_16K  0x20    // set:16k, clear:4k
  97
  98// control 0x30
  99#define CIRRUS_BLTMODE_BACKWARDS        0x01
 100#define CIRRUS_BLTMODE_MEMSYSDEST       0x02
 101#define CIRRUS_BLTMODE_MEMSYSSRC        0x04
 102#define CIRRUS_BLTMODE_TRANSPARENTCOMP  0x08
 103#define CIRRUS_BLTMODE_PATTERNCOPY      0x40
 104#define CIRRUS_BLTMODE_COLOREXPAND      0x80
 105#define CIRRUS_BLTMODE_PIXELWIDTHMASK   0x30
 106#define CIRRUS_BLTMODE_PIXELWIDTH8      0x00
 107#define CIRRUS_BLTMODE_PIXELWIDTH16     0x10
 108#define CIRRUS_BLTMODE_PIXELWIDTH24     0x20
 109#define CIRRUS_BLTMODE_PIXELWIDTH32     0x30
 110
 111// control 0x31
 112#define CIRRUS_BLT_BUSY                 0x01
 113#define CIRRUS_BLT_START                0x02
 114#define CIRRUS_BLT_RESET                0x04
 115#define CIRRUS_BLT_FIFOUSED             0x10
 116#define CIRRUS_BLT_AUTOSTART            0x80
 117
 118// control 0x32
 119#define CIRRUS_ROP_0                    0x00
 120#define CIRRUS_ROP_SRC_AND_DST          0x05
 121#define CIRRUS_ROP_NOP                  0x06
 122#define CIRRUS_ROP_SRC_AND_NOTDST       0x09
 123#define CIRRUS_ROP_NOTDST               0x0b
 124#define CIRRUS_ROP_SRC                  0x0d
 125#define CIRRUS_ROP_1                    0x0e
 126#define CIRRUS_ROP_NOTSRC_AND_DST       0x50
 127#define CIRRUS_ROP_SRC_XOR_DST          0x59
 128#define CIRRUS_ROP_SRC_OR_DST           0x6d
 129#define CIRRUS_ROP_NOTSRC_OR_NOTDST     0x90
 130#define CIRRUS_ROP_SRC_NOTXOR_DST       0x95
 131#define CIRRUS_ROP_SRC_OR_NOTDST        0xad
 132#define CIRRUS_ROP_NOTSRC               0xd0
 133#define CIRRUS_ROP_NOTSRC_OR_DST        0xd6
 134#define CIRRUS_ROP_NOTSRC_AND_NOTDST    0xda
 135
 136#define CIRRUS_ROP_NOP_INDEX 2
 137#define CIRRUS_ROP_SRC_INDEX 5
 138
 139// control 0x33
 140#define CIRRUS_BLTMODEEXT_SOLIDFILL        0x04
 141#define CIRRUS_BLTMODEEXT_COLOREXPINV      0x02
 142#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01
 143
 144// memory-mapped IO
 145#define CIRRUS_MMIO_BLTBGCOLOR        0x00      // dword
 146#define CIRRUS_MMIO_BLTFGCOLOR        0x04      // dword
 147#define CIRRUS_MMIO_BLTWIDTH          0x08      // word
 148#define CIRRUS_MMIO_BLTHEIGHT         0x0a      // word
 149#define CIRRUS_MMIO_BLTDESTPITCH      0x0c      // word
 150#define CIRRUS_MMIO_BLTSRCPITCH       0x0e      // word
 151#define CIRRUS_MMIO_BLTDESTADDR       0x10      // dword
 152#define CIRRUS_MMIO_BLTSRCADDR        0x14      // dword
 153#define CIRRUS_MMIO_BLTWRITEMASK      0x17      // byte
 154#define CIRRUS_MMIO_BLTMODE           0x18      // byte
 155#define CIRRUS_MMIO_BLTROP            0x1a      // byte
 156#define CIRRUS_MMIO_BLTMODEEXT        0x1b      // byte
 157#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c    // word?
 158#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20        // word?
 159#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24     // word
 160#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26     // word
 161#define CIRRUS_MMIO_LINEARDRAW_END_X  0x28      // word
 162#define CIRRUS_MMIO_LINEARDRAW_END_Y  0x2a      // word
 163#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c       // byte
 164#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d  // byte
 165#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e      // byte
 166#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f     // byte
 167#define CIRRUS_MMIO_BRESENHAM_K1      0x30      // word
 168#define CIRRUS_MMIO_BRESENHAM_K3      0x32      // word
 169#define CIRRUS_MMIO_BRESENHAM_ERROR   0x34      // word
 170#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36  // word
 171#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38    // byte
 172#define CIRRUS_MMIO_LINEDRAW_MODE     0x39      // byte
 173#define CIRRUS_MMIO_BLTSTATUS         0x40      // byte
 174
 175#define CIRRUS_PNPMMIO_SIZE         0x1000
 176
 177typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
 178                              uint32_t dstaddr, int dst_pitch,
 179                              int width, int height);
 180
 181typedef struct PCICirrusVGAState {
 182    PCIDevice dev;
 183    CirrusVGAState cirrus_vga;
 184} PCICirrusVGAState;
 185
 186#define TYPE_PCI_CIRRUS_VGA "cirrus-vga"
 187#define PCI_CIRRUS_VGA(obj) \
 188    OBJECT_CHECK(PCICirrusVGAState, (obj), TYPE_PCI_CIRRUS_VGA)
 189
 190static uint8_t rop_to_index[256];
 191
 192/***************************************
 193 *
 194 *  prototypes.
 195 *
 196 ***************************************/
 197
 198
 199static void cirrus_bitblt_reset(CirrusVGAState *s);
 200static void cirrus_update_memory_access(CirrusVGAState *s);
 201
 202/***************************************
 203 *
 204 *  raster operations
 205 *
 206 ***************************************/
 207
 208static bool blit_region_is_unsafe(struct CirrusVGAState *s,
 209                                  int32_t pitch, int32_t addr)
 210{
 211    if (!pitch) {
 212        return true;
 213    }
 214    if (pitch < 0) {
 215        int64_t min = addr
 216            + ((int64_t)s->cirrus_blt_height - 1) * pitch
 217            - s->cirrus_blt_width;
 218        if (min < -1 || addr >= s->vga.vram_size) {
 219            return true;
 220        }
 221    } else {
 222        int64_t max = addr
 223            + ((int64_t)s->cirrus_blt_height-1) * pitch
 224            + s->cirrus_blt_width;
 225        if (max > s->vga.vram_size) {
 226            return true;
 227        }
 228    }
 229    return false;
 230}
 231
 232static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
 233{
 234    /* should be the case, see cirrus_bitblt_start */
 235    assert(s->cirrus_blt_width > 0);
 236    assert(s->cirrus_blt_height > 0);
 237
 238    if (s->cirrus_blt_width > CIRRUS_BLTBUFSIZE) {
 239        return true;
 240    }
 241
 242    if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,
 243                              s->cirrus_blt_dstaddr)) {
 244        return true;
 245    }
 246    if (dst_only) {
 247        return false;
 248    }
 249    if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch,
 250                              s->cirrus_blt_srcaddr)) {
 251        return true;
 252    }
 253
 254    return false;
 255}
 256
 257static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
 258                                  uint32_t dstaddr, uint32_t srcaddr,
 259                                  int dstpitch,int srcpitch,
 260                                  int bltwidth,int bltheight)
 261{
 262}
 263
 264static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
 265                                   uint32_t dstaddr,
 266                                   int dstpitch, int bltwidth,int bltheight)
 267{
 268}
 269
 270static inline uint8_t cirrus_src(CirrusVGAState *s, uint32_t srcaddr)
 271{
 272    if (s->cirrus_srccounter) {
 273        /* cputovideo */
 274        return s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1)];
 275    } else {
 276        /* videotovideo */
 277        return s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask];
 278    }
 279}
 280
 281static inline uint16_t cirrus_src16(CirrusVGAState *s, uint32_t srcaddr)
 282{
 283    uint16_t *src;
 284
 285    if (s->cirrus_srccounter) {
 286        /* cputovideo */
 287        src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~1];
 288    } else {
 289        /* videotovideo */
 290        src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~1];
 291    }
 292    return *src;
 293}
 294
 295static inline uint32_t cirrus_src32(CirrusVGAState *s, uint32_t srcaddr)
 296{
 297    uint32_t *src;
 298
 299    if (s->cirrus_srccounter) {
 300        /* cputovideo */
 301        src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~3];
 302    } else {
 303        /* videotovideo */
 304        src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~3];
 305    }
 306    return *src;
 307}
 308
 309#define ROP_NAME 0
 310#define ROP_FN(d, s) 0
 311#include "cirrus_vga_rop.h"
 312
 313#define ROP_NAME src_and_dst
 314#define ROP_FN(d, s) (s) & (d)
 315#include "cirrus_vga_rop.h"
 316
 317#define ROP_NAME src_and_notdst
 318#define ROP_FN(d, s) (s) & (~(d))
 319#include "cirrus_vga_rop.h"
 320
 321#define ROP_NAME notdst
 322#define ROP_FN(d, s) ~(d)
 323#include "cirrus_vga_rop.h"
 324
 325#define ROP_NAME src
 326#define ROP_FN(d, s) s
 327#include "cirrus_vga_rop.h"
 328
 329#define ROP_NAME 1
 330#define ROP_FN(d, s) ~0
 331#include "cirrus_vga_rop.h"
 332
 333#define ROP_NAME notsrc_and_dst
 334#define ROP_FN(d, s) (~(s)) & (d)
 335#include "cirrus_vga_rop.h"
 336
 337#define ROP_NAME src_xor_dst
 338#define ROP_FN(d, s) (s) ^ (d)
 339#include "cirrus_vga_rop.h"
 340
 341#define ROP_NAME src_or_dst
 342#define ROP_FN(d, s) (s) | (d)
 343#include "cirrus_vga_rop.h"
 344
 345#define ROP_NAME notsrc_or_notdst
 346#define ROP_FN(d, s) (~(s)) | (~(d))
 347#include "cirrus_vga_rop.h"
 348
 349#define ROP_NAME src_notxor_dst
 350#define ROP_FN(d, s) ~((s) ^ (d))
 351#include "cirrus_vga_rop.h"
 352
 353#define ROP_NAME src_or_notdst
 354#define ROP_FN(d, s) (s) | (~(d))
 355#include "cirrus_vga_rop.h"
 356
 357#define ROP_NAME notsrc
 358#define ROP_FN(d, s) (~(s))
 359#include "cirrus_vga_rop.h"
 360
 361#define ROP_NAME notsrc_or_dst
 362#define ROP_FN(d, s) (~(s)) | (d)
 363#include "cirrus_vga_rop.h"
 364
 365#define ROP_NAME notsrc_and_notdst
 366#define ROP_FN(d, s) (~(s)) & (~(d))
 367#include "cirrus_vga_rop.h"
 368
 369static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = {
 370    cirrus_bitblt_rop_fwd_0,
 371    cirrus_bitblt_rop_fwd_src_and_dst,
 372    cirrus_bitblt_rop_nop,
 373    cirrus_bitblt_rop_fwd_src_and_notdst,
 374    cirrus_bitblt_rop_fwd_notdst,
 375    cirrus_bitblt_rop_fwd_src,
 376    cirrus_bitblt_rop_fwd_1,
 377    cirrus_bitblt_rop_fwd_notsrc_and_dst,
 378    cirrus_bitblt_rop_fwd_src_xor_dst,
 379    cirrus_bitblt_rop_fwd_src_or_dst,
 380    cirrus_bitblt_rop_fwd_notsrc_or_notdst,
 381    cirrus_bitblt_rop_fwd_src_notxor_dst,
 382    cirrus_bitblt_rop_fwd_src_or_notdst,
 383    cirrus_bitblt_rop_fwd_notsrc,
 384    cirrus_bitblt_rop_fwd_notsrc_or_dst,
 385    cirrus_bitblt_rop_fwd_notsrc_and_notdst,
 386};
 387
 388static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = {
 389    cirrus_bitblt_rop_bkwd_0,
 390    cirrus_bitblt_rop_bkwd_src_and_dst,
 391    cirrus_bitblt_rop_nop,
 392    cirrus_bitblt_rop_bkwd_src_and_notdst,
 393    cirrus_bitblt_rop_bkwd_notdst,
 394    cirrus_bitblt_rop_bkwd_src,
 395    cirrus_bitblt_rop_bkwd_1,
 396    cirrus_bitblt_rop_bkwd_notsrc_and_dst,
 397    cirrus_bitblt_rop_bkwd_src_xor_dst,
 398    cirrus_bitblt_rop_bkwd_src_or_dst,
 399    cirrus_bitblt_rop_bkwd_notsrc_or_notdst,
 400    cirrus_bitblt_rop_bkwd_src_notxor_dst,
 401    cirrus_bitblt_rop_bkwd_src_or_notdst,
 402    cirrus_bitblt_rop_bkwd_notsrc,
 403    cirrus_bitblt_rop_bkwd_notsrc_or_dst,
 404    cirrus_bitblt_rop_bkwd_notsrc_and_notdst,
 405};
 406
 407#define TRANSP_ROP(name) {\
 408    name ## _8,\
 409    name ## _16,\
 410        }
 411#define TRANSP_NOP(func) {\
 412    func,\
 413    func,\
 414        }
 415
 416static const cirrus_bitblt_rop_t cirrus_fwd_transp_rop[16][2] = {
 417    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_0),
 418    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_dst),
 419    TRANSP_NOP(cirrus_bitblt_rop_nop),
 420    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_notdst),
 421    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notdst),
 422    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src),
 423    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_1),
 424    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_dst),
 425    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_xor_dst),
 426    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_dst),
 427    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_notdst),
 428    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_notxor_dst),
 429    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_notdst),
 430    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc),
 431    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_dst),
 432    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_notdst),
 433};
 434
 435static const cirrus_bitblt_rop_t cirrus_bkwd_transp_rop[16][2] = {
 436    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_0),
 437    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_dst),
 438    TRANSP_NOP(cirrus_bitblt_rop_nop),
 439    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_notdst),
 440    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notdst),
 441    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src),
 442    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_1),
 443    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_dst),
 444    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_xor_dst),
 445    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_dst),
 446    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_notdst),
 447    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_notxor_dst),
 448    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_notdst),
 449    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc),
 450    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_dst),
 451    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_notdst),
 452};
 453
 454#define ROP2(name) {\
 455    name ## _8,\
 456    name ## _16,\
 457    name ## _24,\
 458    name ## _32,\
 459        }
 460
 461#define ROP_NOP2(func) {\
 462    func,\
 463    func,\
 464    func,\
 465    func,\
 466        }
 467
 468static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = {
 469    ROP2(cirrus_patternfill_0),
 470    ROP2(cirrus_patternfill_src_and_dst),
 471    ROP_NOP2(cirrus_bitblt_rop_nop),
 472    ROP2(cirrus_patternfill_src_and_notdst),
 473    ROP2(cirrus_patternfill_notdst),
 474    ROP2(cirrus_patternfill_src),
 475    ROP2(cirrus_patternfill_1),
 476    ROP2(cirrus_patternfill_notsrc_and_dst),
 477    ROP2(cirrus_patternfill_src_xor_dst),
 478    ROP2(cirrus_patternfill_src_or_dst),
 479    ROP2(cirrus_patternfill_notsrc_or_notdst),
 480    ROP2(cirrus_patternfill_src_notxor_dst),
 481    ROP2(cirrus_patternfill_src_or_notdst),
 482    ROP2(cirrus_patternfill_notsrc),
 483    ROP2(cirrus_patternfill_notsrc_or_dst),
 484    ROP2(cirrus_patternfill_notsrc_and_notdst),
 485};
 486
 487static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = {
 488    ROP2(cirrus_colorexpand_transp_0),
 489    ROP2(cirrus_colorexpand_transp_src_and_dst),
 490    ROP_NOP2(cirrus_bitblt_rop_nop),
 491    ROP2(cirrus_colorexpand_transp_src_and_notdst),
 492    ROP2(cirrus_colorexpand_transp_notdst),
 493    ROP2(cirrus_colorexpand_transp_src),
 494    ROP2(cirrus_colorexpand_transp_1),
 495    ROP2(cirrus_colorexpand_transp_notsrc_and_dst),
 496    ROP2(cirrus_colorexpand_transp_src_xor_dst),
 497    ROP2(cirrus_colorexpand_transp_src_or_dst),
 498    ROP2(cirrus_colorexpand_transp_notsrc_or_notdst),
 499    ROP2(cirrus_colorexpand_transp_src_notxor_dst),
 500    ROP2(cirrus_colorexpand_transp_src_or_notdst),
 501    ROP2(cirrus_colorexpand_transp_notsrc),
 502    ROP2(cirrus_colorexpand_transp_notsrc_or_dst),
 503    ROP2(cirrus_colorexpand_transp_notsrc_and_notdst),
 504};
 505
 506static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = {
 507    ROP2(cirrus_colorexpand_0),
 508    ROP2(cirrus_colorexpand_src_and_dst),
 509    ROP_NOP2(cirrus_bitblt_rop_nop),
 510    ROP2(cirrus_colorexpand_src_and_notdst),
 511    ROP2(cirrus_colorexpand_notdst),
 512    ROP2(cirrus_colorexpand_src),
 513    ROP2(cirrus_colorexpand_1),
 514    ROP2(cirrus_colorexpand_notsrc_and_dst),
 515    ROP2(cirrus_colorexpand_src_xor_dst),
 516    ROP2(cirrus_colorexpand_src_or_dst),
 517    ROP2(cirrus_colorexpand_notsrc_or_notdst),
 518    ROP2(cirrus_colorexpand_src_notxor_dst),
 519    ROP2(cirrus_colorexpand_src_or_notdst),
 520    ROP2(cirrus_colorexpand_notsrc),
 521    ROP2(cirrus_colorexpand_notsrc_or_dst),
 522    ROP2(cirrus_colorexpand_notsrc_and_notdst),
 523};
 524
 525static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = {
 526    ROP2(cirrus_colorexpand_pattern_transp_0),
 527    ROP2(cirrus_colorexpand_pattern_transp_src_and_dst),
 528    ROP_NOP2(cirrus_bitblt_rop_nop),
 529    ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst),
 530    ROP2(cirrus_colorexpand_pattern_transp_notdst),
 531    ROP2(cirrus_colorexpand_pattern_transp_src),
 532    ROP2(cirrus_colorexpand_pattern_transp_1),
 533    ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst),
 534    ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst),
 535    ROP2(cirrus_colorexpand_pattern_transp_src_or_dst),
 536    ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst),
 537    ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst),
 538    ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst),
 539    ROP2(cirrus_colorexpand_pattern_transp_notsrc),
 540    ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst),
 541    ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst),
 542};
 543
 544static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = {
 545    ROP2(cirrus_colorexpand_pattern_0),
 546    ROP2(cirrus_colorexpand_pattern_src_and_dst),
 547    ROP_NOP2(cirrus_bitblt_rop_nop),
 548    ROP2(cirrus_colorexpand_pattern_src_and_notdst),
 549    ROP2(cirrus_colorexpand_pattern_notdst),
 550    ROP2(cirrus_colorexpand_pattern_src),
 551    ROP2(cirrus_colorexpand_pattern_1),
 552    ROP2(cirrus_colorexpand_pattern_notsrc_and_dst),
 553    ROP2(cirrus_colorexpand_pattern_src_xor_dst),
 554    ROP2(cirrus_colorexpand_pattern_src_or_dst),
 555    ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst),
 556    ROP2(cirrus_colorexpand_pattern_src_notxor_dst),
 557    ROP2(cirrus_colorexpand_pattern_src_or_notdst),
 558    ROP2(cirrus_colorexpand_pattern_notsrc),
 559    ROP2(cirrus_colorexpand_pattern_notsrc_or_dst),
 560    ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst),
 561};
 562
 563static const cirrus_fill_t cirrus_fill[16][4] = {
 564    ROP2(cirrus_fill_0),
 565    ROP2(cirrus_fill_src_and_dst),
 566    ROP_NOP2(cirrus_bitblt_fill_nop),
 567    ROP2(cirrus_fill_src_and_notdst),
 568    ROP2(cirrus_fill_notdst),
 569    ROP2(cirrus_fill_src),
 570    ROP2(cirrus_fill_1),
 571    ROP2(cirrus_fill_notsrc_and_dst),
 572    ROP2(cirrus_fill_src_xor_dst),
 573    ROP2(cirrus_fill_src_or_dst),
 574    ROP2(cirrus_fill_notsrc_or_notdst),
 575    ROP2(cirrus_fill_src_notxor_dst),
 576    ROP2(cirrus_fill_src_or_notdst),
 577    ROP2(cirrus_fill_notsrc),
 578    ROP2(cirrus_fill_notsrc_or_dst),
 579    ROP2(cirrus_fill_notsrc_and_notdst),
 580};
 581
 582static inline void cirrus_bitblt_fgcol(CirrusVGAState *s)
 583{
 584    unsigned int color;
 585    switch (s->cirrus_blt_pixelwidth) {
 586    case 1:
 587        s->cirrus_blt_fgcol = s->cirrus_shadow_gr1;
 588        break;
 589    case 2:
 590        color = s->cirrus_shadow_gr1 | (s->vga.gr[0x11] << 8);
 591        s->cirrus_blt_fgcol = le16_to_cpu(color);
 592        break;
 593    case 3:
 594        s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 |
 595            (s->vga.gr[0x11] << 8) | (s->vga.gr[0x13] << 16);
 596        break;
 597    default:
 598    case 4:
 599        color = s->cirrus_shadow_gr1 | (s->vga.gr[0x11] << 8) |
 600            (s->vga.gr[0x13] << 16) | (s->vga.gr[0x15] << 24);
 601        s->cirrus_blt_fgcol = le32_to_cpu(color);
 602        break;
 603    }
 604}
 605
 606static inline void cirrus_bitblt_bgcol(CirrusVGAState *s)
 607{
 608    unsigned int color;
 609    switch (s->cirrus_blt_pixelwidth) {
 610    case 1:
 611        s->cirrus_blt_bgcol = s->cirrus_shadow_gr0;
 612        break;
 613    case 2:
 614        color = s->cirrus_shadow_gr0 | (s->vga.gr[0x10] << 8);
 615        s->cirrus_blt_bgcol = le16_to_cpu(color);
 616        break;
 617    case 3:
 618        s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 |
 619            (s->vga.gr[0x10] << 8) | (s->vga.gr[0x12] << 16);
 620        break;
 621    default:
 622    case 4:
 623        color = s->cirrus_shadow_gr0 | (s->vga.gr[0x10] << 8) |
 624            (s->vga.gr[0x12] << 16) | (s->vga.gr[0x14] << 24);
 625        s->cirrus_blt_bgcol = le32_to_cpu(color);
 626        break;
 627    }
 628}
 629
 630static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
 631                                     int off_pitch, int bytesperline,
 632                                     int lines)
 633{
 634    int y;
 635    int off_cur;
 636    int off_cur_end;
 637
 638    if (off_pitch < 0) {
 639        off_begin -= bytesperline - 1;
 640    }
 641
 642    for (y = 0; y < lines; y++) {
 643        off_cur = off_begin;
 644        off_cur_end = ((off_cur + bytesperline - 1) & s->cirrus_addr_mask) + 1;
 645        assert(off_cur_end >= off_cur);
 646        memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur);
 647        off_begin += off_pitch;
 648    }
 649}
 650
 651static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s)
 652{
 653    uint32_t patternsize;
 654    bool videosrc = !s->cirrus_srccounter;
 655
 656    if (videosrc) {
 657        switch (s->vga.get_bpp(&s->vga)) {
 658        case 8:
 659            patternsize = 64;
 660            break;
 661        case 15:
 662        case 16:
 663            patternsize = 128;
 664            break;
 665        case 24:
 666        case 32:
 667        default:
 668            patternsize = 256;
 669            break;
 670        }
 671        s->cirrus_blt_srcaddr &= ~(patternsize - 1);
 672        if (s->cirrus_blt_srcaddr + patternsize > s->vga.vram_size) {
 673            return 0;
 674        }
 675    }
 676
 677    if (blit_is_unsafe(s, true)) {
 678        return 0;
 679    }
 680
 681    (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr,
 682                      videosrc ? s->cirrus_blt_srcaddr : 0,
 683                      s->cirrus_blt_dstpitch, 0,
 684                      s->cirrus_blt_width, s->cirrus_blt_height);
 685    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
 686                             s->cirrus_blt_dstpitch, s->cirrus_blt_width,
 687                             s->cirrus_blt_height);
 688    return 1;
 689}
 690
 691/* fill */
 692
 693static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
 694{
 695    cirrus_fill_t rop_func;
 696
 697    if (blit_is_unsafe(s, true)) {
 698        return 0;
 699    }
 700    rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
 701    rop_func(s, s->cirrus_blt_dstaddr,
 702             s->cirrus_blt_dstpitch,
 703             s->cirrus_blt_width, s->cirrus_blt_height);
 704    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
 705                             s->cirrus_blt_dstpitch, s->cirrus_blt_width,
 706                             s->cirrus_blt_height);
 707    cirrus_bitblt_reset(s);
 708    return 1;
 709}
 710
 711/***************************************
 712 *
 713 *  bitblt (video-to-video)
 714 *
 715 ***************************************/
 716
 717static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
 718{
 719    return cirrus_bitblt_common_patterncopy(s);
 720}
 721
 722static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
 723{
 724    int sx = 0, sy = 0;
 725    int dx = 0, dy = 0;
 726    int depth = 0;
 727    int notify = 0;
 728
 729    /* make sure to only copy if it's a plain copy ROP */
 730    if (*s->cirrus_rop == cirrus_bitblt_rop_fwd_src ||
 731        *s->cirrus_rop == cirrus_bitblt_rop_bkwd_src) {
 732
 733        int width, height;
 734
 735        depth = s->vga.get_bpp(&s->vga) / 8;
 736        if (!depth) {
 737            return 0;
 738        }
 739        s->vga.get_resolution(&s->vga, &width, &height);
 740
 741        /* extra x, y */
 742        sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;
 743        sy = (src / ABS(s->cirrus_blt_srcpitch));
 744        dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;
 745        dy = (dst / ABS(s->cirrus_blt_dstpitch));
 746
 747        /* normalize width */
 748        w /= depth;
 749
 750        /* if we're doing a backward copy, we have to adjust
 751           our x/y to be the upper left corner (instead of the lower
 752           right corner) */
 753        if (s->cirrus_blt_dstpitch < 0) {
 754            sx -= (s->cirrus_blt_width / depth) - 1;
 755            dx -= (s->cirrus_blt_width / depth) - 1;
 756            sy -= s->cirrus_blt_height - 1;
 757            dy -= s->cirrus_blt_height - 1;
 758        }
 759
 760        /* are we in the visible portion of memory? */
 761        if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
 762            (sx + w) <= width && (sy + h) <= height &&
 763            (dx + w) <= width && (dy + h) <= height) {
 764            notify = 1;
 765        }
 766    }
 767
 768    (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr,
 769                      s->cirrus_blt_srcaddr,
 770                      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
 771                      s->cirrus_blt_width, s->cirrus_blt_height);
 772
 773    if (notify) {
 774        dpy_gfx_update(s->vga.con, dx, dy,
 775                       s->cirrus_blt_width / depth,
 776                       s->cirrus_blt_height);
 777    }
 778
 779    /* we don't have to notify the display that this portion has
 780       changed since qemu_console_copy implies this */
 781
 782    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
 783                                s->cirrus_blt_dstpitch, s->cirrus_blt_width,
 784                                s->cirrus_blt_height);
 785
 786    return 1;
 787}
 788
 789static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
 790{
 791    if (blit_is_unsafe(s, false))
 792        return 0;
 793
 794    return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.start_addr,
 795            s->cirrus_blt_srcaddr - s->vga.start_addr,
 796            s->cirrus_blt_width, s->cirrus_blt_height);
 797}
 798
 799/***************************************
 800 *
 801 *  bitblt (cpu-to-video)
 802 *
 803 ***************************************/
 804
 805static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
 806{
 807    int copy_count;
 808    uint8_t *end_ptr;
 809
 810    if (s->cirrus_srccounter > 0) {
 811        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
 812            cirrus_bitblt_common_patterncopy(s);
 813        the_end:
 814            s->cirrus_srccounter = 0;
 815            cirrus_bitblt_reset(s);
 816        } else {
 817            /* at least one scan line */
 818            do {
 819                (*s->cirrus_rop)(s, s->cirrus_blt_dstaddr,
 820                                 0, 0, 0, s->cirrus_blt_width, 1);
 821                cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
 822                                         s->cirrus_blt_width, 1);
 823                s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
 824                s->cirrus_srccounter -= s->cirrus_blt_srcpitch;
 825                if (s->cirrus_srccounter <= 0)
 826                    goto the_end;
 827                /* more bytes than needed can be transferred because of
 828                   word alignment, so we keep them for the next line */
 829                /* XXX: keep alignment to speed up transfer */
 830                end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
 831                copy_count = s->cirrus_srcptr_end - end_ptr;
 832                memmove(s->cirrus_bltbuf, end_ptr, copy_count);
 833                s->cirrus_srcptr = s->cirrus_bltbuf + copy_count;
 834                s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
 835            } while (s->cirrus_srcptr >= s->cirrus_srcptr_end);
 836        }
 837    }
 838}
 839
 840/***************************************
 841 *
 842 *  bitblt wrapper
 843 *
 844 ***************************************/
 845
 846static void cirrus_bitblt_reset(CirrusVGAState * s)
 847{
 848    int need_update;
 849
 850    s->vga.gr[0x31] &=
 851        ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED);
 852    need_update = s->cirrus_srcptr != &s->cirrus_bltbuf[0]
 853        || s->cirrus_srcptr_end != &s->cirrus_bltbuf[0];
 854    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
 855    s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
 856    s->cirrus_srccounter = 0;
 857    if (!need_update)
 858        return;
 859    cirrus_update_memory_access(s);
 860}
 861
 862static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
 863{
 864    int w;
 865
 866    if (blit_is_unsafe(s, true)) {
 867        return 0;
 868    }
 869
 870    s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
 871    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
 872    s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
 873
 874    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
 875        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
 876            s->cirrus_blt_srcpitch = 8;
 877        } else {
 878            /* XXX: check for 24 bpp */
 879            s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth;
 880        }
 881        s->cirrus_srccounter = s->cirrus_blt_srcpitch;
 882    } else {
 883        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
 884            w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth;
 885            if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)
 886                s->cirrus_blt_srcpitch = ((w + 31) >> 5);
 887            else
 888                s->cirrus_blt_srcpitch = ((w + 7) >> 3);
 889        } else {
 890            /* always align input size to 32 bits */
 891            s->cirrus_blt_srcpitch = (s->cirrus_blt_width + 3) & ~3;
 892        }
 893        s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
 894    }
 895
 896    /* the blit_is_unsafe call above should catch this */
 897    assert(s->cirrus_blt_srcpitch <= CIRRUS_BLTBUFSIZE);
 898
 899    s->cirrus_srcptr = s->cirrus_bltbuf;
 900    s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
 901    cirrus_update_memory_access(s);
 902    return 1;
 903}
 904
 905static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
 906{
 907    /* XXX */
 908    qemu_log_mask(LOG_UNIMP,
 909                  "cirrus: bitblt (video to cpu) is not implemented\n");
 910    return 0;
 911}
 912
 913static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
 914{
 915    int ret;
 916
 917    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
 918        ret = cirrus_bitblt_videotovideo_patterncopy(s);
 919    } else {
 920        ret = cirrus_bitblt_videotovideo_copy(s);
 921    }
 922    if (ret)
 923        cirrus_bitblt_reset(s);
 924    return ret;
 925}
 926
 927static void cirrus_bitblt_start(CirrusVGAState * s)
 928{
 929    uint8_t blt_rop;
 930
 931    if (!s->enable_blitter) {
 932        goto bitblt_ignore;
 933    }
 934
 935    s->vga.gr[0x31] |= CIRRUS_BLT_BUSY;
 936
 937    s->cirrus_blt_width = (s->vga.gr[0x20] | (s->vga.gr[0x21] << 8)) + 1;
 938    s->cirrus_blt_height = (s->vga.gr[0x22] | (s->vga.gr[0x23] << 8)) + 1;
 939    s->cirrus_blt_dstpitch = (s->vga.gr[0x24] | (s->vga.gr[0x25] << 8));
 940    s->cirrus_blt_srcpitch = (s->vga.gr[0x26] | (s->vga.gr[0x27] << 8));
 941    s->cirrus_blt_dstaddr =
 942        (s->vga.gr[0x28] | (s->vga.gr[0x29] << 8) | (s->vga.gr[0x2a] << 16));
 943    s->cirrus_blt_srcaddr =
 944        (s->vga.gr[0x2c] | (s->vga.gr[0x2d] << 8) | (s->vga.gr[0x2e] << 16));
 945    s->cirrus_blt_mode = s->vga.gr[0x30];
 946    s->cirrus_blt_modeext = s->vga.gr[0x33];
 947    blt_rop = s->vga.gr[0x32];
 948
 949    s->cirrus_blt_dstaddr &= s->cirrus_addr_mask;
 950    s->cirrus_blt_srcaddr &= s->cirrus_addr_mask;
 951
 952    trace_vga_cirrus_bitblt_start(blt_rop,
 953                                  s->cirrus_blt_mode,
 954                                  s->cirrus_blt_modeext,
 955                                  s->cirrus_blt_width,
 956                                  s->cirrus_blt_height,
 957                                  s->cirrus_blt_dstpitch,
 958                                  s->cirrus_blt_srcpitch,
 959                                  s->cirrus_blt_dstaddr,
 960                                  s->cirrus_blt_srcaddr,
 961                                  s->vga.gr[0x2f]);
 962
 963    switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
 964    case CIRRUS_BLTMODE_PIXELWIDTH8:
 965        s->cirrus_blt_pixelwidth = 1;
 966        break;
 967    case CIRRUS_BLTMODE_PIXELWIDTH16:
 968        s->cirrus_blt_pixelwidth = 2;
 969        break;
 970    case CIRRUS_BLTMODE_PIXELWIDTH24:
 971        s->cirrus_blt_pixelwidth = 3;
 972        break;
 973    case CIRRUS_BLTMODE_PIXELWIDTH32:
 974        s->cirrus_blt_pixelwidth = 4;
 975        break;
 976    default:
 977        qemu_log_mask(LOG_GUEST_ERROR,
 978                      "cirrus: bitblt - pixel width is unknown\n");
 979        goto bitblt_ignore;
 980    }
 981    s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
 982
 983    if ((s->
 984         cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
 985                            CIRRUS_BLTMODE_MEMSYSDEST))
 986        == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
 987        qemu_log_mask(LOG_UNIMP,
 988                      "cirrus: bitblt - memory-to-memory copy requested\n");
 989        goto bitblt_ignore;
 990    }
 991
 992    if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
 993        (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST |
 994                               CIRRUS_BLTMODE_TRANSPARENTCOMP |
 995                               CIRRUS_BLTMODE_PATTERNCOPY |
 996                               CIRRUS_BLTMODE_COLOREXPAND)) ==
 997         (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
 998        cirrus_bitblt_fgcol(s);
 999        cirrus_bitblt_solidfill(s, blt_rop);
1000    } else {
1001        if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND |
1002                                   CIRRUS_BLTMODE_PATTERNCOPY)) ==
1003            CIRRUS_BLTMODE_COLOREXPAND) {
1004
1005            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
1006                if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
1007                    cirrus_bitblt_bgcol(s);
1008                else
1009                    cirrus_bitblt_fgcol(s);
1010                s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1011            } else {
1012                cirrus_bitblt_fgcol(s);
1013                cirrus_bitblt_bgcol(s);
1014                s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1015            }
1016        } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
1017            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
1018                if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
1019                    if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
1020                        cirrus_bitblt_bgcol(s);
1021                    else
1022                        cirrus_bitblt_fgcol(s);
1023                    s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1024                } else {
1025                    cirrus_bitblt_fgcol(s);
1026                    cirrus_bitblt_bgcol(s);
1027                    s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1028                }
1029            } else {
1030                s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1031            }
1032        } else {
1033            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
1034                if (s->cirrus_blt_pixelwidth > 2) {
1035                    qemu_log_mask(LOG_GUEST_ERROR,
1036                                  "cirrus: src transparent without colorexpand "
1037                                  "must be 8bpp or 16bpp\n");
1038                    goto bitblt_ignore;
1039                }
1040                if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
1041                    s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
1042                    s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
1043                    s->cirrus_rop = cirrus_bkwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1044                } else {
1045                    s->cirrus_rop = cirrus_fwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1046                }
1047            } else {
1048                if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
1049                    s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
1050                    s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
1051                    s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]];
1052                } else {
1053                    s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]];
1054                }
1055            }
1056        }
1057        // setup bitblt engine.
1058        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
1059            if (!cirrus_bitblt_cputovideo(s))
1060                goto bitblt_ignore;
1061        } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
1062            if (!cirrus_bitblt_videotocpu(s))
1063                goto bitblt_ignore;
1064        } else {
1065            if (!cirrus_bitblt_videotovideo(s))
1066                goto bitblt_ignore;
1067        }
1068    }
1069    return;
1070  bitblt_ignore:;
1071    cirrus_bitblt_reset(s);
1072}
1073
1074static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
1075{
1076    unsigned old_value;
1077
1078    old_value = s->vga.gr[0x31];
1079    s->vga.gr[0x31] = reg_value;
1080
1081    if (((old_value & CIRRUS_BLT_RESET) != 0) &&
1082        ((reg_value & CIRRUS_BLT_RESET) == 0)) {
1083        cirrus_bitblt_reset(s);
1084    } else if (((old_value & CIRRUS_BLT_START) == 0) &&
1085               ((reg_value & CIRRUS_BLT_START) != 0)) {
1086        cirrus_bitblt_start(s);
1087    }
1088}
1089
1090
1091/***************************************
1092 *
1093 *  basic parameters
1094 *
1095 ***************************************/
1096
1097static void cirrus_get_offsets(VGACommonState *s1,
1098                               uint32_t *pline_offset,
1099                               uint32_t *pstart_addr,
1100                               uint32_t *pline_compare)
1101{
1102    CirrusVGAState * s = container_of(s1, CirrusVGAState, vga);
1103    uint32_t start_addr, line_offset, line_compare;
1104
1105    line_offset = s->vga.cr[0x13]
1106        | ((s->vga.cr[0x1b] & 0x10) << 4);
1107    line_offset <<= 3;
1108    *pline_offset = line_offset;
1109
1110    start_addr = (s->vga.cr[0x0c] << 8)
1111        | s->vga.cr[0x0d]
1112        | ((s->vga.cr[0x1b] & 0x01) << 16)
1113        | ((s->vga.cr[0x1b] & 0x0c) << 15)
1114        | ((s->vga.cr[0x1d] & 0x80) << 12);
1115    *pstart_addr = start_addr;
1116
1117    line_compare = s->vga.cr[0x18] |
1118        ((s->vga.cr[0x07] & 0x10) << 4) |
1119        ((s->vga.cr[0x09] & 0x40) << 3);
1120    *pline_compare = line_compare;
1121}
1122
1123static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
1124{
1125    uint32_t ret = 16;
1126
1127    switch (s->cirrus_hidden_dac_data & 0xf) {
1128    case 0:
1129        ret = 15;
1130        break;                  /* Sierra HiColor */
1131    case 1:
1132        ret = 16;
1133        break;                  /* XGA HiColor */
1134    default:
1135        qemu_log_mask(LOG_GUEST_ERROR,
1136                      "cirrus: invalid DAC value 0x%x in 16bpp\n",
1137                      (s->cirrus_hidden_dac_data & 0xf));
1138        ret = 15;               /* XXX */
1139        break;
1140    }
1141    return ret;
1142}
1143
1144static int cirrus_get_bpp(VGACommonState *s1)
1145{
1146    CirrusVGAState * s = container_of(s1, CirrusVGAState, vga);
1147    uint32_t ret = 8;
1148
1149    if ((s->vga.sr[0x07] & 0x01) != 0) {
1150        /* Cirrus SVGA */
1151        switch (s->vga.sr[0x07] & CIRRUS_SR7_BPP_MASK) {
1152        case CIRRUS_SR7_BPP_8:
1153            ret = 8;
1154            break;
1155        case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
1156            ret = cirrus_get_bpp16_depth(s);
1157            break;
1158        case CIRRUS_SR7_BPP_24:
1159            ret = 24;
1160            break;
1161        case CIRRUS_SR7_BPP_16:
1162            ret = cirrus_get_bpp16_depth(s);
1163            break;
1164        case CIRRUS_SR7_BPP_32:
1165            ret = 32;
1166            break;
1167        default:
1168#ifdef DEBUG_CIRRUS
1169            printf("cirrus: unknown bpp - sr7=%x\n", s->vga.sr[0x7]);
1170#endif
1171            ret = 8;
1172            break;
1173        }
1174    } else {
1175        /* VGA */
1176        ret = 0;
1177    }
1178
1179    return ret;
1180}
1181
1182static void cirrus_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1183{
1184    int width, height;
1185
1186    width = (s->cr[0x01] + 1) * 8;
1187    height = s->cr[0x12] |
1188        ((s->cr[0x07] & 0x02) << 7) |
1189        ((s->cr[0x07] & 0x40) << 3);
1190    height = (height + 1);
1191    /* interlace support */
1192    if (s->cr[0x1a] & 0x01)
1193        height = height * 2;
1194    *pwidth = width;
1195    *pheight = height;
1196}
1197
1198/***************************************
1199 *
1200 * bank memory
1201 *
1202 ***************************************/
1203
1204static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
1205{
1206    unsigned offset;
1207    unsigned limit;
1208
1209    if ((s->vga.gr[0x0b] & 0x01) != 0)  /* dual bank */
1210        offset = s->vga.gr[0x09 + bank_index];
1211    else                        /* single bank */
1212        offset = s->vga.gr[0x09];
1213
1214    if ((s->vga.gr[0x0b] & 0x20) != 0)
1215        offset <<= 14;
1216    else
1217        offset <<= 12;
1218
1219    if (s->real_vram_size <= offset)
1220        limit = 0;
1221    else
1222        limit = s->real_vram_size - offset;
1223
1224    if (((s->vga.gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
1225        if (limit > 0x8000) {
1226            offset += 0x8000;
1227            limit -= 0x8000;
1228        } else {
1229            limit = 0;
1230        }
1231    }
1232
1233    if (limit > 0) {
1234        s->cirrus_bank_base[bank_index] = offset;
1235        s->cirrus_bank_limit[bank_index] = limit;
1236    } else {
1237        s->cirrus_bank_base[bank_index] = 0;
1238        s->cirrus_bank_limit[bank_index] = 0;
1239    }
1240}
1241
1242/***************************************
1243 *
1244 *  I/O access between 0x3c4-0x3c5
1245 *
1246 ***************************************/
1247
1248static int cirrus_vga_read_sr(CirrusVGAState * s)
1249{
1250    switch (s->vga.sr_index) {
1251    case 0x00:                  // Standard VGA
1252    case 0x01:                  // Standard VGA
1253    case 0x02:                  // Standard VGA
1254    case 0x03:                  // Standard VGA
1255    case 0x04:                  // Standard VGA
1256        return s->vga.sr[s->vga.sr_index];
1257    case 0x06:                  // Unlock Cirrus extensions
1258        return s->vga.sr[s->vga.sr_index];
1259    case 0x10:
1260    case 0x30:
1261    case 0x50:
1262    case 0x70:                  // Graphics Cursor X
1263    case 0x90:
1264    case 0xb0:
1265    case 0xd0:
1266    case 0xf0:                  // Graphics Cursor X
1267        return s->vga.sr[0x10];
1268    case 0x11:
1269    case 0x31:
1270    case 0x51:
1271    case 0x71:                  // Graphics Cursor Y
1272    case 0x91:
1273    case 0xb1:
1274    case 0xd1:
1275    case 0xf1:                  // Graphics Cursor Y
1276        return s->vga.sr[0x11];
1277    case 0x05:                  // ???
1278    case 0x07:                  // Extended Sequencer Mode
1279    case 0x08:                  // EEPROM Control
1280    case 0x09:                  // Scratch Register 0
1281    case 0x0a:                  // Scratch Register 1
1282    case 0x0b:                  // VCLK 0
1283    case 0x0c:                  // VCLK 1
1284    case 0x0d:                  // VCLK 2
1285    case 0x0e:                  // VCLK 3
1286    case 0x0f:                  // DRAM Control
1287    case 0x12:                  // Graphics Cursor Attribute
1288    case 0x13:                  // Graphics Cursor Pattern Address
1289    case 0x14:                  // Scratch Register 2
1290    case 0x15:                  // Scratch Register 3
1291    case 0x16:                  // Performance Tuning Register
1292    case 0x17:                  // Configuration Readback and Extended Control
1293    case 0x18:                  // Signature Generator Control
1294    case 0x19:                  // Signal Generator Result
1295    case 0x1a:                  // Signal Generator Result
1296    case 0x1b:                  // VCLK 0 Denominator & Post
1297    case 0x1c:                  // VCLK 1 Denominator & Post
1298    case 0x1d:                  // VCLK 2 Denominator & Post
1299    case 0x1e:                  // VCLK 3 Denominator & Post
1300    case 0x1f:                  // BIOS Write Enable and MCLK select
1301#ifdef DEBUG_CIRRUS
1302        printf("cirrus: handled inport sr_index %02x\n", s->vga.sr_index);
1303#endif
1304        return s->vga.sr[s->vga.sr_index];
1305    default:
1306        qemu_log_mask(LOG_GUEST_ERROR,
1307                      "cirrus: inport sr_index 0x%02x\n", s->vga.sr_index);
1308        return 0xff;
1309    }
1310}
1311
1312static void cirrus_vga_write_sr(CirrusVGAState * s, uint32_t val)
1313{
1314    switch (s->vga.sr_index) {
1315    case 0x00:                  // Standard VGA
1316    case 0x01:                  // Standard VGA
1317    case 0x02:                  // Standard VGA
1318    case 0x03:                  // Standard VGA
1319    case 0x04:                  // Standard VGA
1320        s->vga.sr[s->vga.sr_index] = val & sr_mask[s->vga.sr_index];
1321        if (s->vga.sr_index == 1)
1322            s->vga.update_retrace_info(&s->vga);
1323        break;
1324    case 0x06:                  // Unlock Cirrus extensions
1325        val &= 0x17;
1326        if (val == 0x12) {
1327            s->vga.sr[s->vga.sr_index] = 0x12;
1328        } else {
1329            s->vga.sr[s->vga.sr_index] = 0x0f;
1330        }
1331        break;
1332    case 0x10:
1333    case 0x30:
1334    case 0x50:
1335    case 0x70:                  // Graphics Cursor X
1336    case 0x90:
1337    case 0xb0:
1338    case 0xd0:
1339    case 0xf0:                  // Graphics Cursor X
1340        s->vga.sr[0x10] = val;
1341        s->vga.hw_cursor_x = (val << 3) | (s->vga.sr_index >> 5);
1342        break;
1343    case 0x11:
1344    case 0x31:
1345    case 0x51:
1346    case 0x71:                  // Graphics Cursor Y
1347    case 0x91:
1348    case 0xb1:
1349    case 0xd1:
1350    case 0xf1:                  // Graphics Cursor Y
1351        s->vga.sr[0x11] = val;
1352        s->vga.hw_cursor_y = (val << 3) | (s->vga.sr_index >> 5);
1353        break;
1354    case 0x07:                  // Extended Sequencer Mode
1355        cirrus_update_memory_access(s);
1356        /* fall through */
1357    case 0x08:                  // EEPROM Control
1358    case 0x09:                  // Scratch Register 0
1359    case 0x0a:                  // Scratch Register 1
1360    case 0x0b:                  // VCLK 0
1361    case 0x0c:                  // VCLK 1
1362    case 0x0d:                  // VCLK 2
1363    case 0x0e:                  // VCLK 3
1364    case 0x0f:                  // DRAM Control
1365    case 0x13:                  // Graphics Cursor Pattern Address
1366    case 0x14:                  // Scratch Register 2
1367    case 0x15:                  // Scratch Register 3
1368    case 0x16:                  // Performance Tuning Register
1369    case 0x18:                  // Signature Generator Control
1370    case 0x19:                  // Signature Generator Result
1371    case 0x1a:                  // Signature Generator Result
1372    case 0x1b:                  // VCLK 0 Denominator & Post
1373    case 0x1c:                  // VCLK 1 Denominator & Post
1374    case 0x1d:                  // VCLK 2 Denominator & Post
1375    case 0x1e:                  // VCLK 3 Denominator & Post
1376    case 0x1f:                  // BIOS Write Enable and MCLK select
1377        s->vga.sr[s->vga.sr_index] = val;
1378#ifdef DEBUG_CIRRUS
1379        printf("cirrus: handled outport sr_index %02x, sr_value %02x\n",
1380               s->vga.sr_index, val);
1381#endif
1382        break;
1383    case 0x12:                  // Graphics Cursor Attribute
1384        s->vga.sr[0x12] = val;
1385        s->vga.force_shadow = !!(val & CIRRUS_CURSOR_SHOW);
1386#ifdef DEBUG_CIRRUS
1387        printf("cirrus: cursor ctl SR12=%02x (force shadow: %d)\n",
1388               val, s->vga.force_shadow);
1389#endif
1390        break;
1391    case 0x17:                  // Configuration Readback and Extended Control
1392        s->vga.sr[s->vga.sr_index] = (s->vga.sr[s->vga.sr_index] & 0x38)
1393                                   | (val & 0xc7);
1394        cirrus_update_memory_access(s);
1395        break;
1396    default:
1397        qemu_log_mask(LOG_GUEST_ERROR,
1398                      "cirrus: outport sr_index 0x%02x, sr_value 0x%02x\n",
1399                      s->vga.sr_index, val);
1400        break;
1401    }
1402}
1403
1404/***************************************
1405 *
1406 *  I/O access at 0x3c6
1407 *
1408 ***************************************/
1409
1410static int cirrus_read_hidden_dac(CirrusVGAState * s)
1411{
1412    if (++s->cirrus_hidden_dac_lockindex == 5) {
1413        s->cirrus_hidden_dac_lockindex = 0;
1414        return s->cirrus_hidden_dac_data;
1415    }
1416    return 0xff;
1417}
1418
1419static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
1420{
1421    if (s->cirrus_hidden_dac_lockindex == 4) {
1422        s->cirrus_hidden_dac_data = reg_value;
1423#if defined(DEBUG_CIRRUS)
1424        printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
1425#endif
1426    }
1427    s->cirrus_hidden_dac_lockindex = 0;
1428}
1429
1430/***************************************
1431 *
1432 *  I/O access at 0x3c9
1433 *
1434 ***************************************/
1435
1436static int cirrus_vga_read_palette(CirrusVGAState * s)
1437{
1438    int val;
1439
1440    if ((s->vga.sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) {
1441        val = s->cirrus_hidden_palette[(s->vga.dac_read_index & 0x0f) * 3 +
1442                                       s->vga.dac_sub_index];
1443    } else {
1444        val = s->vga.palette[s->vga.dac_read_index * 3 + s->vga.dac_sub_index];
1445    }
1446    if (++s->vga.dac_sub_index == 3) {
1447        s->vga.dac_sub_index = 0;
1448        s->vga.dac_read_index++;
1449    }
1450    return val;
1451}
1452
1453static void cirrus_vga_write_palette(CirrusVGAState * s, int reg_value)
1454{
1455    s->vga.dac_cache[s->vga.dac_sub_index] = reg_value;
1456    if (++s->vga.dac_sub_index == 3) {
1457        if ((s->vga.sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) {
1458            memcpy(&s->cirrus_hidden_palette[(s->vga.dac_write_index & 0x0f) * 3],
1459                   s->vga.dac_cache, 3);
1460        } else {
1461            memcpy(&s->vga.palette[s->vga.dac_write_index * 3], s->vga.dac_cache, 3);
1462        }
1463        /* XXX update cursor */
1464        s->vga.dac_sub_index = 0;
1465        s->vga.dac_write_index++;
1466    }
1467}
1468
1469/***************************************
1470 *
1471 *  I/O access between 0x3ce-0x3cf
1472 *
1473 ***************************************/
1474
1475static int cirrus_vga_read_gr(CirrusVGAState * s, unsigned reg_index)
1476{
1477    switch (reg_index) {
1478    case 0x00: // Standard VGA, BGCOLOR 0x000000ff
1479        return s->cirrus_shadow_gr0;
1480    case 0x01: // Standard VGA, FGCOLOR 0x000000ff
1481        return s->cirrus_shadow_gr1;
1482    case 0x02:                  // Standard VGA
1483    case 0x03:                  // Standard VGA
1484    case 0x04:                  // Standard VGA
1485    case 0x06:                  // Standard VGA
1486    case 0x07:                  // Standard VGA
1487    case 0x08:                  // Standard VGA
1488        return s->vga.gr[s->vga.gr_index];
1489    case 0x05:                  // Standard VGA, Cirrus extended mode
1490    default:
1491        break;
1492    }
1493
1494    if (reg_index < 0x3a) {
1495        return s->vga.gr[reg_index];
1496    } else {
1497        qemu_log_mask(LOG_GUEST_ERROR,
1498                      "cirrus: inport gr_index 0x%02x\n", reg_index);
1499        return 0xff;
1500    }
1501}
1502
1503static void
1504cirrus_vga_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1505{
1506    trace_vga_cirrus_write_gr(reg_index, reg_value);
1507    switch (reg_index) {
1508    case 0x00:                  // Standard VGA, BGCOLOR 0x000000ff
1509        s->vga.gr[reg_index] = reg_value & gr_mask[reg_index];
1510        s->cirrus_shadow_gr0 = reg_value;
1511        break;
1512    case 0x01:                  // Standard VGA, FGCOLOR 0x000000ff
1513        s->vga.gr[reg_index] = reg_value & gr_mask[reg_index];
1514        s->cirrus_shadow_gr1 = reg_value;
1515        break;
1516    case 0x02:                  // Standard VGA
1517    case 0x03:                  // Standard VGA
1518    case 0x04:                  // Standard VGA
1519    case 0x06:                  // Standard VGA
1520    case 0x07:                  // Standard VGA
1521    case 0x08:                  // Standard VGA
1522        s->vga.gr[reg_index] = reg_value & gr_mask[reg_index];
1523        break;
1524    case 0x05:                  // Standard VGA, Cirrus extended mode
1525        s->vga.gr[reg_index] = reg_value & 0x7f;
1526        cirrus_update_memory_access(s);
1527        break;
1528    case 0x09:                  // bank offset #0
1529    case 0x0A:                  // bank offset #1
1530        s->vga.gr[reg_index] = reg_value;
1531        cirrus_update_bank_ptr(s, 0);
1532        cirrus_update_bank_ptr(s, 1);
1533        cirrus_update_memory_access(s);
1534        break;
1535    case 0x0B:
1536        s->vga.gr[reg_index] = reg_value;
1537        cirrus_update_bank_ptr(s, 0);
1538        cirrus_update_bank_ptr(s, 1);
1539        cirrus_update_memory_access(s);
1540        break;
1541    case 0x10:                  // BGCOLOR 0x0000ff00
1542    case 0x11:                  // FGCOLOR 0x0000ff00
1543    case 0x12:                  // BGCOLOR 0x00ff0000
1544    case 0x13:                  // FGCOLOR 0x00ff0000
1545    case 0x14:                  // BGCOLOR 0xff000000
1546    case 0x15:                  // FGCOLOR 0xff000000
1547    case 0x20:                  // BLT WIDTH 0x0000ff
1548    case 0x22:                  // BLT HEIGHT 0x0000ff
1549    case 0x24:                  // BLT DEST PITCH 0x0000ff
1550    case 0x26:                  // BLT SRC PITCH 0x0000ff
1551    case 0x28:                  // BLT DEST ADDR 0x0000ff
1552    case 0x29:                  // BLT DEST ADDR 0x00ff00
1553    case 0x2c:                  // BLT SRC ADDR 0x0000ff
1554    case 0x2d:                  // BLT SRC ADDR 0x00ff00
1555    case 0x2f:                  // BLT WRITEMASK
1556    case 0x30:                  // BLT MODE
1557    case 0x32:                  // RASTER OP
1558    case 0x33:                  // BLT MODEEXT
1559    case 0x34:                  // BLT TRANSPARENT COLOR 0x00ff
1560    case 0x35:                  // BLT TRANSPARENT COLOR 0xff00
1561    case 0x38:                  // BLT TRANSPARENT COLOR MASK 0x00ff
1562    case 0x39:                  // BLT TRANSPARENT COLOR MASK 0xff00
1563        s->vga.gr[reg_index] = reg_value;
1564        break;
1565    case 0x21:                  // BLT WIDTH 0x001f00
1566    case 0x23:                  // BLT HEIGHT 0x001f00
1567    case 0x25:                  // BLT DEST PITCH 0x001f00
1568    case 0x27:                  // BLT SRC PITCH 0x001f00
1569        s->vga.gr[reg_index] = reg_value & 0x1f;
1570        break;
1571    case 0x2a:                  // BLT DEST ADDR 0x3f0000
1572        s->vga.gr[reg_index] = reg_value & 0x3f;
1573        /* if auto start mode, starts bit blt now */
1574        if (s->vga.gr[0x31] & CIRRUS_BLT_AUTOSTART) {
1575            cirrus_bitblt_start(s);
1576        }
1577        break;
1578    case 0x2e:                  // BLT SRC ADDR 0x3f0000
1579        s->vga.gr[reg_index] = reg_value & 0x3f;
1580        break;
1581    case 0x31:                  // BLT STATUS/START
1582        cirrus_write_bitblt(s, reg_value);
1583        break;
1584    default:
1585        qemu_log_mask(LOG_GUEST_ERROR,
1586                      "cirrus: outport gr_index 0x%02x, gr_value 0x%02x\n",
1587                      reg_index, reg_value);
1588        break;
1589    }
1590}
1591
1592/***************************************
1593 *
1594 *  I/O access between 0x3d4-0x3d5
1595 *
1596 ***************************************/
1597
1598static int cirrus_vga_read_cr(CirrusVGAState * s, unsigned reg_index)
1599{
1600    switch (reg_index) {
1601    case 0x00:                  // Standard VGA
1602    case 0x01:                  // Standard VGA
1603    case 0x02:                  // Standard VGA
1604    case 0x03:                  // Standard VGA
1605    case 0x04:                  // Standard VGA
1606    case 0x05:                  // Standard VGA
1607    case 0x06:                  // Standard VGA
1608    case 0x07:                  // Standard VGA
1609    case 0x08:                  // Standard VGA
1610    case 0x09:                  // Standard VGA
1611    case 0x0a:                  // Standard VGA
1612    case 0x0b:                  // Standard VGA
1613    case 0x0c:                  // Standard VGA
1614    case 0x0d:                  // Standard VGA
1615    case 0x0e:                  // Standard VGA
1616    case 0x0f:                  // Standard VGA
1617    case 0x10:                  // Standard VGA
1618    case 0x11:                  // Standard VGA
1619    case 0x12:                  // Standard VGA
1620    case 0x13:                  // Standard VGA
1621    case 0x14:                  // Standard VGA
1622    case 0x15:                  // Standard VGA
1623    case 0x16:                  // Standard VGA
1624    case 0x17:                  // Standard VGA
1625    case 0x18:                  // Standard VGA
1626        return s->vga.cr[s->vga.cr_index];
1627    case 0x24:                  // Attribute Controller Toggle Readback (R)
1628        return (s->vga.ar_flip_flop << 7);
1629    case 0x19:                  // Interlace End
1630    case 0x1a:                  // Miscellaneous Control
1631    case 0x1b:                  // Extended Display Control
1632    case 0x1c:                  // Sync Adjust and Genlock
1633    case 0x1d:                  // Overlay Extended Control
1634    case 0x22:                  // Graphics Data Latches Readback (R)
1635    case 0x25:                  // Part Status
1636    case 0x27:                  // Part ID (R)
1637        return s->vga.cr[s->vga.cr_index];
1638    case 0x26:                  // Attribute Controller Index Readback (R)
1639        return s->vga.ar_index & 0x3f;
1640        break;
1641    default:
1642        qemu_log_mask(LOG_GUEST_ERROR,
1643                      "cirrus: inport cr_index 0x%02x\n", reg_index);
1644        return 0xff;
1645    }
1646}
1647
1648static void cirrus_vga_write_cr(CirrusVGAState * s, int reg_value)
1649{
1650    switch (s->vga.cr_index) {
1651    case 0x00:                  // Standard VGA
1652    case 0x01:                  // Standard VGA
1653    case 0x02:                  // Standard VGA
1654    case 0x03:                  // Standard VGA
1655    case 0x04:                  // Standard VGA
1656    case 0x05:                  // Standard VGA
1657    case 0x06:                  // Standard VGA
1658    case 0x07:                  // Standard VGA
1659    case 0x08:                  // Standard VGA
1660    case 0x09:                  // Standard VGA
1661    case 0x0a:                  // Standard VGA
1662    case 0x0b:                  // Standard VGA
1663    case 0x0c:                  // Standard VGA
1664    case 0x0d:                  // Standard VGA
1665    case 0x0e:                  // Standard VGA
1666    case 0x0f:                  // Standard VGA
1667    case 0x10:                  // Standard VGA
1668    case 0x11:                  // Standard VGA
1669    case 0x12:                  // Standard VGA
1670    case 0x13:                  // Standard VGA
1671    case 0x14:                  // Standard VGA
1672    case 0x15:                  // Standard VGA
1673    case 0x16:                  // Standard VGA
1674    case 0x17:                  // Standard VGA
1675    case 0x18:                  // Standard VGA
1676        /* handle CR0-7 protection */
1677        if ((s->vga.cr[0x11] & 0x80) && s->vga.cr_index <= 7) {
1678            /* can always write bit 4 of CR7 */
1679            if (s->vga.cr_index == 7)
1680                s->vga.cr[7] = (s->vga.cr[7] & ~0x10) | (reg_value & 0x10);
1681            return;
1682        }
1683        s->vga.cr[s->vga.cr_index] = reg_value;
1684        switch(s->vga.cr_index) {
1685        case 0x00:
1686        case 0x04:
1687        case 0x05:
1688        case 0x06:
1689        case 0x07:
1690        case 0x11:
1691        case 0x17:
1692            s->vga.update_retrace_info(&s->vga);
1693            break;
1694        }
1695        break;
1696    case 0x19:                  // Interlace End
1697    case 0x1a:                  // Miscellaneous Control
1698    case 0x1b:                  // Extended Display Control
1699    case 0x1c:                  // Sync Adjust and Genlock
1700    case 0x1d:                  // Overlay Extended Control
1701        s->vga.cr[s->vga.cr_index] = reg_value;
1702#ifdef DEBUG_CIRRUS
1703        printf("cirrus: handled outport cr_index %02x, cr_value %02x\n",
1704               s->vga.cr_index, reg_value);
1705#endif
1706        break;
1707    case 0x22:                  // Graphics Data Latches Readback (R)
1708    case 0x24:                  // Attribute Controller Toggle Readback (R)
1709    case 0x26:                  // Attribute Controller Index Readback (R)
1710    case 0x27:                  // Part ID (R)
1711        break;
1712    case 0x25:                  // Part Status
1713    default:
1714        qemu_log_mask(LOG_GUEST_ERROR,
1715                      "cirrus: outport cr_index 0x%02x, cr_value 0x%02x\n",
1716                      s->vga.cr_index, reg_value);
1717        break;
1718    }
1719}
1720
1721/***************************************
1722 *
1723 *  memory-mapped I/O (bitblt)
1724 *
1725 ***************************************/
1726
1727static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
1728{
1729    int value = 0xff;
1730
1731    switch (address) {
1732    case (CIRRUS_MMIO_BLTBGCOLOR + 0):
1733        value = cirrus_vga_read_gr(s, 0x00);
1734        break;
1735    case (CIRRUS_MMIO_BLTBGCOLOR + 1):
1736        value = cirrus_vga_read_gr(s, 0x10);
1737        break;
1738    case (CIRRUS_MMIO_BLTBGCOLOR + 2):
1739        value = cirrus_vga_read_gr(s, 0x12);
1740        break;
1741    case (CIRRUS_MMIO_BLTBGCOLOR + 3):
1742        value = cirrus_vga_read_gr(s, 0x14);
1743        break;
1744    case (CIRRUS_MMIO_BLTFGCOLOR + 0):
1745        value = cirrus_vga_read_gr(s, 0x01);
1746        break;
1747    case (CIRRUS_MMIO_BLTFGCOLOR + 1):
1748        value = cirrus_vga_read_gr(s, 0x11);
1749        break;
1750    case (CIRRUS_MMIO_BLTFGCOLOR + 2):
1751        value = cirrus_vga_read_gr(s, 0x13);
1752        break;
1753    case (CIRRUS_MMIO_BLTFGCOLOR + 3):
1754        value = cirrus_vga_read_gr(s, 0x15);
1755        break;
1756    case (CIRRUS_MMIO_BLTWIDTH + 0):
1757        value = cirrus_vga_read_gr(s, 0x20);
1758        break;
1759    case (CIRRUS_MMIO_BLTWIDTH + 1):
1760        value = cirrus_vga_read_gr(s, 0x21);
1761        break;
1762    case (CIRRUS_MMIO_BLTHEIGHT + 0):
1763        value = cirrus_vga_read_gr(s, 0x22);
1764        break;
1765    case (CIRRUS_MMIO_BLTHEIGHT + 1):
1766        value = cirrus_vga_read_gr(s, 0x23);
1767        break;
1768    case (CIRRUS_MMIO_BLTDESTPITCH + 0):
1769        value = cirrus_vga_read_gr(s, 0x24);
1770        break;
1771    case (CIRRUS_MMIO_BLTDESTPITCH + 1):
1772        value = cirrus_vga_read_gr(s, 0x25);
1773        break;
1774    case (CIRRUS_MMIO_BLTSRCPITCH + 0):
1775        value = cirrus_vga_read_gr(s, 0x26);
1776        break;
1777    case (CIRRUS_MMIO_BLTSRCPITCH + 1):
1778        value = cirrus_vga_read_gr(s, 0x27);
1779        break;
1780    case (CIRRUS_MMIO_BLTDESTADDR + 0):
1781        value = cirrus_vga_read_gr(s, 0x28);
1782        break;
1783    case (CIRRUS_MMIO_BLTDESTADDR + 1):
1784        value = cirrus_vga_read_gr(s, 0x29);
1785        break;
1786    case (CIRRUS_MMIO_BLTDESTADDR + 2):
1787        value = cirrus_vga_read_gr(s, 0x2a);
1788        break;
1789    case (CIRRUS_MMIO_BLTSRCADDR + 0):
1790        value = cirrus_vga_read_gr(s, 0x2c);
1791        break;
1792    case (CIRRUS_MMIO_BLTSRCADDR + 1):
1793        value = cirrus_vga_read_gr(s, 0x2d);
1794        break;
1795    case (CIRRUS_MMIO_BLTSRCADDR + 2):
1796        value = cirrus_vga_read_gr(s, 0x2e);
1797        break;
1798    case CIRRUS_MMIO_BLTWRITEMASK:
1799        value = cirrus_vga_read_gr(s, 0x2f);
1800        break;
1801    case CIRRUS_MMIO_BLTMODE:
1802        value = cirrus_vga_read_gr(s, 0x30);
1803        break;
1804    case CIRRUS_MMIO_BLTROP:
1805        value = cirrus_vga_read_gr(s, 0x32);
1806        break;
1807    case CIRRUS_MMIO_BLTMODEEXT:
1808        value = cirrus_vga_read_gr(s, 0x33);
1809        break;
1810    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
1811        value = cirrus_vga_read_gr(s, 0x34);
1812        break;
1813    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
1814        value = cirrus_vga_read_gr(s, 0x35);
1815        break;
1816    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
1817        value = cirrus_vga_read_gr(s, 0x38);
1818        break;
1819    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
1820        value = cirrus_vga_read_gr(s, 0x39);
1821        break;
1822    case CIRRUS_MMIO_BLTSTATUS:
1823        value = cirrus_vga_read_gr(s, 0x31);
1824        break;
1825    default:
1826        qemu_log_mask(LOG_GUEST_ERROR,
1827                      "cirrus: mmio read - address 0x%04x\n", address);
1828        break;
1829    }
1830
1831    trace_vga_cirrus_write_blt(address, value);
1832    return (uint8_t) value;
1833}
1834
1835static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address,
1836                                  uint8_t value)
1837{
1838    trace_vga_cirrus_write_blt(address, value);
1839    switch (address) {
1840    case (CIRRUS_MMIO_BLTBGCOLOR + 0):
1841        cirrus_vga_write_gr(s, 0x00, value);
1842        break;
1843    case (CIRRUS_MMIO_BLTBGCOLOR + 1):
1844        cirrus_vga_write_gr(s, 0x10, value);
1845        break;
1846    case (CIRRUS_MMIO_BLTBGCOLOR + 2):
1847        cirrus_vga_write_gr(s, 0x12, value);
1848        break;
1849    case (CIRRUS_MMIO_BLTBGCOLOR + 3):
1850        cirrus_vga_write_gr(s, 0x14, value);
1851        break;
1852    case (CIRRUS_MMIO_BLTFGCOLOR + 0):
1853        cirrus_vga_write_gr(s, 0x01, value);
1854        break;
1855    case (CIRRUS_MMIO_BLTFGCOLOR + 1):
1856        cirrus_vga_write_gr(s, 0x11, value);
1857        break;
1858    case (CIRRUS_MMIO_BLTFGCOLOR + 2):
1859        cirrus_vga_write_gr(s, 0x13, value);
1860        break;
1861    case (CIRRUS_MMIO_BLTFGCOLOR + 3):
1862        cirrus_vga_write_gr(s, 0x15, value);
1863        break;
1864    case (CIRRUS_MMIO_BLTWIDTH + 0):
1865        cirrus_vga_write_gr(s, 0x20, value);
1866        break;
1867    case (CIRRUS_MMIO_BLTWIDTH + 1):
1868        cirrus_vga_write_gr(s, 0x21, value);
1869        break;
1870    case (CIRRUS_MMIO_BLTHEIGHT + 0):
1871        cirrus_vga_write_gr(s, 0x22, value);
1872        break;
1873    case (CIRRUS_MMIO_BLTHEIGHT + 1):
1874        cirrus_vga_write_gr(s, 0x23, value);
1875        break;
1876    case (CIRRUS_MMIO_BLTDESTPITCH + 0):
1877        cirrus_vga_write_gr(s, 0x24, value);
1878        break;
1879    case (CIRRUS_MMIO_BLTDESTPITCH + 1):
1880        cirrus_vga_write_gr(s, 0x25, value);
1881        break;
1882    case (CIRRUS_MMIO_BLTSRCPITCH + 0):
1883        cirrus_vga_write_gr(s, 0x26, value);
1884        break;
1885    case (CIRRUS_MMIO_BLTSRCPITCH + 1):
1886        cirrus_vga_write_gr(s, 0x27, value);
1887        break;
1888    case (CIRRUS_MMIO_BLTDESTADDR + 0):
1889        cirrus_vga_write_gr(s, 0x28, value);
1890        break;
1891    case (CIRRUS_MMIO_BLTDESTADDR + 1):
1892        cirrus_vga_write_gr(s, 0x29, value);
1893        break;
1894    case (CIRRUS_MMIO_BLTDESTADDR + 2):
1895        cirrus_vga_write_gr(s, 0x2a, value);
1896        break;
1897    case (CIRRUS_MMIO_BLTDESTADDR + 3):
1898        /* ignored */
1899        break;
1900    case (CIRRUS_MMIO_BLTSRCADDR + 0):
1901        cirrus_vga_write_gr(s, 0x2c, value);
1902        break;
1903    case (CIRRUS_MMIO_BLTSRCADDR + 1):
1904        cirrus_vga_write_gr(s, 0x2d, value);
1905        break;
1906    case (CIRRUS_MMIO_BLTSRCADDR + 2):
1907        cirrus_vga_write_gr(s, 0x2e, value);
1908        break;
1909    case CIRRUS_MMIO_BLTWRITEMASK:
1910        cirrus_vga_write_gr(s, 0x2f, value);
1911        break;
1912    case CIRRUS_MMIO_BLTMODE:
1913        cirrus_vga_write_gr(s, 0x30, value);
1914        break;
1915    case CIRRUS_MMIO_BLTROP:
1916        cirrus_vga_write_gr(s, 0x32, value);
1917        break;
1918    case CIRRUS_MMIO_BLTMODEEXT:
1919        cirrus_vga_write_gr(s, 0x33, value);
1920        break;
1921    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
1922        cirrus_vga_write_gr(s, 0x34, value);
1923        break;
1924    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
1925        cirrus_vga_write_gr(s, 0x35, value);
1926        break;
1927    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
1928        cirrus_vga_write_gr(s, 0x38, value);
1929        break;
1930    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
1931        cirrus_vga_write_gr(s, 0x39, value);
1932        break;
1933    case CIRRUS_MMIO_BLTSTATUS:
1934        cirrus_vga_write_gr(s, 0x31, value);
1935        break;
1936    default:
1937        qemu_log_mask(LOG_GUEST_ERROR,
1938                      "cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n",
1939                      address, value);
1940        break;
1941    }
1942}
1943
1944/***************************************
1945 *
1946 *  write mode 4/5
1947 *
1948 ***************************************/
1949
1950static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
1951                                             unsigned mode,
1952                                             unsigned offset,
1953                                             uint32_t mem_value)
1954{
1955    int x;
1956    unsigned val = mem_value;
1957    uint8_t *dst;
1958
1959    for (x = 0; x < 8; x++) {
1960        dst = s->vga.vram_ptr + ((offset + x) & s->cirrus_addr_mask);
1961        if (val & 0x80) {
1962            *dst = s->cirrus_shadow_gr1;
1963        } else if (mode == 5) {
1964            *dst = s->cirrus_shadow_gr0;
1965        }
1966        val <<= 1;
1967    }
1968    memory_region_set_dirty(&s->vga.vram, offset, 8);
1969}
1970
1971static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
1972                                              unsigned mode,
1973                                              unsigned offset,
1974                                              uint32_t mem_value)
1975{
1976    int x;
1977    unsigned val = mem_value;
1978    uint8_t *dst;
1979
1980    for (x = 0; x < 8; x++) {
1981        dst = s->vga.vram_ptr + ((offset + 2 * x) & s->cirrus_addr_mask & ~1);
1982        if (val & 0x80) {
1983            *dst = s->cirrus_shadow_gr1;
1984            *(dst + 1) = s->vga.gr[0x11];
1985        } else if (mode == 5) {
1986            *dst = s->cirrus_shadow_gr0;
1987            *(dst + 1) = s->vga.gr[0x10];
1988        }
1989        val <<= 1;
1990    }
1991    memory_region_set_dirty(&s->vga.vram, offset, 16);
1992}
1993
1994/***************************************
1995 *
1996 *  memory access between 0xa0000-0xbffff
1997 *
1998 ***************************************/
1999
2000static uint64_t cirrus_vga_mem_read(void *opaque,
2001                                    hwaddr addr,
2002                                    uint32_t size)
2003{
2004    CirrusVGAState *s = opaque;
2005    unsigned bank_index;
2006    unsigned bank_offset;
2007    uint32_t val;
2008
2009    if ((s->vga.sr[0x07] & 0x01) == 0) {
2010        return vga_mem_readb(&s->vga, addr);
2011    }
2012
2013    if (addr < 0x10000) {
2014        /* XXX handle bitblt */
2015        /* video memory */
2016        bank_index = addr >> 15;
2017        bank_offset = addr & 0x7fff;
2018        if (bank_offset < s->cirrus_bank_limit[bank_index]) {
2019            bank_offset += s->cirrus_bank_base[bank_index];
2020            if ((s->vga.gr[0x0B] & 0x14) == 0x14) {
2021                bank_offset <<= 4;
2022            } else if (s->vga.gr[0x0B] & 0x02) {
2023                bank_offset <<= 3;
2024            }
2025            bank_offset &= s->cirrus_addr_mask;
2026            val = *(s->vga.vram_ptr + bank_offset);
2027        } else
2028            val = 0xff;
2029    } else if (addr >= 0x18000 && addr < 0x18100) {
2030        /* memory-mapped I/O */
2031        val = 0xff;
2032        if ((s->vga.sr[0x17] & 0x44) == 0x04) {
2033            val = cirrus_mmio_blt_read(s, addr & 0xff);
2034        }
2035    } else {
2036        val = 0xff;
2037        qemu_log_mask(LOG_GUEST_ERROR,
2038                      "cirrus: mem_readb 0x" TARGET_FMT_plx "\n", addr);
2039    }
2040    return val;
2041}
2042
2043static void cirrus_vga_mem_write(void *opaque,
2044                                 hwaddr addr,
2045                                 uint64_t mem_value,
2046                                 uint32_t size)
2047{
2048    CirrusVGAState *s = opaque;
2049    unsigned bank_index;
2050    unsigned bank_offset;
2051    unsigned mode;
2052
2053    if ((s->vga.sr[0x07] & 0x01) == 0) {
2054        vga_mem_writeb(&s->vga, addr, mem_value);
2055        return;
2056    }
2057
2058    if (addr < 0x10000) {
2059        if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2060            /* bitblt */
2061            *s->cirrus_srcptr++ = (uint8_t) mem_value;
2062            if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2063                cirrus_bitblt_cputovideo_next(s);
2064            }
2065        } else {
2066            /* video memory */
2067            bank_index = addr >> 15;
2068            bank_offset = addr & 0x7fff;
2069            if (bank_offset < s->cirrus_bank_limit[bank_index]) {
2070                bank_offset += s->cirrus_bank_base[bank_index];
2071                if ((s->vga.gr[0x0B] & 0x14) == 0x14) {
2072                    bank_offset <<= 4;
2073                } else if (s->vga.gr[0x0B] & 0x02) {
2074                    bank_offset <<= 3;
2075                }
2076                bank_offset &= s->cirrus_addr_mask;
2077                mode = s->vga.gr[0x05] & 0x7;
2078                if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
2079                    *(s->vga.vram_ptr + bank_offset) = mem_value;
2080                    memory_region_set_dirty(&s->vga.vram, bank_offset,
2081                                            sizeof(mem_value));
2082                } else {
2083                    if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
2084                        cirrus_mem_writeb_mode4and5_8bpp(s, mode,
2085                                                         bank_offset,
2086                                                         mem_value);
2087                    } else {
2088                        cirrus_mem_writeb_mode4and5_16bpp(s, mode,
2089                                                          bank_offset,
2090                                                          mem_value);
2091                    }
2092                }
2093            }
2094        }
2095    } else if (addr >= 0x18000 && addr < 0x18100) {
2096        /* memory-mapped I/O */
2097        if ((s->vga.sr[0x17] & 0x44) == 0x04) {
2098            cirrus_mmio_blt_write(s, addr & 0xff, mem_value);
2099        }
2100    } else {
2101        qemu_log_mask(LOG_GUEST_ERROR,
2102                      "cirrus: mem_writeb 0x" TARGET_FMT_plx " "
2103                      "value 0x%02" PRIu64 "\n", addr, mem_value);
2104    }
2105}
2106
2107static const MemoryRegionOps cirrus_vga_mem_ops = {
2108    .read = cirrus_vga_mem_read,
2109    .write = cirrus_vga_mem_write,
2110    .endianness = DEVICE_LITTLE_ENDIAN,
2111    .impl = {
2112        .min_access_size = 1,
2113        .max_access_size = 1,
2114    },
2115};
2116
2117/***************************************
2118 *
2119 *  hardware cursor
2120 *
2121 ***************************************/
2122
2123static inline void invalidate_cursor1(CirrusVGAState *s)
2124{
2125    if (s->last_hw_cursor_size) {
2126        vga_invalidate_scanlines(&s->vga,
2127                                 s->last_hw_cursor_y + s->last_hw_cursor_y_start,
2128                                 s->last_hw_cursor_y + s->last_hw_cursor_y_end);
2129    }
2130}
2131
2132static inline void cirrus_cursor_compute_yrange(CirrusVGAState *s)
2133{
2134    const uint8_t *src;
2135    uint32_t content;
2136    int y, y_min, y_max;
2137
2138    src = s->vga.vram_ptr + s->real_vram_size - 16 * KiB;
2139    if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) {
2140        src += (s->vga.sr[0x13] & 0x3c) * 256;
2141        y_min = 64;
2142        y_max = -1;
2143        for(y = 0; y < 64; y++) {
2144            content = ((uint32_t *)src)[0] |
2145                ((uint32_t *)src)[1] |
2146                ((uint32_t *)src)[2] |
2147                ((uint32_t *)src)[3];
2148            if (content) {
2149                if (y < y_min)
2150                    y_min = y;
2151                if (y > y_max)
2152                    y_max = y;
2153            }
2154            src += 16;
2155        }
2156    } else {
2157        src += (s->vga.sr[0x13] & 0x3f) * 256;
2158        y_min = 32;
2159        y_max = -1;
2160        for(y = 0; y < 32; y++) {
2161            content = ((uint32_t *)src)[0] |
2162                ((uint32_t *)(src + 128))[0];
2163            if (content) {
2164                if (y < y_min)
2165                    y_min = y;
2166                if (y > y_max)
2167                    y_max = y;
2168            }
2169            src += 4;
2170        }
2171    }
2172    if (y_min > y_max) {
2173        s->last_hw_cursor_y_start = 0;
2174        s->last_hw_cursor_y_end = 0;
2175    } else {
2176        s->last_hw_cursor_y_start = y_min;
2177        s->last_hw_cursor_y_end = y_max + 1;
2178    }
2179}
2180
2181/* NOTE: we do not currently handle the cursor bitmap change, so we
2182   update the cursor only if it moves. */
2183static void cirrus_cursor_invalidate(VGACommonState *s1)
2184{
2185    CirrusVGAState *s = container_of(s1, CirrusVGAState, vga);
2186    int size;
2187
2188    if (!(s->vga.sr[0x12] & CIRRUS_CURSOR_SHOW)) {
2189        size = 0;
2190    } else {
2191        if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE)
2192            size = 64;
2193        else
2194            size = 32;
2195    }
2196    /* invalidate last cursor and new cursor if any change */
2197    if (s->last_hw_cursor_size != size ||
2198        s->last_hw_cursor_x != s->vga.hw_cursor_x ||
2199        s->last_hw_cursor_y != s->vga.hw_cursor_y) {
2200
2201        invalidate_cursor1(s);
2202
2203        s->last_hw_cursor_size = size;
2204        s->last_hw_cursor_x = s->vga.hw_cursor_x;
2205        s->last_hw_cursor_y = s->vga.hw_cursor_y;
2206        /* compute the real cursor min and max y */
2207        cirrus_cursor_compute_yrange(s);
2208        invalidate_cursor1(s);
2209    }
2210}
2211
2212static void vga_draw_cursor_line(uint8_t *d1,
2213                                 const uint8_t *src1,
2214                                 int poffset, int w,
2215                                 unsigned int color0,
2216                                 unsigned int color1,
2217                                 unsigned int color_xor)
2218{
2219    const uint8_t *plane0, *plane1;
2220    int x, b0, b1;
2221    uint8_t *d;
2222
2223    d = d1;
2224    plane0 = src1;
2225    plane1 = src1 + poffset;
2226    for (x = 0; x < w; x++) {
2227        b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
2228        b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
2229        switch (b0 | (b1 << 1)) {
2230        case 0:
2231            break;
2232        case 1:
2233            ((uint32_t *)d)[0] ^= color_xor;
2234            break;
2235        case 2:
2236            ((uint32_t *)d)[0] = color0;
2237            break;
2238        case 3:
2239            ((uint32_t *)d)[0] = color1;
2240            break;
2241        }
2242        d += 4;
2243    }
2244}
2245
2246static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
2247{
2248    CirrusVGAState *s = container_of(s1, CirrusVGAState, vga);
2249    int w, h, x1, x2, poffset;
2250    unsigned int color0, color1;
2251    const uint8_t *palette, *src;
2252    uint32_t content;
2253
2254    if (!(s->vga.sr[0x12] & CIRRUS_CURSOR_SHOW))
2255        return;
2256    /* fast test to see if the cursor intersects with the scan line */
2257    if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) {
2258        h = 64;
2259    } else {
2260        h = 32;
2261    }
2262    if (scr_y < s->vga.hw_cursor_y ||
2263        scr_y >= (s->vga.hw_cursor_y + h)) {
2264        return;
2265    }
2266
2267    src = s->vga.vram_ptr + s->real_vram_size - 16 * KiB;
2268    if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) {
2269        src += (s->vga.sr[0x13] & 0x3c) * 256;
2270        src += (scr_y - s->vga.hw_cursor_y) * 16;
2271        poffset = 8;
2272        content = ((uint32_t *)src)[0] |
2273            ((uint32_t *)src)[1] |
2274            ((uint32_t *)src)[2] |
2275            ((uint32_t *)src)[3];
2276    } else {
2277        src += (s->vga.sr[0x13] & 0x3f) * 256;
2278        src += (scr_y - s->vga.hw_cursor_y) * 4;
2279
2280
2281        poffset = 128;
2282        content = ((uint32_t *)src)[0] |
2283            ((uint32_t *)(src + 128))[0];
2284    }
2285    /* if nothing to draw, no need to continue */
2286    if (!content)
2287        return;
2288    w = h;
2289
2290    x1 = s->vga.hw_cursor_x;
2291    if (x1 >= s->vga.last_scr_width)
2292        return;
2293    x2 = s->vga.hw_cursor_x + w;
2294    if (x2 > s->vga.last_scr_width)
2295        x2 = s->vga.last_scr_width;
2296    w = x2 - x1;
2297    palette = s->cirrus_hidden_palette;
2298    color0 = rgb_to_pixel32(c6_to_8(palette[0x0 * 3]),
2299                            c6_to_8(palette[0x0 * 3 + 1]),
2300                            c6_to_8(palette[0x0 * 3 + 2]));
2301    color1 = rgb_to_pixel32(c6_to_8(palette[0xf * 3]),
2302                            c6_to_8(palette[0xf * 3 + 1]),
2303                            c6_to_8(palette[0xf * 3 + 2]));
2304    d1 += x1 * 4;
2305    vga_draw_cursor_line(d1, src, poffset, w, color0, color1, 0xffffff);
2306}
2307
2308/***************************************
2309 *
2310 *  LFB memory access
2311 *
2312 ***************************************/
2313
2314static uint64_t cirrus_linear_read(void *opaque, hwaddr addr,
2315                                   unsigned size)
2316{
2317    CirrusVGAState *s = opaque;
2318    uint32_t ret;
2319
2320    addr &= s->cirrus_addr_mask;
2321
2322    if (((s->vga.sr[0x17] & 0x44) == 0x44) &&
2323        ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
2324        /* memory-mapped I/O */
2325        ret = cirrus_mmio_blt_read(s, addr & 0xff);
2326    } else if (0) {
2327        /* XXX handle bitblt */
2328        ret = 0xff;
2329    } else {
2330        /* video memory */
2331        if ((s->vga.gr[0x0B] & 0x14) == 0x14) {
2332            addr <<= 4;
2333        } else if (s->vga.gr[0x0B] & 0x02) {
2334            addr <<= 3;
2335        }
2336        addr &= s->cirrus_addr_mask;
2337        ret = *(s->vga.vram_ptr + addr);
2338    }
2339
2340    return ret;
2341}
2342
2343static void cirrus_linear_write(void *opaque, hwaddr addr,
2344                                uint64_t val, unsigned size)
2345{
2346    CirrusVGAState *s = opaque;
2347    unsigned mode;
2348
2349    addr &= s->cirrus_addr_mask;
2350
2351    if (((s->vga.sr[0x17] & 0x44) == 0x44) &&
2352        ((addr & s->linear_mmio_mask) ==  s->linear_mmio_mask)) {
2353        /* memory-mapped I/O */
2354        cirrus_mmio_blt_write(s, addr & 0xff, val);
2355    } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2356        /* bitblt */
2357        *s->cirrus_srcptr++ = (uint8_t) val;
2358        if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2359            cirrus_bitblt_cputovideo_next(s);
2360        }
2361    } else {
2362        /* video memory */
2363        if ((s->vga.gr[0x0B] & 0x14) == 0x14) {
2364            addr <<= 4;
2365        } else if (s->vga.gr[0x0B] & 0x02) {
2366            addr <<= 3;
2367        }
2368        addr &= s->cirrus_addr_mask;
2369
2370        mode = s->vga.gr[0x05] & 0x7;
2371        if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
2372            *(s->vga.vram_ptr + addr) = (uint8_t) val;
2373            memory_region_set_dirty(&s->vga.vram, addr, 1);
2374        } else {
2375            if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
2376                cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
2377            } else {
2378                cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val);
2379            }
2380        }
2381    }
2382}
2383
2384/***************************************
2385 *
2386 *  system to screen memory access
2387 *
2388 ***************************************/
2389
2390
2391static uint64_t cirrus_linear_bitblt_read(void *opaque,
2392                                          hwaddr addr,
2393                                          unsigned size)
2394{
2395    CirrusVGAState *s = opaque;
2396
2397    /* XXX handle bitblt */
2398    (void)s;
2399    qemu_log_mask(LOG_UNIMP,
2400                  "cirrus: linear bitblt is not implemented\n");
2401
2402    return 0xff;
2403}
2404
2405static void cirrus_linear_bitblt_write(void *opaque,
2406                                       hwaddr addr,
2407                                       uint64_t val,
2408                                       unsigned size)
2409{
2410    CirrusVGAState *s = opaque;
2411
2412    if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2413        /* bitblt */
2414        *s->cirrus_srcptr++ = (uint8_t) val;
2415        if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2416            cirrus_bitblt_cputovideo_next(s);
2417        }
2418    }
2419}
2420
2421static const MemoryRegionOps cirrus_linear_bitblt_io_ops = {
2422    .read = cirrus_linear_bitblt_read,
2423    .write = cirrus_linear_bitblt_write,
2424    .endianness = DEVICE_LITTLE_ENDIAN,
2425    .impl = {
2426        .min_access_size = 1,
2427        .max_access_size = 1,
2428    },
2429};
2430
2431static void map_linear_vram_bank(CirrusVGAState *s, unsigned bank)
2432{
2433    MemoryRegion *mr = &s->cirrus_bank[bank];
2434    bool enabled = !(s->cirrus_srcptr != s->cirrus_srcptr_end)
2435        && !((s->vga.sr[0x07] & 0x01) == 0)
2436        && !((s->vga.gr[0x0B] & 0x14) == 0x14)
2437        && !(s->vga.gr[0x0B] & 0x02);
2438
2439    memory_region_set_enabled(mr, enabled);
2440    memory_region_set_alias_offset(mr, s->cirrus_bank_base[bank]);
2441}
2442
2443static void map_linear_vram(CirrusVGAState *s)
2444{
2445    if (s->bustype == CIRRUS_BUSTYPE_PCI && !s->linear_vram) {
2446        s->linear_vram = true;
2447        memory_region_add_subregion_overlap(&s->pci_bar, 0, &s->vga.vram, 1);
2448    }
2449    map_linear_vram_bank(s, 0);
2450    map_linear_vram_bank(s, 1);
2451}
2452
2453static void unmap_linear_vram(CirrusVGAState *s)
2454{
2455    if (s->bustype == CIRRUS_BUSTYPE_PCI && s->linear_vram) {
2456        s->linear_vram = false;
2457        memory_region_del_subregion(&s->pci_bar, &s->vga.vram);
2458    }
2459    memory_region_set_enabled(&s->cirrus_bank[0], false);
2460    memory_region_set_enabled(&s->cirrus_bank[1], false);
2461}
2462
2463/* Compute the memory access functions */
2464static void cirrus_update_memory_access(CirrusVGAState *s)
2465{
2466    unsigned mode;
2467
2468    memory_region_transaction_begin();
2469    if ((s->vga.sr[0x17] & 0x44) == 0x44) {
2470        goto generic_io;
2471    } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2472        goto generic_io;
2473    } else {
2474        if ((s->vga.gr[0x0B] & 0x14) == 0x14) {
2475            goto generic_io;
2476        } else if (s->vga.gr[0x0B] & 0x02) {
2477            goto generic_io;
2478        }
2479
2480        mode = s->vga.gr[0x05] & 0x7;
2481        if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
2482            map_linear_vram(s);
2483        } else {
2484        generic_io:
2485            unmap_linear_vram(s);
2486        }
2487    }
2488    memory_region_transaction_commit();
2489}
2490
2491
2492/* I/O ports */
2493
2494static uint64_t cirrus_vga_ioport_read(void *opaque, hwaddr addr,
2495                                       unsigned size)
2496{
2497    CirrusVGAState *c = opaque;
2498    VGACommonState *s = &c->vga;
2499    int val, index;
2500
2501    addr += 0x3b0;
2502
2503    if (vga_ioport_invalid(s, addr)) {
2504        val = 0xff;
2505    } else {
2506        switch (addr) {
2507        case 0x3c0:
2508            if (s->ar_flip_flop == 0) {
2509                val = s->ar_index;
2510            } else {
2511                val = 0;
2512            }
2513            break;
2514        case 0x3c1:
2515            index = s->ar_index & 0x1f;
2516            if (index < 21)
2517                val = s->ar[index];
2518            else
2519                val = 0;
2520            break;
2521        case 0x3c2:
2522            val = s->st00;
2523            break;
2524        case 0x3c4:
2525            val = s->sr_index;
2526            break;
2527        case 0x3c5:
2528            val = cirrus_vga_read_sr(c);
2529            break;
2530#ifdef DEBUG_VGA_REG
2531            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
2532#endif
2533            break;
2534        case 0x3c6:
2535            val = cirrus_read_hidden_dac(c);
2536            break;
2537        case 0x3c7:
2538            val = s->dac_state;
2539            break;
2540        case 0x3c8:
2541            val = s->dac_write_index;
2542            c->cirrus_hidden_dac_lockindex = 0;
2543            break;
2544        case 0x3c9:
2545            val = cirrus_vga_read_palette(c);
2546            break;
2547        case 0x3ca:
2548            val = s->fcr;
2549            break;
2550        case 0x3cc:
2551            val = s->msr;
2552            break;
2553        case 0x3ce:
2554            val = s->gr_index;
2555            break;
2556        case 0x3cf:
2557            val = cirrus_vga_read_gr(c, s->gr_index);
2558#ifdef DEBUG_VGA_REG
2559            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
2560#endif
2561            break;
2562        case 0x3b4:
2563        case 0x3d4:
2564            val = s->cr_index;
2565            break;
2566        case 0x3b5:
2567        case 0x3d5:
2568            val = cirrus_vga_read_cr(c, s->cr_index);
2569#ifdef DEBUG_VGA_REG
2570            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
2571#endif
2572            break;
2573        case 0x3ba:
2574        case 0x3da:
2575            /* just toggle to fool polling */
2576            val = s->st01 = s->retrace(s);
2577            s->ar_flip_flop = 0;
2578            break;
2579        default:
2580            val = 0x00;
2581            break;
2582        }
2583    }
2584    trace_vga_cirrus_read_io(addr, val);
2585    return val;
2586}
2587
2588static void cirrus_vga_ioport_write(void *opaque, hwaddr addr, uint64_t val,
2589                                    unsigned size)
2590{
2591    CirrusVGAState *c = opaque;
2592    VGACommonState *s = &c->vga;
2593    int index;
2594
2595    addr += 0x3b0;
2596
2597    /* check port range access depending on color/monochrome mode */
2598    if (vga_ioport_invalid(s, addr)) {
2599        return;
2600    }
2601    trace_vga_cirrus_write_io(addr, val);
2602
2603    switch (addr) {
2604    case 0x3c0:
2605        if (s->ar_flip_flop == 0) {
2606            val &= 0x3f;
2607            s->ar_index = val;
2608        } else {
2609            index = s->ar_index & 0x1f;
2610            switch (index) {
2611            case 0x00 ... 0x0f:
2612                s->ar[index] = val & 0x3f;
2613                break;
2614            case 0x10:
2615                s->ar[index] = val & ~0x10;
2616                break;
2617            case 0x11:
2618                s->ar[index] = val;
2619                break;
2620            case 0x12:
2621                s->ar[index] = val & ~0xc0;
2622                break;
2623            case 0x13:
2624                s->ar[index] = val & ~0xf0;
2625                break;
2626            case 0x14:
2627                s->ar[index] = val & ~0xf0;
2628                break;
2629            default:
2630                break;
2631            }
2632        }
2633        s->ar_flip_flop ^= 1;
2634        break;
2635    case 0x3c2:
2636        s->msr = val & ~0x10;
2637        s->update_retrace_info(s);
2638        break;
2639    case 0x3c4:
2640        s->sr_index = val;
2641        break;
2642    case 0x3c5:
2643#ifdef DEBUG_VGA_REG
2644        printf("vga: write SR%x = 0x%02" PRIu64 "\n", s->sr_index, val);
2645#endif
2646        cirrus_vga_write_sr(c, val);
2647        break;
2648    case 0x3c6:
2649        cirrus_write_hidden_dac(c, val);
2650        break;
2651    case 0x3c7:
2652        s->dac_read_index = val;
2653        s->dac_sub_index = 0;
2654        s->dac_state = 3;
2655        break;
2656    case 0x3c8:
2657        s->dac_write_index = val;
2658        s->dac_sub_index = 0;
2659        s->dac_state = 0;
2660        break;
2661    case 0x3c9:
2662        cirrus_vga_write_palette(c, val);
2663        break;
2664    case 0x3ce:
2665        s->gr_index = val;
2666        break;
2667    case 0x3cf:
2668#ifdef DEBUG_VGA_REG
2669        printf("vga: write GR%x = 0x%02" PRIu64 "\n", s->gr_index, val);
2670#endif
2671        cirrus_vga_write_gr(c, s->gr_index, val);
2672        break;
2673    case 0x3b4:
2674    case 0x3d4:
2675        s->cr_index = val;
2676        break;
2677    case 0x3b5:
2678    case 0x3d5:
2679#ifdef DEBUG_VGA_REG
2680        printf("vga: write CR%x = 0x%02"PRIu64"\n", s->cr_index, val);
2681#endif
2682        cirrus_vga_write_cr(c, val);
2683        break;
2684    case 0x3ba:
2685    case 0x3da:
2686        s->fcr = val & 0x10;
2687        break;
2688    }
2689}
2690
2691/***************************************
2692 *
2693 *  memory-mapped I/O access
2694 *
2695 ***************************************/
2696
2697static uint64_t cirrus_mmio_read(void *opaque, hwaddr addr,
2698                                 unsigned size)
2699{
2700    CirrusVGAState *s = opaque;
2701
2702    if (addr >= 0x100) {
2703        return cirrus_mmio_blt_read(s, addr - 0x100);
2704    } else {
2705        return cirrus_vga_ioport_read(s, addr + 0x10, size);
2706    }
2707}
2708
2709static void cirrus_mmio_write(void *opaque, hwaddr addr,
2710                              uint64_t val, unsigned size)
2711{
2712    CirrusVGAState *s = opaque;
2713
2714    if (addr >= 0x100) {
2715        cirrus_mmio_blt_write(s, addr - 0x100, val);
2716    } else {
2717        cirrus_vga_ioport_write(s, addr + 0x10, val, size);
2718    }
2719}
2720
2721static const MemoryRegionOps cirrus_mmio_io_ops = {
2722    .read = cirrus_mmio_read,
2723    .write = cirrus_mmio_write,
2724    .endianness = DEVICE_LITTLE_ENDIAN,
2725    .impl = {
2726        .min_access_size = 1,
2727        .max_access_size = 1,
2728    },
2729};
2730
2731/* load/save state */
2732
2733static int cirrus_post_load(void *opaque, int version_id)
2734{
2735    CirrusVGAState *s = opaque;
2736
2737    s->vga.gr[0x00] = s->cirrus_shadow_gr0 & 0x0f;
2738    s->vga.gr[0x01] = s->cirrus_shadow_gr1 & 0x0f;
2739
2740    cirrus_update_bank_ptr(s, 0);
2741    cirrus_update_bank_ptr(s, 1);
2742    cirrus_update_memory_access(s);
2743    /* force refresh */
2744    s->vga.graphic_mode = -1;
2745
2746    return 0;
2747}
2748
2749const VMStateDescription vmstate_cirrus_vga = {
2750    .name = "cirrus_vga",
2751    .version_id = 2,
2752    .minimum_version_id = 1,
2753    .post_load = cirrus_post_load,
2754    .fields = (VMStateField[]) {
2755        VMSTATE_UINT32(vga.latch, CirrusVGAState),
2756        VMSTATE_UINT8(vga.sr_index, CirrusVGAState),
2757        VMSTATE_BUFFER(vga.sr, CirrusVGAState),
2758        VMSTATE_UINT8(vga.gr_index, CirrusVGAState),
2759        VMSTATE_UINT8(cirrus_shadow_gr0, CirrusVGAState),
2760        VMSTATE_UINT8(cirrus_shadow_gr1, CirrusVGAState),
2761        VMSTATE_BUFFER_START_MIDDLE(vga.gr, CirrusVGAState, 2),
2762        VMSTATE_UINT8(vga.ar_index, CirrusVGAState),
2763        VMSTATE_BUFFER(vga.ar, CirrusVGAState),
2764        VMSTATE_INT32(vga.ar_flip_flop, CirrusVGAState),
2765        VMSTATE_UINT8(vga.cr_index, CirrusVGAState),
2766        VMSTATE_BUFFER(vga.cr, CirrusVGAState),
2767        VMSTATE_UINT8(vga.msr, CirrusVGAState),
2768        VMSTATE_UINT8(vga.fcr, CirrusVGAState),
2769        VMSTATE_UINT8(vga.st00, CirrusVGAState),
2770        VMSTATE_UINT8(vga.st01, CirrusVGAState),
2771        VMSTATE_UINT8(vga.dac_state, CirrusVGAState),
2772        VMSTATE_UINT8(vga.dac_sub_index, CirrusVGAState),
2773        VMSTATE_UINT8(vga.dac_read_index, CirrusVGAState),
2774        VMSTATE_UINT8(vga.dac_write_index, CirrusVGAState),
2775        VMSTATE_BUFFER(vga.dac_cache, CirrusVGAState),
2776        VMSTATE_BUFFER(vga.palette, CirrusVGAState),
2777        VMSTATE_INT32(vga.bank_offset, CirrusVGAState),
2778        VMSTATE_UINT8(cirrus_hidden_dac_lockindex, CirrusVGAState),
2779        VMSTATE_UINT8(cirrus_hidden_dac_data, CirrusVGAState),
2780        VMSTATE_UINT32(vga.hw_cursor_x, CirrusVGAState),
2781        VMSTATE_UINT32(vga.hw_cursor_y, CirrusVGAState),
2782        /* XXX: we do not save the bitblt state - we assume we do not save
2783           the state when the blitter is active */
2784        VMSTATE_END_OF_LIST()
2785    }
2786};
2787
2788static const VMStateDescription vmstate_pci_cirrus_vga = {
2789    .name = "cirrus_vga",
2790    .version_id = 2,
2791    .minimum_version_id = 2,
2792    .fields = (VMStateField[]) {
2793        VMSTATE_PCI_DEVICE(dev, PCICirrusVGAState),
2794        VMSTATE_STRUCT(cirrus_vga, PCICirrusVGAState, 0,
2795                       vmstate_cirrus_vga, CirrusVGAState),
2796        VMSTATE_END_OF_LIST()
2797    }
2798};
2799
2800/***************************************
2801 *
2802 *  initialize
2803 *
2804 ***************************************/
2805
2806static void cirrus_reset(void *opaque)
2807{
2808    CirrusVGAState *s = opaque;
2809
2810    vga_common_reset(&s->vga);
2811    unmap_linear_vram(s);
2812    s->vga.sr[0x06] = 0x0f;
2813    if (s->device_id == CIRRUS_ID_CLGD5446) {
2814        /* 4MB 64 bit memory config, always PCI */
2815        s->vga.sr[0x1F] = 0x2d;         // MemClock
2816        s->vga.gr[0x18] = 0x0f;             // fastest memory configuration
2817        s->vga.sr[0x0f] = 0x98;
2818        s->vga.sr[0x17] = 0x20;
2819        s->vga.sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */
2820    } else {
2821        s->vga.sr[0x1F] = 0x22;         // MemClock
2822        s->vga.sr[0x0F] = CIRRUS_MEMSIZE_2M;
2823        s->vga.sr[0x17] = s->bustype;
2824        s->vga.sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
2825    }
2826    s->vga.cr[0x27] = s->device_id;
2827
2828    s->cirrus_hidden_dac_lockindex = 5;
2829    s->cirrus_hidden_dac_data = 0;
2830}
2831
2832static const MemoryRegionOps cirrus_linear_io_ops = {
2833    .read = cirrus_linear_read,
2834    .write = cirrus_linear_write,
2835    .endianness = DEVICE_LITTLE_ENDIAN,
2836    .impl = {
2837        .min_access_size = 1,
2838        .max_access_size = 1,
2839    },
2840};
2841
2842static const MemoryRegionOps cirrus_vga_io_ops = {
2843    .read = cirrus_vga_ioport_read,
2844    .write = cirrus_vga_ioport_write,
2845    .endianness = DEVICE_LITTLE_ENDIAN,
2846    .impl = {
2847        .min_access_size = 1,
2848        .max_access_size = 1,
2849    },
2850};
2851
2852void cirrus_init_common(CirrusVGAState *s, Object *owner,
2853                        int device_id, int is_pci,
2854                        MemoryRegion *system_memory, MemoryRegion *system_io)
2855{
2856    int i;
2857    static int inited;
2858
2859    if (!inited) {
2860        inited = 1;
2861        for(i = 0;i < 256; i++)
2862            rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */
2863        rop_to_index[CIRRUS_ROP_0] = 0;
2864        rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1;
2865        rop_to_index[CIRRUS_ROP_NOP] = 2;
2866        rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3;
2867        rop_to_index[CIRRUS_ROP_NOTDST] = 4;
2868        rop_to_index[CIRRUS_ROP_SRC] = 5;
2869        rop_to_index[CIRRUS_ROP_1] = 6;
2870        rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7;
2871        rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8;
2872        rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9;
2873        rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10;
2874        rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11;
2875        rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12;
2876        rop_to_index[CIRRUS_ROP_NOTSRC] = 13;
2877        rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14;
2878        rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15;
2879        s->device_id = device_id;
2880        if (is_pci)
2881            s->bustype = CIRRUS_BUSTYPE_PCI;
2882        else
2883            s->bustype = CIRRUS_BUSTYPE_ISA;
2884    }
2885
2886    /* Register ioport 0x3b0 - 0x3df */
2887    memory_region_init_io(&s->cirrus_vga_io, owner, &cirrus_vga_io_ops, s,
2888                          "cirrus-io", 0x30);
2889    memory_region_set_flush_coalesced(&s->cirrus_vga_io);
2890    memory_region_add_subregion(system_io, 0x3b0, &s->cirrus_vga_io);
2891
2892    memory_region_init(&s->low_mem_container, owner,
2893                       "cirrus-lowmem-container",
2894                       0x20000);
2895
2896    memory_region_init_io(&s->low_mem, owner, &cirrus_vga_mem_ops, s,
2897                          "cirrus-low-memory", 0x20000);
2898    memory_region_add_subregion(&s->low_mem_container, 0, &s->low_mem);
2899    for (i = 0; i < 2; ++i) {
2900        static const char *names[] = { "vga.bank0", "vga.bank1" };
2901        MemoryRegion *bank = &s->cirrus_bank[i];
2902        memory_region_init_alias(bank, owner, names[i], &s->vga.vram,
2903                                 0, 0x8000);
2904        memory_region_set_enabled(bank, false);
2905        memory_region_add_subregion_overlap(&s->low_mem_container, i * 0x8000,
2906                                            bank, 1);
2907    }
2908    memory_region_add_subregion_overlap(system_memory,
2909                                        0x000a0000,
2910                                        &s->low_mem_container,
2911                                        1);
2912    memory_region_set_coalescing(&s->low_mem);
2913
2914    /* I/O handler for LFB */
2915    memory_region_init_io(&s->cirrus_linear_io, owner, &cirrus_linear_io_ops, s,
2916                          "cirrus-linear-io", s->vga.vram_size_mb * MiB);
2917    memory_region_set_flush_coalesced(&s->cirrus_linear_io);
2918
2919    /* I/O handler for LFB */
2920    memory_region_init_io(&s->cirrus_linear_bitblt_io, owner,
2921                          &cirrus_linear_bitblt_io_ops,
2922                          s,
2923                          "cirrus-bitblt-mmio",
2924                          0x400000);
2925    memory_region_set_flush_coalesced(&s->cirrus_linear_bitblt_io);
2926
2927    /* I/O handler for memory-mapped I/O */
2928    memory_region_init_io(&s->cirrus_mmio_io, owner, &cirrus_mmio_io_ops, s,
2929                          "cirrus-mmio", CIRRUS_PNPMMIO_SIZE);
2930    memory_region_set_flush_coalesced(&s->cirrus_mmio_io);
2931
2932    s->real_vram_size =
2933        (s->device_id == CIRRUS_ID_CLGD5446) ? 4 * MiB : 2 * MiB;
2934
2935    /* XXX: s->vga.vram_size must be a power of two */
2936    s->cirrus_addr_mask = s->real_vram_size - 1;
2937    s->linear_mmio_mask = s->real_vram_size - 256;
2938
2939    s->vga.get_bpp = cirrus_get_bpp;
2940    s->vga.get_offsets = cirrus_get_offsets;
2941    s->vga.get_resolution = cirrus_get_resolution;
2942    s->vga.cursor_invalidate = cirrus_cursor_invalidate;
2943    s->vga.cursor_draw_line = cirrus_cursor_draw_line;
2944
2945    qemu_register_reset(cirrus_reset, s);
2946}
2947
2948/***************************************
2949 *
2950 *  PCI bus support
2951 *
2952 ***************************************/
2953
2954static void pci_cirrus_vga_realize(PCIDevice *dev, Error **errp)
2955{
2956     PCICirrusVGAState *d = PCI_CIRRUS_VGA(dev);
2957     CirrusVGAState *s = &d->cirrus_vga;
2958     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
2959     int16_t device_id = pc->device_id;
2960
2961     /* follow real hardware, cirrus card emulated has 4 MB video memory.
2962       Also accept 8 MB/16 MB for backward compatibility. */
2963     if (s->vga.vram_size_mb != 4 && s->vga.vram_size_mb != 8 &&
2964         s->vga.vram_size_mb != 16) {
2965         error_setg(errp, "Invalid cirrus_vga ram size '%u'",
2966                    s->vga.vram_size_mb);
2967         return;
2968     }
2969     /* setup VGA */
2970     vga_common_init(&s->vga, OBJECT(dev));
2971     cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
2972                        pci_address_space_io(dev));
2973     s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga);
2974
2975     /* setup PCI */
2976
2977    memory_region_init(&s->pci_bar, OBJECT(dev), "cirrus-pci-bar0", 0x2000000);
2978
2979    /* XXX: add byte swapping apertures */
2980    memory_region_add_subregion(&s->pci_bar, 0, &s->cirrus_linear_io);
2981    memory_region_add_subregion(&s->pci_bar, 0x1000000,
2982                                &s->cirrus_linear_bitblt_io);
2983
2984     /* setup memory space */
2985     /* memory #0 LFB */
2986     /* memory #1 memory-mapped I/O */
2987     /* XXX: s->vga.vram_size must be a power of two */
2988     pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->pci_bar);
2989     if (device_id == CIRRUS_ID_CLGD5446) {
2990         pci_register_bar(&d->dev, 1, 0, &s->cirrus_mmio_io);
2991     }
2992}
2993
2994static Property pci_vga_cirrus_properties[] = {
2995    DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState,
2996                       cirrus_vga.vga.vram_size_mb, 4),
2997    DEFINE_PROP_BOOL("blitter", struct PCICirrusVGAState,
2998                     cirrus_vga.enable_blitter, true),
2999    DEFINE_PROP_BOOL("global-vmstate", struct PCICirrusVGAState,
3000                     cirrus_vga.vga.global_vmstate, false),
3001    DEFINE_PROP_END_OF_LIST(),
3002};
3003
3004static void cirrus_vga_class_init(ObjectClass *klass, void *data)
3005{
3006    DeviceClass *dc = DEVICE_CLASS(klass);
3007    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
3008
3009    k->realize = pci_cirrus_vga_realize;
3010    k->romfile = VGABIOS_CIRRUS_FILENAME;
3011    k->vendor_id = PCI_VENDOR_ID_CIRRUS;
3012    k->device_id = CIRRUS_ID_CLGD5446;
3013    k->class_id = PCI_CLASS_DISPLAY_VGA;
3014    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
3015    dc->desc = "Cirrus CLGD 54xx VGA";
3016    dc->vmsd = &vmstate_pci_cirrus_vga;
3017    device_class_set_props(dc, pci_vga_cirrus_properties);
3018    dc->hotpluggable = false;
3019}
3020
3021static const TypeInfo cirrus_vga_info = {
3022    .name          = TYPE_PCI_CIRRUS_VGA,
3023    .parent        = TYPE_PCI_DEVICE,
3024    .instance_size = sizeof(PCICirrusVGAState),
3025    .class_init    = cirrus_vga_class_init,
3026    .interfaces = (InterfaceInfo[]) {
3027        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
3028        { },
3029    },
3030};
3031
3032static void cirrus_vga_register_types(void)
3033{
3034    type_register_static(&cirrus_vga_info);
3035}
3036
3037type_init(cirrus_vga_register_types)
3038