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