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