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