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