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