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