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