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