Commit e6e5ad80d8c48934205092f8b6d5a5dbcd56658d

Authored by bellard
1 parent 798b0c25

Cirrus VGA emulation (initial patch by Suzu - heavily modified for easier merge)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@891 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 2705 additions and 0 deletions
hw/cirrus_vga.c 0 → 100644
  1 +/*
  2 + * QEMU Cirrus VGA Emulator.
  3 + *
  4 + * Copyright (c) 2004 Fabrice Bellard
  5 + * Copyright (c) 2004 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 +#include "vl.h"
  26 +#include "vga_int.h"
  27 +
  28 +/***************************************
  29 + *
  30 + * definitions
  31 + *
  32 + ***************************************/
  33 +
  34 +#define qemu_MIN(a,b) ((a) < (b) ? (a) : (b))
  35 +
  36 +// ID
  37 +#define CIRRUS_ID_CLGD5422 (0x23<<2)
  38 +#define CIRRUS_ID_CLGD5426 (0x24<<2)
  39 +#define CIRRUS_ID_CLGD5424 (0x25<<2)
  40 +#define CIRRUS_ID_CLGD5428 (0x26<<2)
  41 +#define CIRRUS_ID_CLGD5430 (0x28<<2)
  42 +#define CIRRUS_ID_CLGD5434 (0x2A<<2)
  43 +#define CIRRUS_ID_CLGD5446 (0x2E<<2)
  44 +
  45 +// sequencer 0x07
  46 +#define CIRRUS_SR7_BPP_VGA 0x00
  47 +#define CIRRUS_SR7_BPP_SVGA 0x01
  48 +#define CIRRUS_SR7_BPP_MASK 0x0e
  49 +#define CIRRUS_SR7_BPP_8 0x00
  50 +#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02
  51 +#define CIRRUS_SR7_BPP_24 0x04
  52 +#define CIRRUS_SR7_BPP_16 0x06
  53 +#define CIRRUS_SR7_BPP_32 0x08
  54 +#define CIRRUS_SR7_ISAADDR_MASK 0xe0
  55 +
  56 +// sequencer 0x0f
  57 +#define CIRRUS_MEMSIZE_512k 0x08
  58 +#define CIRRUS_MEMSIZE_1M 0x10
  59 +#define CIRRUS_MEMSIZE_2M 0x18
  60 +#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled.
  61 +
  62 +// sequencer 0x12
  63 +#define CIRRUS_CURSOR_SHOW 0x01
  64 +#define CIRRUS_CURSOR_HIDDENPEL 0x02
  65 +#define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear
  66 +
  67 +// sequencer 0x17
  68 +#define CIRRUS_BUSTYPE_VLBFAST 0x10
  69 +#define CIRRUS_BUSTYPE_PCI 0x20
  70 +#define CIRRUS_BUSTYPE_VLBSLOW 0x30
  71 +#define CIRRUS_BUSTYPE_ISA 0x38
  72 +#define CIRRUS_MMIO_ENABLE 0x04
  73 +#define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared.
  74 +#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
  75 +
  76 +// control 0x0b
  77 +#define CIRRUS_BANKING_DUAL 0x01
  78 +#define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k
  79 +
  80 +// control 0x30
  81 +#define CIRRUS_BLTMODE_BACKWARDS 0x01
  82 +#define CIRRUS_BLTMODE_MEMSYSDEST 0x02
  83 +#define CIRRUS_BLTMODE_MEMSYSSRC 0x04
  84 +#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08
  85 +#define CIRRUS_BLTMODE_PATTERNCOPY 0x40
  86 +#define CIRRUS_BLTMODE_COLOREXPAND 0x80
  87 +#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30
  88 +#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00
  89 +#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10
  90 +#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20
  91 +#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30
  92 +
  93 +// control 0x31
  94 +#define CIRRUS_BLT_BUSY 0x01
  95 +#define CIRRUS_BLT_START 0x02
  96 +#define CIRRUS_BLT_RESET 0x04
  97 +#define CIRRUS_BLT_FIFOUSED 0x10
  98 +
  99 +// control 0x32
  100 +#define CIRRUS_ROP_0 0x00
  101 +#define CIRRUS_ROP_SRC_AND_DST 0x05
  102 +#define CIRRUS_ROP_NOP 0x06
  103 +#define CIRRUS_ROP_SRC_AND_NOTDST 0x09
  104 +#define CIRRUS_ROP_NOTDST 0x0b
  105 +#define CIRRUS_ROP_SRC 0x0d
  106 +#define CIRRUS_ROP_1 0x0e
  107 +#define CIRRUS_ROP_NOTSRC_AND_DST 0x50
  108 +#define CIRRUS_ROP_SRC_XOR_DST 0x59
  109 +#define CIRRUS_ROP_SRC_OR_DST 0x6d
  110 +#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90
  111 +#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95
  112 +#define CIRRUS_ROP_SRC_OR_NOTDST 0xad
  113 +#define CIRRUS_ROP_NOTSRC 0xd0
  114 +#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6
  115 +#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda
  116 +
  117 +// memory-mapped IO
  118 +#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword
  119 +#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword
  120 +#define CIRRUS_MMIO_BLTWIDTH 0x08 // word
  121 +#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word
  122 +#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word
  123 +#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word
  124 +#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword
  125 +#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword
  126 +#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte
  127 +#define CIRRUS_MMIO_BLTMODE 0x18 // byte
  128 +#define CIRRUS_MMIO_BLTROP 0x1a // byte
  129 +#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte
  130 +#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c // word?
  131 +#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word?
  132 +#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24 // word
  133 +#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26 // word
  134 +#define CIRRUS_MMIO_LINEARDRAW_END_X 0x28 // word
  135 +#define CIRRUS_MMIO_LINEARDRAW_END_Y 0x2a // word
  136 +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c // byte
  137 +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d // byte
  138 +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e // byte
  139 +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f // byte
  140 +#define CIRRUS_MMIO_BRESENHAM_K1 0x30 // word
  141 +#define CIRRUS_MMIO_BRESENHAM_K3 0x32 // word
  142 +#define CIRRUS_MMIO_BRESENHAM_ERROR 0x34 // word
  143 +#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36 // word
  144 +#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38 // byte
  145 +#define CIRRUS_MMIO_LINEDRAW_MODE 0x39 // byte
  146 +#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte
  147 +
  148 +// PCI 0x00: vendor, 0x02: device
  149 +#define PCI_VENDOR_CIRRUS 0x1013
  150 +#define PCI_DEVICE_CLGD5430 0x00a0 // CLGD5430 or CLGD5440
  151 +#define PCI_DEVICE_CLGD5434 0x00a8
  152 +#define PCI_DEVICE_CLGD5436 0x00ac
  153 +#define PCI_DEVICE_CLGD5446 0x00b8
  154 +#define PCI_DEVICE_CLGD5462 0x00d0
  155 +#define PCI_DEVICE_CLGD5465 0x00d6
  156 +// PCI 0x04: command(word), 0x06(word): status
  157 +#define PCI_COMMAND_IOACCESS 0x0001
  158 +#define PCI_COMMAND_MEMACCESS 0x0002
  159 +#define PCI_COMMAND_BUSMASTER 0x0004
  160 +#define PCI_COMMAND_SPECIALCYCLE 0x0008
  161 +#define PCI_COMMAND_MEMWRITEINVALID 0x0010
  162 +#define PCI_COMMAND_PALETTESNOOPING 0x0020
  163 +#define PCI_COMMAND_PARITYDETECTION 0x0040
  164 +#define PCI_COMMAND_ADDRESSDATASTEPPING 0x0080
  165 +#define PCI_COMMAND_SERR 0x0100
  166 +#define PCI_COMMAND_BACKTOBACKTRANS 0x0200
  167 +// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
  168 +#define PCI_CLASS_BASE_DISPLAY 0x03
  169 +// PCI 0x08, 0x00ff0000
  170 +#define PCI_CLASS_SUB_VGA 0x00
  171 +// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test)
  172 +#define PCI_CLASS_HEADERTYPE_00h 0x00
  173 +// 0x10-0x3f (headertype 00h)
  174 +// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers
  175 +// 0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x)
  176 +#define PCI_MAP_MEM 0x0
  177 +#define PCI_MAP_IO 0x1
  178 +#define PCI_MAP_MEM_ADDR_MASK (~0xf)
  179 +#define PCI_MAP_IO_ADDR_MASK (~0x3)
  180 +#define PCI_MAP_MEMFLAGS_32BIT 0x0
  181 +#define PCI_MAP_MEMFLAGS_32BIT_1M 0x1
  182 +#define PCI_MAP_MEMFLAGS_64BIT 0x4
  183 +#define PCI_MAP_MEMFLAGS_CACHEABLE 0x8
  184 +// PCI 0x28: cardbus CIS pointer
  185 +// PCI 0x2c: subsystem vendor id, 0x2e: subsystem id
  186 +// PCI 0x30: expansion ROM base address
  187 +#define PCI_ROMBIOS_ENABLED 0x1
  188 +// PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer
  189 +// PCI 0x38: reserved
  190 +// PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat
  191 +
  192 +#define CIRRUS_PNPMMIO_SIZE 0x800
  193 +
  194 +
  195 +/* I/O and memory hook */
  196 +#define CIRRUS_HOOK_NOT_HANDLED 0
  197 +#define CIRRUS_HOOK_HANDLED 1
  198 +
  199 +typedef void (*cirrus_bitblt_rop_t) (uint8_t * dst, const uint8_t * src,
  200 + int dstpitch, int srcpitch,
  201 + int bltwidth, int bltheight);
  202 +
  203 +typedef void (*cirrus_bitblt_handler_t) (void *opaque);
  204 +
  205 +typedef struct CirrusVGAState {
  206 + /* XXX: we use the anonymous struct/union gcc 3.x extension */
  207 + struct VGAState;
  208 +
  209 + int cirrus_linear_io_addr;
  210 + int cirrus_mmio_io_addr;
  211 + uint32_t cirrus_addr_mask;
  212 + uint8_t cirrus_shadow_gr0;
  213 + uint8_t cirrus_shadow_gr1;
  214 + uint8_t cirrus_hidden_dac_lockindex;
  215 + uint8_t cirrus_hidden_dac_data;
  216 + uint32_t cirrus_bank_base[2];
  217 + uint32_t cirrus_bank_limit[2];
  218 + uint8_t cirrus_hidden_palette[48];
  219 + uint32_t cirrus_hw_cursor_x;
  220 + uint32_t cirrus_hw_cursor_y;
  221 + int cirrus_blt_pixelwidth;
  222 + int cirrus_blt_width;
  223 + int cirrus_blt_height;
  224 + int cirrus_blt_dstpitch;
  225 + int cirrus_blt_srcpitch;
  226 + uint32_t cirrus_blt_dstaddr;
  227 + uint32_t cirrus_blt_srcaddr;
  228 + uint8_t cirrus_blt_mode;
  229 + cirrus_bitblt_rop_t cirrus_rop;
  230 +#define CIRRUS_BLTBUFSIZE 256
  231 + uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE];
  232 + uint8_t *cirrus_srcptr;
  233 + uint8_t *cirrus_srcptr_end;
  234 + uint32_t cirrus_srccounter;
  235 + uint8_t *cirrus_dstptr;
  236 + uint8_t *cirrus_dstptr_end;
  237 + uint32_t cirrus_dstcounter;
  238 + cirrus_bitblt_handler_t cirrus_blt_handler;
  239 + int cirrus_blt_horz_counter;
  240 +} CirrusVGAState;
  241 +
  242 +typedef struct PCICirrusVGAState {
  243 + PCIDevice dev;
  244 + CirrusVGAState cirrus_vga;
  245 +} PCICirrusVGAState;
  246 +
  247 +/***************************************
  248 + *
  249 + * prototypes.
  250 + *
  251 + ***************************************/
  252 +
  253 +
  254 +static void cirrus_bitblt_reset(CirrusVGAState * s);
  255 +
  256 +/***************************************
  257 + *
  258 + * raster operations
  259 + *
  260 + ***************************************/
  261 +
  262 +#define IMPLEMENT_FORWARD_BITBLT(name,opline) \
  263 + static void \
  264 + cirrus_bitblt_rop_fwd_##name( \
  265 + uint8_t *dst,const uint8_t *src, \
  266 + int dstpitch,int srcpitch, \
  267 + int bltwidth,int bltheight) \
  268 + { \
  269 + int x,y; \
  270 + dstpitch -= bltwidth; \
  271 + srcpitch -= bltwidth; \
  272 + for (y = 0; y < bltheight; y++) { \
  273 + for (x = 0; x < bltwidth; x++) { \
  274 + opline; \
  275 + dst++; \
  276 + src++; \
  277 + } \
  278 + dst += dstpitch; \
  279 + src += srcpitch; \
  280 + } \
  281 + }
  282 +
  283 +#define IMPLEMENT_BACKWARD_BITBLT(name,opline) \
  284 + static void \
  285 + cirrus_bitblt_rop_bkwd_##name( \
  286 + uint8_t *dst,const uint8_t *src, \
  287 + int dstpitch,int srcpitch, \
  288 + int bltwidth,int bltheight) \
  289 + { \
  290 + int x,y; \
  291 + dstpitch += bltwidth; \
  292 + srcpitch += bltwidth; \
  293 + for (y = 0; y < bltheight; y++) { \
  294 + for (x = 0; x < bltwidth; x++) { \
  295 + opline; \
  296 + dst--; \
  297 + src--; \
  298 + } \
  299 + dst += dstpitch; \
  300 + src += srcpitch; \
  301 + } \
  302 + }
  303 +
  304 +IMPLEMENT_FORWARD_BITBLT(0, *dst = 0)
  305 + IMPLEMENT_FORWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst))
  306 + IMPLEMENT_FORWARD_BITBLT(nop, (void) 0)
  307 + IMPLEMENT_FORWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
  308 + IMPLEMENT_FORWARD_BITBLT(notdst, *dst = ~(*dst))
  309 + IMPLEMENT_FORWARD_BITBLT(src, *dst = *src)
  310 + IMPLEMENT_FORWARD_BITBLT(1, *dst = 0xff)
  311 + IMPLEMENT_FORWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
  312 + IMPLEMENT_FORWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
  313 + IMPLEMENT_FORWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst))
  314 + IMPLEMENT_FORWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
  315 + IMPLEMENT_FORWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
  316 + IMPLEMENT_FORWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
  317 + IMPLEMENT_FORWARD_BITBLT(notsrc, *dst = (~(*src)))
  318 + IMPLEMENT_FORWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
  319 + IMPLEMENT_FORWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
  320 +
  321 + IMPLEMENT_BACKWARD_BITBLT(0, *dst = 0)
  322 + IMPLEMENT_BACKWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst))
  323 + IMPLEMENT_BACKWARD_BITBLT(nop, (void) 0)
  324 + IMPLEMENT_BACKWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
  325 + IMPLEMENT_BACKWARD_BITBLT(notdst, *dst = ~(*dst))
  326 + IMPLEMENT_BACKWARD_BITBLT(src, *dst = *src)
  327 + IMPLEMENT_BACKWARD_BITBLT(1, *dst = 0xff)
  328 + IMPLEMENT_BACKWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
  329 + IMPLEMENT_BACKWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
  330 + IMPLEMENT_BACKWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst))
  331 + IMPLEMENT_BACKWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
  332 + IMPLEMENT_BACKWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
  333 + IMPLEMENT_BACKWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
  334 + IMPLEMENT_BACKWARD_BITBLT(notsrc, *dst = (~(*src)))
  335 + IMPLEMENT_BACKWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
  336 + IMPLEMENT_BACKWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
  337 +
  338 +static cirrus_bitblt_rop_t cirrus_get_fwd_rop_handler(uint8_t rop)
  339 +{
  340 + cirrus_bitblt_rop_t rop_handler = cirrus_bitblt_rop_fwd_nop;
  341 +
  342 + switch (rop) {
  343 + case CIRRUS_ROP_0:
  344 + rop_handler = cirrus_bitblt_rop_fwd_0;
  345 + break;
  346 + case CIRRUS_ROP_SRC_AND_DST:
  347 + rop_handler = cirrus_bitblt_rop_fwd_src_and_dst;
  348 + break;
  349 + case CIRRUS_ROP_NOP:
  350 + rop_handler = cirrus_bitblt_rop_fwd_nop;
  351 + break;
  352 + case CIRRUS_ROP_SRC_AND_NOTDST:
  353 + rop_handler = cirrus_bitblt_rop_fwd_src_and_notdst;
  354 + break;
  355 + case CIRRUS_ROP_NOTDST:
  356 + rop_handler = cirrus_bitblt_rop_fwd_notdst;
  357 + break;
  358 + case CIRRUS_ROP_SRC:
  359 + rop_handler = cirrus_bitblt_rop_fwd_src;
  360 + break;
  361 + case CIRRUS_ROP_1:
  362 + rop_handler = cirrus_bitblt_rop_fwd_1;
  363 + break;
  364 + case CIRRUS_ROP_NOTSRC_AND_DST:
  365 + rop_handler = cirrus_bitblt_rop_fwd_notsrc_and_dst;
  366 + break;
  367 + case CIRRUS_ROP_SRC_XOR_DST:
  368 + rop_handler = cirrus_bitblt_rop_fwd_src_xor_dst;
  369 + break;
  370 + case CIRRUS_ROP_SRC_OR_DST:
  371 + rop_handler = cirrus_bitblt_rop_fwd_src_or_dst;
  372 + break;
  373 + case CIRRUS_ROP_NOTSRC_OR_NOTDST:
  374 + rop_handler = cirrus_bitblt_rop_fwd_notsrc_or_notdst;
  375 + break;
  376 + case CIRRUS_ROP_SRC_NOTXOR_DST:
  377 + rop_handler = cirrus_bitblt_rop_fwd_src_notxor_dst;
  378 + break;
  379 + case CIRRUS_ROP_SRC_OR_NOTDST:
  380 + rop_handler = cirrus_bitblt_rop_fwd_src_or_notdst;
  381 + break;
  382 + case CIRRUS_ROP_NOTSRC:
  383 + rop_handler = cirrus_bitblt_rop_fwd_notsrc;
  384 + break;
  385 + case CIRRUS_ROP_NOTSRC_OR_DST:
  386 + rop_handler = cirrus_bitblt_rop_fwd_notsrc_or_dst;
  387 + break;
  388 + case CIRRUS_ROP_NOTSRC_AND_NOTDST:
  389 + rop_handler = cirrus_bitblt_rop_fwd_notsrc_and_notdst;
  390 + break;
  391 + default:
  392 +#ifdef DEBUG_CIRRUS
  393 + printf("unknown ROP %02x\n", rop);
  394 +#endif
  395 + break;
  396 + }
  397 +
  398 + return rop_handler;
  399 +}
  400 +
  401 +static cirrus_bitblt_rop_t cirrus_get_bkwd_rop_handler(uint8_t rop)
  402 +{
  403 + cirrus_bitblt_rop_t rop_handler = cirrus_bitblt_rop_bkwd_nop;
  404 +
  405 + switch (rop) {
  406 + case CIRRUS_ROP_0:
  407 + rop_handler = cirrus_bitblt_rop_bkwd_0;
  408 + break;
  409 + case CIRRUS_ROP_SRC_AND_DST:
  410 + rop_handler = cirrus_bitblt_rop_bkwd_src_and_dst;
  411 + break;
  412 + case CIRRUS_ROP_NOP:
  413 + rop_handler = cirrus_bitblt_rop_bkwd_nop;
  414 + break;
  415 + case CIRRUS_ROP_SRC_AND_NOTDST:
  416 + rop_handler = cirrus_bitblt_rop_bkwd_src_and_notdst;
  417 + break;
  418 + case CIRRUS_ROP_NOTDST:
  419 + rop_handler = cirrus_bitblt_rop_bkwd_notdst;
  420 + break;
  421 + case CIRRUS_ROP_SRC:
  422 + rop_handler = cirrus_bitblt_rop_bkwd_src;
  423 + break;
  424 + case CIRRUS_ROP_1:
  425 + rop_handler = cirrus_bitblt_rop_bkwd_1;
  426 + break;
  427 + case CIRRUS_ROP_NOTSRC_AND_DST:
  428 + rop_handler = cirrus_bitblt_rop_bkwd_notsrc_and_dst;
  429 + break;
  430 + case CIRRUS_ROP_SRC_XOR_DST:
  431 + rop_handler = cirrus_bitblt_rop_bkwd_src_xor_dst;
  432 + break;
  433 + case CIRRUS_ROP_SRC_OR_DST:
  434 + rop_handler = cirrus_bitblt_rop_bkwd_src_or_dst;
  435 + break;
  436 + case CIRRUS_ROP_NOTSRC_OR_NOTDST:
  437 + rop_handler = cirrus_bitblt_rop_bkwd_notsrc_or_notdst;
  438 + break;
  439 + case CIRRUS_ROP_SRC_NOTXOR_DST:
  440 + rop_handler = cirrus_bitblt_rop_bkwd_src_notxor_dst;
  441 + break;
  442 + case CIRRUS_ROP_SRC_OR_NOTDST:
  443 + rop_handler = cirrus_bitblt_rop_bkwd_src_or_notdst;
  444 + break;
  445 + case CIRRUS_ROP_NOTSRC:
  446 + rop_handler = cirrus_bitblt_rop_bkwd_notsrc;
  447 + break;
  448 + case CIRRUS_ROP_NOTSRC_OR_DST:
  449 + rop_handler = cirrus_bitblt_rop_bkwd_notsrc_or_dst;
  450 + break;
  451 + case CIRRUS_ROP_NOTSRC_AND_NOTDST:
  452 + rop_handler = cirrus_bitblt_rop_bkwd_notsrc_and_notdst;
  453 + break;
  454 + default:
  455 +#ifdef DEBUG_CIRRUS
  456 + printf("unknown ROP %02x\n", rop);
  457 +#endif
  458 + break;
  459 + }
  460 +
  461 + return rop_handler;
  462 +}
  463 +
  464 +/***************************************
  465 + *
  466 + * color expansion
  467 + *
  468 + ***************************************/
  469 +
  470 +static void
  471 +cirrus_colorexpand_8(CirrusVGAState * s, uint8_t * dst,
  472 + const uint8_t * src, int count)
  473 +{
  474 + int x;
  475 + uint8_t colors[2];
  476 + unsigned bits;
  477 + unsigned bitmask;
  478 + int srcskipleft = 0;
  479 +
  480 + colors[0] = s->gr[0x00];
  481 + colors[1] = s->gr[0x01];
  482 +
  483 + bitmask = 0x80 >> srcskipleft;
  484 + bits = *src++;
  485 + for (x = 0; x < count; x++) {
  486 + if ((bitmask & 0xff) == 0) {
  487 + bitmask = 0x80;
  488 + bits = *src++;
  489 + }
  490 + *dst++ = colors[!!(bits & bitmask)];
  491 + bitmask >>= 1;
  492 + }
  493 +}
  494 +
  495 +static void
  496 +cirrus_colorexpand_16(CirrusVGAState * s, uint8_t * dst,
  497 + const uint8_t * src, int count)
  498 +{
  499 + int x;
  500 + uint8_t colors[2][2];
  501 + unsigned bits;
  502 + unsigned bitmask;
  503 + unsigned index;
  504 + int srcskipleft = 0;
  505 +
  506 + colors[0][0] = s->gr[0x00];
  507 + colors[0][1] = s->gr[0x10];
  508 + colors[1][0] = s->gr[0x01];
  509 + colors[1][1] = s->gr[0x11];
  510 +
  511 + bitmask = 0x80 >> srcskipleft;
  512 + bits = *src++;
  513 + for (x = 0; x < count; x++) {
  514 + if ((bitmask & 0xff) == 0) {
  515 + bitmask = 0x80;
  516 + bits = *src++;
  517 + }
  518 + index = !!(bits & bitmask);
  519 + *dst++ = colors[index][0];
  520 + *dst++ = colors[index][1];
  521 + bitmask >>= 1;
  522 + }
  523 +}
  524 +
  525 +static void
  526 +cirrus_colorexpand_24(CirrusVGAState * s, uint8_t * dst,
  527 + const uint8_t * src, int count)
  528 +{
  529 + int x;
  530 + uint8_t colors[2][3];
  531 + unsigned bits;
  532 + unsigned bitmask;
  533 + unsigned index;
  534 + int srcskipleft = 0;
  535 +
  536 + colors[0][0] = s->gr[0x00];
  537 + colors[0][1] = s->gr[0x10];
  538 + colors[0][2] = s->gr[0x12];
  539 + colors[1][0] = s->gr[0x01];
  540 + colors[1][1] = s->gr[0x11];
  541 + colors[1][2] = s->gr[0x13];
  542 +
  543 + bitmask = 0x80 << srcskipleft;
  544 + bits = *src++;
  545 + for (x = 0; x < count; x++) {
  546 + if ((bitmask & 0xff) == 0) {
  547 + bitmask = 0x80;
  548 + bits = *src++;
  549 + }
  550 + index = !!(bits & bitmask);
  551 + *dst++ = colors[index][0];
  552 + *dst++ = colors[index][1];
  553 + *dst++ = colors[index][2];
  554 + bitmask >>= 1;
  555 + }
  556 +}
  557 +
  558 +static void
  559 +cirrus_colorexpand_32(CirrusVGAState * s, uint8_t * dst,
  560 + const uint8_t * src, int count)
  561 +{
  562 + int x;
  563 + uint8_t colors[2][4];
  564 + unsigned bits;
  565 + unsigned bitmask;
  566 + unsigned index;
  567 + int srcskipleft = 0;
  568 +
  569 + colors[0][0] = s->gr[0x00];
  570 + colors[0][1] = s->gr[0x10];
  571 + colors[0][2] = s->gr[0x12];
  572 + colors[0][3] = s->gr[0x14];
  573 + colors[1][0] = s->gr[0x01];
  574 + colors[1][1] = s->gr[0x11];
  575 + colors[1][2] = s->gr[0x13];
  576 + colors[1][3] = s->gr[0x15];
  577 +
  578 + bitmask = 0x80 << srcskipleft;
  579 + bits = *src++;
  580 + for (x = 0; x < count; x++) {
  581 + if ((bitmask & 0xff) == 0) {
  582 + bitmask = 0x80;
  583 + bits = *src++;
  584 + }
  585 + index = !!(bits & bitmask);
  586 + *dst++ = colors[index][0];
  587 + *dst++ = colors[index][1];
  588 + *dst++ = colors[index][2];
  589 + *dst++ = colors[index][3];
  590 + bitmask >>= 1;
  591 + }
  592 +}
  593 +
  594 +static void
  595 +cirrus_colorexpand(CirrusVGAState * s, uint8_t * dst, const uint8_t * src,
  596 + int count)
  597 +{
  598 + switch (s->cirrus_blt_pixelwidth) {
  599 + case 1:
  600 + cirrus_colorexpand_8(s, dst, src, count);
  601 + break;
  602 + case 2:
  603 + cirrus_colorexpand_16(s, dst, src, count);
  604 + break;
  605 + case 3:
  606 + cirrus_colorexpand_24(s, dst, src, count);
  607 + break;
  608 + case 4:
  609 + cirrus_colorexpand_32(s, dst, src, count);
  610 + break;
  611 + default:
  612 +#ifdef DEBUG_CIRRUS
  613 + printf("cirrus: COLOREXPAND pixelwidth %d - unimplemented\n",
  614 + s->cirrus_blt_pixelwidth);
  615 +#endif
  616 + break;
  617 + }
  618 +}
  619 +
  620 +static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
  621 + int off_pitch, int bytesperline,
  622 + int lines)
  623 +{
  624 + int y;
  625 + int off_cur;
  626 + int off_cur_end;
  627 +
  628 + for (y = 0; y < lines; y++) {
  629 + off_cur = off_begin;
  630 + off_cur_end = off_cur + bytesperline;
  631 + off_cur &= TARGET_PAGE_MASK;
  632 + while (off_cur < off_cur_end) {
  633 + cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
  634 + off_cur += TARGET_PAGE_SIZE;
  635 + }
  636 + off_begin += off_pitch;
  637 + }
  638 +}
  639 +
  640 +
  641 +
  642 +static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
  643 + const uint8_t * src)
  644 +{
  645 + uint8_t work_colorexp[256];
  646 + uint8_t *dst;
  647 + uint8_t *dstc;
  648 + int x, y;
  649 + int tilewidth, tileheight;
  650 + int patternbytes = s->cirrus_blt_pixelwidth * 8;
  651 +
  652 + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
  653 + cirrus_colorexpand(s, work_colorexp, src, 8 * 8);
  654 + src = work_colorexp;
  655 + s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_COLOREXPAND;
  656 + }
  657 + if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_PATTERNCOPY) {
  658 +#ifdef DEBUG_CIRRUS
  659 + printf("cirrus: blt mode %02x (pattercopy) - unimplemented\n",
  660 + s->cirrus_blt_mode);
  661 +#endif
  662 + return 0;
  663 + }
  664 +
  665 + dst = s->vram_ptr + s->cirrus_blt_dstaddr;
  666 + for (y = 0; y < s->cirrus_blt_height; y += 8) {
  667 + dstc = dst;
  668 + tileheight = qemu_MIN(8, s->cirrus_blt_height - y);
  669 + for (x = 0; x < s->cirrus_blt_width; x += patternbytes) {
  670 + tilewidth = qemu_MIN(patternbytes, s->cirrus_blt_width - x);
  671 + (*s->cirrus_rop) (dstc, src,
  672 + s->cirrus_blt_dstpitch, patternbytes,
  673 + tilewidth, tileheight);
  674 + dstc += patternbytes;
  675 + }
  676 + dst += s->cirrus_blt_dstpitch * 8;
  677 + }
  678 + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
  679 + s->cirrus_blt_dstpitch, s->cirrus_blt_width,
  680 + s->cirrus_blt_height);
  681 + return 1;
  682 +}
  683 +
  684 +/***************************************
  685 + *
  686 + * bitblt (video-to-video)
  687 + *
  688 + ***************************************/
  689 +
  690 +static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
  691 +{
  692 + return cirrus_bitblt_common_patterncopy(s,
  693 + s->vram_ptr +
  694 + s->cirrus_blt_srcaddr);
  695 +}
  696 +
  697 +static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
  698 +{
  699 + if ((s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) != 0) {
  700 +#ifdef DEBUG_CIRRUS
  701 + printf("cirrus: CIRRUS_BLTMODE_COLOREXPAND - unimplemented\n");
  702 +#endif
  703 + return 0;
  704 + }
  705 + if ((s->cirrus_blt_mode & (~CIRRUS_BLTMODE_BACKWARDS)) != 0) {
  706 +#ifdef DEBUG_CIRRUS
  707 + printf("cirrus: blt mode %02x - unimplemented\n",
  708 + s->cirrus_blt_mode);
  709 +#endif
  710 + return 0;
  711 + }
  712 +
  713 + (*s->cirrus_rop) (s->vram_ptr + s->cirrus_blt_dstaddr,
  714 + s->vram_ptr + s->cirrus_blt_srcaddr,
  715 + s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
  716 + s->cirrus_blt_width, s->cirrus_blt_height);
  717 + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
  718 + s->cirrus_blt_dstpitch, s->cirrus_blt_width,
  719 + s->cirrus_blt_height);
  720 + return 1;
  721 +}
  722 +
  723 +/***************************************
  724 + *
  725 + * bitblt (cpu-to-video)
  726 + *
  727 + ***************************************/
  728 +
  729 +static void cirrus_bitblt_cputovideo_patterncopy(void *opaque)
  730 +{
  731 + CirrusVGAState *s = (CirrusVGAState *) opaque;
  732 + int data_count;
  733 +
  734 + data_count = s->cirrus_srcptr - &s->cirrus_bltbuf[0];
  735 +
  736 + if (data_count > 0) {
  737 + if (data_count != s->cirrus_srccounter) {
  738 +#ifdef DEBUG_CIRRUS
  739 + printf("cirrus: internal error\n");
  740 +#endif
  741 + } else {
  742 + cirrus_bitblt_common_patterncopy(s, &s->cirrus_bltbuf[0]);
  743 + }
  744 + cirrus_bitblt_reset(s);
  745 + }
  746 +}
  747 +
  748 +static void cirrus_bitblt_cputovideo_copy(void *opaque)
  749 +{
  750 + CirrusVGAState *s = (CirrusVGAState *) opaque;
  751 + int data_count;
  752 + int data_avail;
  753 + uint8_t work_colorexp[256];
  754 + uint8_t *src_ptr = NULL;
  755 + int src_avail = 0;
  756 + int src_processing;
  757 + int src_linepad = 0;
  758 +
  759 + if (s->cirrus_blt_height <= 0) {
  760 + s->cirrus_srcptr = s->cirrus_srcptr_end;
  761 + return;
  762 + }
  763 +
  764 + s->cirrus_srcptr = &s->cirrus_bltbuf[0];
  765 + while (1) {
  766 + /* get BLT source. */
  767 + if (src_avail <= 0) {
  768 + data_count = s->cirrus_srcptr_end - s->cirrus_srcptr;
  769 + if (data_count <= 0)
  770 + break;
  771 +
  772 + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
  773 + if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_COLOREXPAND) {
  774 +#ifdef DEBUG_CIRRUS
  775 + printf("cirrus: unsupported\n");
  776 +#endif
  777 + cirrus_bitblt_reset(s);
  778 + return;
  779 + }
  780 + data_avail = qemu_MIN(data_count, 256 / 32);
  781 + cirrus_colorexpand(s, work_colorexp, s->cirrus_srcptr,
  782 + data_avail * 8);
  783 + src_ptr = &work_colorexp[0];
  784 + src_avail = data_avail * 8 * s->cirrus_blt_pixelwidth;
  785 + s->cirrus_srcptr += data_avail;
  786 + src_linepad =
  787 + ((s->cirrus_blt_width + 7) / 8) * 8 -
  788 + s->cirrus_blt_width;
  789 + src_linepad *= s->cirrus_blt_pixelwidth;
  790 + } else {
  791 + if (s->cirrus_blt_mode != 0) {
  792 +#ifdef DEBUG_CIRRUS
  793 + printf("cirrus: unsupported\n");
  794 +#endif
  795 + cirrus_bitblt_reset(s);
  796 + return;
  797 + }
  798 + src_ptr = s->cirrus_srcptr;
  799 + src_avail =
  800 + data_count / s->cirrus_blt_pixelwidth *
  801 + s->cirrus_blt_pixelwidth;
  802 + s->cirrus_srcptr += src_avail;
  803 + }
  804 + if (src_avail <= 0)
  805 + break;
  806 + }
  807 +
  808 + /* 1-line BLT */
  809 + src_processing =
  810 + s->cirrus_blt_srcpitch - s->cirrus_blt_horz_counter;
  811 + src_processing = qemu_MIN(src_avail, src_processing);
  812 + (*s->cirrus_rop) (s->vram_ptr + s->cirrus_blt_dstaddr,
  813 + src_ptr, 0, 0, src_processing, 1);
  814 + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
  815 + src_processing, 1);
  816 +
  817 + s->cirrus_blt_dstaddr += src_processing;
  818 + src_ptr += src_processing;
  819 + src_avail -= src_processing;
  820 + s->cirrus_blt_horz_counter += src_processing;
  821 + if (s->cirrus_blt_horz_counter >= s->cirrus_blt_srcpitch) {
  822 + src_ptr += src_linepad;
  823 + src_avail -= src_linepad;
  824 + s->cirrus_blt_dstaddr +=
  825 + s->cirrus_blt_dstpitch - s->cirrus_blt_srcpitch;
  826 + s->cirrus_blt_horz_counter = 0;
  827 + s->cirrus_blt_height--;
  828 + if (s->cirrus_blt_height <= 0) {
  829 + s->cirrus_srcptr = s->cirrus_srcptr_end;
  830 + return;
  831 + }
  832 + }
  833 + }
  834 +}
  835 +
  836 +static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
  837 +{
  838 + int copy_count;
  839 + int avail_count;
  840 +
  841 + s->cirrus_blt_handler(s);
  842 +
  843 + if (s->cirrus_srccounter > 0) {
  844 + s->cirrus_srccounter -= s->cirrus_srcptr - &s->cirrus_bltbuf[0];
  845 + copy_count = s->cirrus_srcptr_end - s->cirrus_srcptr;
  846 + memmove(&s->cirrus_bltbuf[0], s->cirrus_srcptr, copy_count);
  847 + avail_count = qemu_MIN(CIRRUS_BLTBUFSIZE, s->cirrus_srccounter);
  848 + s->cirrus_srcptr = &s->cirrus_bltbuf[0];
  849 + s->cirrus_srcptr_end = s->cirrus_srcptr + avail_count;
  850 + if (s->cirrus_srccounter <= 0) {
  851 + cirrus_bitblt_reset(s);
  852 + }
  853 + }
  854 +}
  855 +
  856 +/***************************************
  857 + *
  858 + * bitblt wrapper
  859 + *
  860 + ***************************************/
  861 +
  862 +static void cirrus_bitblt_reset(CirrusVGAState * s)
  863 +{
  864 + s->gr[0x31] &=
  865 + ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED);
  866 + s->cirrus_srcptr = &s->cirrus_bltbuf[0];
  867 + s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
  868 + s->cirrus_srccounter = 0;
  869 + s->cirrus_dstptr = &s->cirrus_bltbuf[0];
  870 + s->cirrus_dstptr_end = &s->cirrus_bltbuf[0];
  871 + s->cirrus_dstcounter = 0;
  872 + s->cirrus_blt_handler = NULL;
  873 +}
  874 +
  875 +static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
  876 +{
  877 + s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
  878 + s->cirrus_srcptr = &s->cirrus_bltbuf[0];
  879 + s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
  880 +
  881 + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
  882 + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
  883 + s->cirrus_srccounter = 8;
  884 + } else {
  885 + s->cirrus_srccounter = 8 * 8 * s->cirrus_blt_pixelwidth;
  886 + }
  887 + s->cirrus_blt_srcpitch = 0;
  888 + s->cirrus_blt_handler = cirrus_bitblt_cputovideo_patterncopy;
  889 + } else {
  890 + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
  891 + s->cirrus_srccounter =
  892 + ((s->cirrus_blt_width + 7) / 8) * s->cirrus_blt_height;
  893 + s->cirrus_blt_srcpitch =
  894 + s->cirrus_blt_width * s->cirrus_blt_pixelwidth;
  895 + } else {
  896 + s->cirrus_srccounter =
  897 + s->cirrus_blt_width * s->cirrus_blt_height;
  898 + s->cirrus_blt_srcpitch = s->cirrus_blt_width;
  899 + }
  900 + /* 4-byte alignment */
  901 + s->cirrus_srccounter = (s->cirrus_srccounter + 3) & (~3);
  902 +
  903 + s->cirrus_blt_handler = cirrus_bitblt_cputovideo_copy;
  904 + s->cirrus_blt_horz_counter = 0;
  905 + }
  906 +
  907 + cirrus_bitblt_cputovideo_next(s);
  908 + return 1;
  909 +}
  910 +
  911 +static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
  912 +{
  913 + /* XXX */
  914 +#ifdef DEBUG_CIRRUS
  915 + printf("cirrus: bitblt (video to cpu) is not implemented yet\n");
  916 +#endif
  917 + return 0;
  918 +}
  919 +
  920 +static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
  921 +{
  922 + int ret;
  923 +
  924 + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
  925 + ret = cirrus_bitblt_videotovideo_patterncopy(s);
  926 + } else {
  927 + ret = cirrus_bitblt_videotovideo_copy(s);
  928 + }
  929 +
  930 + if (ret)
  931 + cirrus_bitblt_reset(s);
  932 + return ret;
  933 +}
  934 +
  935 +static void cirrus_bitblt_start(CirrusVGAState * s)
  936 +{
  937 + uint8_t blt_rop;
  938 +
  939 + s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1;
  940 + s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1;
  941 + s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8));
  942 + s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8));
  943 + s->cirrus_blt_dstaddr =
  944 + (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16));
  945 + s->cirrus_blt_srcaddr =
  946 + (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16));
  947 + s->cirrus_blt_mode = s->gr[0x30];
  948 + blt_rop = s->gr[0x32];
  949 +
  950 + switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
  951 + case CIRRUS_BLTMODE_PIXELWIDTH8:
  952 + s->cirrus_blt_pixelwidth = 1;
  953 + break;
  954 + case CIRRUS_BLTMODE_PIXELWIDTH16:
  955 + s->cirrus_blt_pixelwidth = 2;
  956 + break;
  957 + case CIRRUS_BLTMODE_PIXELWIDTH24:
  958 + s->cirrus_blt_pixelwidth = 3;
  959 + break;
  960 + case CIRRUS_BLTMODE_PIXELWIDTH32:
  961 + s->cirrus_blt_pixelwidth = 4;
  962 + break;
  963 + default:
  964 +#ifdef DEBUG_CIRRUS
  965 + printf("cirrus: bitblt - pixel width is unknown\n");
  966 +#endif
  967 + goto bitblt_ignore;
  968 + }
  969 + s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
  970 +
  971 + if ((s->
  972 + cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
  973 + CIRRUS_BLTMODE_MEMSYSDEST))
  974 + == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
  975 +#ifdef DEBUG_CIRRUS
  976 + printf("cirrus: bitblt - memory-to-memory copy is requested\n");
  977 +#endif
  978 + goto bitblt_ignore;
  979 + }
  980 +
  981 + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
  982 + s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
  983 + s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
  984 + s->cirrus_rop = cirrus_get_bkwd_rop_handler(blt_rop);
  985 + } else {
  986 + s->cirrus_rop = cirrus_get_fwd_rop_handler(blt_rop);
  987 + }
  988 +
  989 + // setup bitblt engine.
  990 + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
  991 + if (!cirrus_bitblt_cputovideo(s))
  992 + goto bitblt_ignore;
  993 + } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
  994 + if (!cirrus_bitblt_videotocpu(s))
  995 + goto bitblt_ignore;
  996 + } else {
  997 + if (!cirrus_bitblt_videotovideo(s))
  998 + goto bitblt_ignore;
  999 + }
  1000 +
  1001 + return;
  1002 + bitblt_ignore:;
  1003 + cirrus_bitblt_reset(s);
  1004 +}
  1005 +
  1006 +static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
  1007 +{
  1008 + unsigned old_value;
  1009 +
  1010 + old_value = s->gr[0x31];
  1011 + s->gr[0x31] = reg_value;
  1012 +
  1013 + if (((old_value & CIRRUS_BLT_RESET) != 0) &&
  1014 + ((reg_value & CIRRUS_BLT_RESET) == 0)) {
  1015 + cirrus_bitblt_reset(s);
  1016 + } else if (((old_value & CIRRUS_BLT_START) == 0) &&
  1017 + ((reg_value & CIRRUS_BLT_START) != 0)) {
  1018 + s->gr[0x31] |= CIRRUS_BLT_BUSY;
  1019 + cirrus_bitblt_start(s);
  1020 + }
  1021 +}
  1022 +
  1023 +
  1024 +/***************************************
  1025 + *
  1026 + * basic parameters
  1027 + *
  1028 + ***************************************/
  1029 +
  1030 +static void cirrus_get_offsets(VGAState *s1,
  1031 + uint32_t *pline_offset,
  1032 + uint32_t *pstart_addr)
  1033 +{
  1034 + CirrusVGAState * s = (CirrusVGAState *)s1;
  1035 + uint32_t start_addr;
  1036 + uint32_t line_offset;
  1037 +
  1038 + line_offset = s->cr[0x13]
  1039 + | ((s->cr[0x1b] & 0x10) << 8);
  1040 + line_offset <<= 3;
  1041 + *pline_offset = line_offset;
  1042 +
  1043 + start_addr = (s->cr[0x0c] << 8)
  1044 + | s->cr[0x0d]
  1045 + | ((s->cr[0x1b] & 0x01) << 16)
  1046 + | ((s->cr[0x1b] & 0x0c) << 15)
  1047 + | ((s->cr[0x1d] & 0x80) << 12);
  1048 + *pstart_addr = start_addr;
  1049 +}
  1050 +
  1051 +static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
  1052 +{
  1053 + uint32_t ret = 16;
  1054 +
  1055 + switch (s->cirrus_hidden_dac_data & 0xf) {
  1056 + case 0:
  1057 + ret = 15;
  1058 + break; /* Sierra HiColor */
  1059 + case 1:
  1060 + ret = 16;
  1061 + break; /* XGA HiColor */
  1062 + default:
  1063 +#ifdef DEBUG_CIRRUS
  1064 + printf("cirrus: invalid DAC value %x in 16bpp\n",
  1065 + (s->cirrus_hidden_dac_data & 0xf));
  1066 +#endif
  1067 + ret = 15; /* XXX */
  1068 + break;
  1069 + }
  1070 + return ret;
  1071 +}
  1072 +
  1073 +static int cirrus_get_bpp(VGAState *s1)
  1074 +{
  1075 + CirrusVGAState * s = (CirrusVGAState *)s1;
  1076 + uint32_t ret = 8;
  1077 +
  1078 + if ((s->sr[0x07] & 0x01) != 0) {
  1079 + /* Cirrus SVGA */
  1080 + switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) {
  1081 + case CIRRUS_SR7_BPP_8:
  1082 + ret = 8;
  1083 + break;
  1084 + case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
  1085 + ret = cirrus_get_bpp16_depth(s);
  1086 + break;
  1087 + case CIRRUS_SR7_BPP_24:
  1088 + ret = 24;
  1089 + break;
  1090 + case CIRRUS_SR7_BPP_16:
  1091 + ret = cirrus_get_bpp16_depth(s);
  1092 + break;
  1093 + case CIRRUS_SR7_BPP_32:
  1094 + ret = 32;
  1095 + break;
  1096 + default:
  1097 +#ifdef DEBUG_CIRRUS
  1098 + printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]);
  1099 +#endif
  1100 + ret = 8;
  1101 + break;
  1102 + }
  1103 + } else {
  1104 + /* VGA */
  1105 + ret = 8;
  1106 + }
  1107 +
  1108 + return ret;
  1109 +}
  1110 +
  1111 +/***************************************
  1112 + *
  1113 + * bank memory
  1114 + *
  1115 + ***************************************/
  1116 +
  1117 +static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
  1118 +{
  1119 + unsigned offset;
  1120 + unsigned limit;
  1121 +
  1122 + if ((s->gr[0x0b] & 0x01) != 0) /* dual bank */
  1123 + offset = s->gr[0x09 + bank_index];
  1124 + else /* single bank */
  1125 + offset = s->gr[0x09];
  1126 +
  1127 + if ((s->gr[0x0b] & 0x20) != 0)
  1128 + offset <<= 14;
  1129 + else
  1130 + offset <<= 12;
  1131 +
  1132 + if (s->vram_size <= offset)
  1133 + limit = 0;
  1134 + else
  1135 + limit = s->vram_size - offset;
  1136 +
  1137 + if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
  1138 + if (limit > 0x8000) {
  1139 + offset += 0x8000;
  1140 + limit -= 0x8000;
  1141 + } else {
  1142 + limit = 0;
  1143 + }
  1144 + }
  1145 +
  1146 + if (limit > 0) {
  1147 + s->cirrus_bank_base[bank_index] = offset;
  1148 + s->cirrus_bank_limit[bank_index] = limit;
  1149 + } else {
  1150 + s->cirrus_bank_base[bank_index] = 0;
  1151 + s->cirrus_bank_limit[bank_index] = 0;
  1152 + }
  1153 +}
  1154 +
  1155 +/***************************************
  1156 + *
  1157 + * I/O access between 0x3c4-0x3c5
  1158 + *
  1159 + ***************************************/
  1160 +
  1161 +static int
  1162 +cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
  1163 +{
  1164 + switch (reg_index) {
  1165 + case 0x00: // Standard VGA
  1166 + case 0x01: // Standard VGA
  1167 + case 0x02: // Standard VGA
  1168 + case 0x03: // Standard VGA
  1169 + case 0x04: // Standard VGA
  1170 + return CIRRUS_HOOK_NOT_HANDLED;
  1171 + case 0x06: // Unlock Cirrus extensions
  1172 + *reg_value = s->sr[reg_index];
  1173 + break;
  1174 + case 0x05: // ???
  1175 + case 0x07: // Extended Sequencer Mode
  1176 + case 0x08: // EEPROM Control
  1177 + case 0x09: // Scratch Register 0
  1178 + case 0x0a: // Scratch Register 1
  1179 + case 0x0b: // VCLK 0
  1180 + case 0x0c: // VCLK 1
  1181 + case 0x0d: // VCLK 2
  1182 + case 0x0e: // VCLK 3
  1183 + case 0x0f: // DRAM Control
  1184 + case 0x10:
  1185 + case 0x30:
  1186 + case 0x50:
  1187 + case 0x70: // Graphics Cursor X
  1188 + case 0x90:
  1189 + case 0xb0:
  1190 + case 0xd0:
  1191 + case 0xf0: // Graphics Cursor X
  1192 + case 0x11:
  1193 + case 0x31:
  1194 + case 0x51:
  1195 + case 0x71: // Graphics Cursor Y
  1196 + case 0x91:
  1197 + case 0xb1:
  1198 + case 0xd1:
  1199 + case 0xf1: // Graphics Cursor Y
  1200 + case 0x12: // Graphics Cursor Attribute
  1201 + case 0x13: // Graphics Cursor Pattern Address
  1202 + case 0x14: // Scratch Register 2
  1203 + case 0x15: // Scratch Register 3
  1204 + case 0x16: // Performance Tuning Register
  1205 + case 0x17: // Configuration Readback and Extended Control
  1206 + case 0x18: // Signature Generator Control
  1207 + case 0x19: // Signal Generator Result
  1208 + case 0x1a: // Signal Generator Result
  1209 + case 0x1b: // VCLK 0 Denominator & Post
  1210 + case 0x1c: // VCLK 1 Denominator & Post
  1211 + case 0x1d: // VCLK 2 Denominator & Post
  1212 + case 0x1e: // VCLK 3 Denominator & Post
  1213 + case 0x1f: // BIOS Write Enable and MCLK select
  1214 +#ifdef DEBUG_CIRRUS
  1215 + printf("cirrus: handled inport sr_index %02x\n", reg_index);
  1216 +#endif
  1217 + *reg_value = s->sr[reg_index];
  1218 + break;
  1219 + default:
  1220 +#ifdef DEBUG_CIRRUS
  1221 + printf("cirrus: inport sr_index %02x\n", reg_index);
  1222 +#endif
  1223 + *reg_value = 0xff;
  1224 + break;
  1225 + }
  1226 +
  1227 + return CIRRUS_HOOK_HANDLED;
  1228 +}
  1229 +
  1230 +static int
  1231 +cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
  1232 +{
  1233 + switch (reg_index) {
  1234 + case 0x00: // Standard VGA
  1235 + case 0x01: // Standard VGA
  1236 + case 0x02: // Standard VGA
  1237 + case 0x03: // Standard VGA
  1238 + case 0x04: // Standard VGA
  1239 + return CIRRUS_HOOK_NOT_HANDLED;
  1240 + case 0x06: // Unlock Cirrus extensions
  1241 + reg_value &= 0x17;
  1242 + if (reg_value == 0x12) {
  1243 + s->sr[reg_index] = 0x12;
  1244 + } else {
  1245 + s->sr[reg_index] = 0x0f;
  1246 + }
  1247 + break;
  1248 + case 0x10:
  1249 + case 0x30:
  1250 + case 0x50:
  1251 + case 0x70: // Graphics Cursor X
  1252 + case 0x90:
  1253 + case 0xb0:
  1254 + case 0xd0:
  1255 + case 0xf0: // Graphics Cursor X
  1256 + s->sr[0x10] = reg_value;
  1257 + s->cirrus_hw_cursor_x = ((reg_index << 3) & 0x700) | reg_value;
  1258 + break;
  1259 + case 0x11:
  1260 + case 0x31:
  1261 + case 0x51:
  1262 + case 0x71: // Graphics Cursor Y
  1263 + case 0x91:
  1264 + case 0xb1:
  1265 + case 0xd1:
  1266 + case 0xf1: // Graphics Cursor Y
  1267 + s->sr[0x11] = reg_value;
  1268 + s->cirrus_hw_cursor_y = ((reg_index << 3) & 0x700) | reg_value;
  1269 + break;
  1270 + case 0x07: // Extended Sequencer Mode
  1271 + case 0x08: // EEPROM Control
  1272 + case 0x09: // Scratch Register 0
  1273 + case 0x0a: // Scratch Register 1
  1274 + case 0x0b: // VCLK 0
  1275 + case 0x0c: // VCLK 1
  1276 + case 0x0d: // VCLK 2
  1277 + case 0x0e: // VCLK 3
  1278 + case 0x0f: // DRAM Control
  1279 + case 0x12: // Graphics Cursor Attribute
  1280 + case 0x13: // Graphics Cursor Pattern Address
  1281 + case 0x14: // Scratch Register 2
  1282 + case 0x15: // Scratch Register 3
  1283 + case 0x16: // Performance Tuning Register
  1284 + case 0x17: // Configuration Readback and Extended Control
  1285 + case 0x18: // Signature Generator Control
  1286 + case 0x19: // Signature Generator Result
  1287 + case 0x1a: // Signature Generator Result
  1288 + case 0x1b: // VCLK 0 Denominator & Post
  1289 + case 0x1c: // VCLK 1 Denominator & Post
  1290 + case 0x1d: // VCLK 2 Denominator & Post
  1291 + case 0x1e: // VCLK 3 Denominator & Post
  1292 + case 0x1f: // BIOS Write Enable and MCLK select
  1293 + s->sr[reg_index] = reg_value;
  1294 +#ifdef DEBUG_CIRRUS
  1295 + printf("cirrus: handled outport sr_index %02x, sr_value %02x\n",
  1296 + reg_index, reg_value);
  1297 +#endif
  1298 + break;
  1299 + default:
  1300 +#ifdef DEBUG_CIRRUS
  1301 + printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index,
  1302 + reg_value);
  1303 +#endif
  1304 + break;
  1305 + }
  1306 +
  1307 + return CIRRUS_HOOK_HANDLED;
  1308 +}
  1309 +
  1310 +/***************************************
  1311 + *
  1312 + * I/O access at 0x3c6
  1313 + *
  1314 + ***************************************/
  1315 +
  1316 +static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value)
  1317 +{
  1318 + *reg_value = 0xff;
  1319 + if (s->cirrus_hidden_dac_lockindex < 5) {
  1320 + if (s->cirrus_hidden_dac_lockindex == 4) {
  1321 + *reg_value = s->cirrus_hidden_dac_data;
  1322 + }
  1323 + s->cirrus_hidden_dac_lockindex++;
  1324 + }
  1325 +}
  1326 +
  1327 +static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
  1328 +{
  1329 + if (s->cirrus_hidden_dac_lockindex == 4) {
  1330 + s->cirrus_hidden_dac_data = reg_value;
  1331 +#ifdef DEBUG_CIRRUS
  1332 + printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
  1333 +#endif
  1334 + }
  1335 + s->cirrus_hidden_dac_lockindex = 0;
  1336 +}
  1337 +
  1338 +/***************************************
  1339 + *
  1340 + * I/O access at 0x3c9
  1341 + *
  1342 + ***************************************/
  1343 +
  1344 +static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value)
  1345 +{
  1346 + if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
  1347 + return CIRRUS_HOOK_NOT_HANDLED;
  1348 + if (s->dac_read_index < 0x10) {
  1349 + *reg_value =
  1350 + s->cirrus_hidden_palette[s->dac_read_index * 3 +
  1351 + s->dac_sub_index];
  1352 + } else {
  1353 + *reg_value = 0xff; /* XXX */
  1354 + }
  1355 + if (++s->dac_sub_index == 3) {
  1356 + s->dac_sub_index = 0;
  1357 + s->dac_read_index++;
  1358 + }
  1359 + return CIRRUS_HOOK_HANDLED;
  1360 +}
  1361 +
  1362 +static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value)
  1363 +{
  1364 + if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
  1365 + return CIRRUS_HOOK_NOT_HANDLED;
  1366 + s->dac_cache[s->dac_sub_index] = reg_value;
  1367 + if (++s->dac_sub_index == 3) {
  1368 + if (s->dac_read_index < 0x10) {
  1369 + memcpy(&s->cirrus_hidden_palette[s->dac_write_index * 3],
  1370 + s->dac_cache, 3);
  1371 + /* XXX update cursor */
  1372 + }
  1373 + s->dac_sub_index = 0;
  1374 + s->dac_write_index++;
  1375 + }
  1376 + return CIRRUS_HOOK_HANDLED;
  1377 +}
  1378 +
  1379 +/***************************************
  1380 + *
  1381 + * I/O access between 0x3ce-0x3cf
  1382 + *
  1383 + ***************************************/
  1384 +
  1385 +static int
  1386 +cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
  1387 +{
  1388 + switch (reg_index) {
  1389 + case 0x02: // Standard VGA
  1390 + case 0x03: // Standard VGA
  1391 + case 0x04: // Standard VGA
  1392 + case 0x06: // Standard VGA
  1393 + case 0x07: // Standard VGA
  1394 + case 0x08: // Standard VGA
  1395 + return CIRRUS_HOOK_NOT_HANDLED;
  1396 + case 0x05: // Standard VGA, Cirrus extended mode
  1397 + default:
  1398 + break;
  1399 + }
  1400 +
  1401 + if (reg_index < 0x3a) {
  1402 + *reg_value = s->gr[reg_index];
  1403 + } else {
  1404 +#ifdef DEBUG_CIRRUS
  1405 + printf("cirrus: inport gr_index %02x\n", reg_index);
  1406 +#endif
  1407 + *reg_value = 0xff;
  1408 + }
  1409 +
  1410 + return CIRRUS_HOOK_HANDLED;
  1411 +}
  1412 +
  1413 +static int
  1414 +cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
  1415 +{
  1416 + switch (reg_index) {
  1417 + case 0x00: // Standard VGA, BGCOLOR 0x000000ff
  1418 + s->gr[0x00] = reg_value;
  1419 + return CIRRUS_HOOK_NOT_HANDLED;
  1420 + case 0x01: // Standard VGA, FGCOLOR 0x000000ff
  1421 + s->gr[0x01] = reg_value;
  1422 + return CIRRUS_HOOK_NOT_HANDLED;
  1423 + case 0x02: // Standard VGA
  1424 + case 0x03: // Standard VGA
  1425 + case 0x04: // Standard VGA
  1426 + case 0x06: // Standard VGA
  1427 + case 0x07: // Standard VGA
  1428 + case 0x08: // Standard VGA
  1429 + return CIRRUS_HOOK_NOT_HANDLED;
  1430 + case 0x05: // Standard VGA, Cirrus extended mode
  1431 + s->gr[reg_index] = reg_value & 0x7f;
  1432 + break;
  1433 + case 0x09: // bank offset #0
  1434 + case 0x0A: // bank offset #1
  1435 + case 0x0B:
  1436 + s->gr[reg_index] = reg_value;
  1437 + cirrus_update_bank_ptr(s, 0);
  1438 + cirrus_update_bank_ptr(s, 1);
  1439 + break;
  1440 + case 0x10: // BGCOLOR 0x0000ff00
  1441 + case 0x11: // FGCOLOR 0x0000ff00
  1442 + case 0x12: // BGCOLOR 0x00ff0000
  1443 + case 0x13: // FGCOLOR 0x00ff0000
  1444 + case 0x14: // BGCOLOR 0xff000000
  1445 + case 0x15: // FGCOLOR 0xff000000
  1446 + case 0x20: // BLT WIDTH 0x0000ff
  1447 + case 0x22: // BLT HEIGHT 0x0000ff
  1448 + case 0x24: // BLT DEST PITCH 0x0000ff
  1449 + case 0x26: // BLT SRC PITCH 0x0000ff
  1450 + case 0x28: // BLT DEST ADDR 0x0000ff
  1451 + case 0x29: // BLT DEST ADDR 0x00ff00
  1452 + case 0x2c: // BLT SRC ADDR 0x0000ff
  1453 + case 0x2d: // BLT SRC ADDR 0x00ff00
  1454 + case 0x30: // BLT MODE
  1455 + case 0x32: // RASTER OP
  1456 + case 0x34: // BLT TRANSPARENT COLOR 0x00ff
  1457 + case 0x35: // BLT TRANSPARENT COLOR 0xff00
  1458 + case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff
  1459 + case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00
  1460 + s->gr[reg_index] = reg_value;
  1461 + break;
  1462 + case 0x21: // BLT WIDTH 0x001f00
  1463 + case 0x23: // BLT HEIGHT 0x001f00
  1464 + case 0x25: // BLT DEST PITCH 0x001f00
  1465 + case 0x27: // BLT SRC PITCH 0x001f00
  1466 + s->gr[reg_index] = reg_value & 0x1f;
  1467 + break;
  1468 + case 0x2a: // BLT DEST ADDR 0x3f0000
  1469 + case 0x2e: // BLT SRC ADDR 0x3f0000
  1470 + s->gr[reg_index] = reg_value & 0x3f;
  1471 + break;
  1472 + case 0x31: // BLT STATUS/START
  1473 + cirrus_write_bitblt(s, reg_value);
  1474 + break;
  1475 + default:
  1476 +#ifdef DEBUG_CIRRUS
  1477 + printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
  1478 + reg_value);
  1479 +#endif
  1480 + break;
  1481 + }
  1482 +
  1483 + return CIRRUS_HOOK_HANDLED;
  1484 +}
  1485 +
  1486 +/***************************************
  1487 + *
  1488 + * I/O access between 0x3d4-0x3d5
  1489 + *
  1490 + ***************************************/
  1491 +
  1492 +static int
  1493 +cirrus_hook_read_cr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
  1494 +{
  1495 + switch (reg_index) {
  1496 + case 0x00: // Standard VGA
  1497 + case 0x01: // Standard VGA
  1498 + case 0x02: // Standard VGA
  1499 + case 0x03: // Standard VGA
  1500 + case 0x04: // Standard VGA
  1501 + case 0x05: // Standard VGA
  1502 + case 0x06: // Standard VGA
  1503 + case 0x07: // Standard VGA
  1504 + case 0x08: // Standard VGA
  1505 + case 0x09: // Standard VGA
  1506 + case 0x0a: // Standard VGA
  1507 + case 0x0b: // Standard VGA
  1508 + case 0x0c: // Standard VGA
  1509 + case 0x0d: // Standard VGA
  1510 + case 0x0e: // Standard VGA
  1511 + case 0x0f: // Standard VGA
  1512 + case 0x10: // Standard VGA
  1513 + case 0x11: // Standard VGA
  1514 + case 0x12: // Standard VGA
  1515 + case 0x13: // Standard VGA
  1516 + case 0x14: // Standard VGA
  1517 + case 0x15: // Standard VGA
  1518 + case 0x16: // Standard VGA
  1519 + case 0x17: // Standard VGA
  1520 + case 0x18: // Standard VGA
  1521 + return CIRRUS_HOOK_NOT_HANDLED;
  1522 + case 0x19: // Interlace End
  1523 + case 0x1a: // Miscellaneous Control
  1524 + case 0x1b: // Extended Display Control
  1525 + case 0x1c: // Sync Adjust and Genlock
  1526 + case 0x1d: // Overlay Extended Control
  1527 + case 0x22: // Graphics Data Latches Readback (R)
  1528 + case 0x24: // Attribute Controller Toggle Readback (R)
  1529 + case 0x25: // Part Status
  1530 + case 0x27: // Part ID (R)
  1531 + *reg_value = s->cr[reg_index];
  1532 + break;
  1533 + case 0x26: // Attribute Controller Index Readback (R)
  1534 + *reg_value = s->ar_index & 0x3f;
  1535 + break;
  1536 + default:
  1537 +#ifdef DEBUG_CIRRUS
  1538 + printf("cirrus: inport cr_index %02x\n", reg_index);
  1539 + *reg_value = 0xff;
  1540 +#endif
  1541 + break;
  1542 + }
  1543 +
  1544 + return CIRRUS_HOOK_HANDLED;
  1545 +}
  1546 +
  1547 +static int
  1548 +cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value)
  1549 +{
  1550 + switch (reg_index) {
  1551 + case 0x00: // Standard VGA
  1552 + case 0x01: // Standard VGA
  1553 + case 0x02: // Standard VGA
  1554 + case 0x03: // Standard VGA
  1555 + case 0x04: // Standard VGA
  1556 + case 0x05: // Standard VGA
  1557 + case 0x06: // Standard VGA
  1558 + case 0x07: // Standard VGA
  1559 + case 0x08: // Standard VGA
  1560 + case 0x09: // Standard VGA
  1561 + case 0x0a: // Standard VGA
  1562 + case 0x0b: // Standard VGA
  1563 + case 0x0c: // Standard VGA
  1564 + case 0x0d: // Standard VGA
  1565 + case 0x0e: // Standard VGA
  1566 + case 0x0f: // Standard VGA
  1567 + case 0x10: // Standard VGA
  1568 + case 0x11: // Standard VGA
  1569 + case 0x12: // Standard VGA
  1570 + case 0x13: // Standard VGA
  1571 + case 0x14: // Standard VGA
  1572 + case 0x15: // Standard VGA
  1573 + case 0x16: // Standard VGA
  1574 + case 0x17: // Standard VGA
  1575 + case 0x18: // Standard VGA
  1576 + return CIRRUS_HOOK_NOT_HANDLED;
  1577 + case 0x19: // Interlace End
  1578 + case 0x1a: // Miscellaneous Control
  1579 + case 0x1b: // Extended Display Control
  1580 + case 0x1c: // Sync Adjust and Genlock
  1581 + s->cr[reg_index] = reg_value;
  1582 +#ifdef DEBUG_CIRRUS
  1583 + printf("cirrus: handled outport cr_index %02x, cr_value %02x\n",
  1584 + reg_index, reg_value);
  1585 +#endif
  1586 + break;
  1587 + case 0x22: // Graphics Data Latches Readback (R)
  1588 + case 0x24: // Attribute Controller Toggle Readback (R)
  1589 + case 0x26: // Attribute Controller Index Readback (R)
  1590 + case 0x27: // Part ID (R)
  1591 + break;
  1592 + case 0x1d: // Overlay Extended Control
  1593 + case 0x25: // Part Status
  1594 + default:
  1595 +#ifdef DEBUG_CIRRUS
  1596 + printf("cirrus: outport cr_index %02x, cr_value %02x\n", reg_index,
  1597 + reg_value);
  1598 +#endif
  1599 + break;
  1600 + }
  1601 +
  1602 + return CIRRUS_HOOK_HANDLED;
  1603 +}
  1604 +
  1605 +/***************************************
  1606 + *
  1607 + * memory-mapped I/O (bitblt)
  1608 + *
  1609 + ***************************************/
  1610 +
  1611 +static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
  1612 +{
  1613 + int value = 0xff;
  1614 +
  1615 + switch (address) {
  1616 + case (CIRRUS_MMIO_BLTBGCOLOR + 0):
  1617 + cirrus_hook_read_gr(s, 0x00, &value);
  1618 + break;
  1619 + case (CIRRUS_MMIO_BLTBGCOLOR + 1):
  1620 + cirrus_hook_read_gr(s, 0x10, &value);
  1621 + break;
  1622 + case (CIRRUS_MMIO_BLTBGCOLOR + 2):
  1623 + cirrus_hook_read_gr(s, 0x12, &value);
  1624 + break;
  1625 + case (CIRRUS_MMIO_BLTBGCOLOR + 3):
  1626 + cirrus_hook_read_gr(s, 0x14, &value);
  1627 + break;
  1628 + case (CIRRUS_MMIO_BLTFGCOLOR + 0):
  1629 + cirrus_hook_read_gr(s, 0x01, &value);
  1630 + break;
  1631 + case (CIRRUS_MMIO_BLTFGCOLOR + 1):
  1632 + cirrus_hook_read_gr(s, 0x11, &value);
  1633 + break;
  1634 + case (CIRRUS_MMIO_BLTFGCOLOR + 2):
  1635 + cirrus_hook_read_gr(s, 0x13, &value);
  1636 + break;
  1637 + case (CIRRUS_MMIO_BLTFGCOLOR + 3):
  1638 + cirrus_hook_read_gr(s, 0x15, &value);
  1639 + break;
  1640 + case (CIRRUS_MMIO_BLTWIDTH + 0):
  1641 + cirrus_hook_read_gr(s, 0x20, &value);
  1642 + break;
  1643 + case (CIRRUS_MMIO_BLTWIDTH + 1):
  1644 + cirrus_hook_read_gr(s, 0x21, &value);
  1645 + break;
  1646 + case (CIRRUS_MMIO_BLTHEIGHT + 0):
  1647 + cirrus_hook_read_gr(s, 0x22, &value);
  1648 + break;
  1649 + case (CIRRUS_MMIO_BLTHEIGHT + 1):
  1650 + cirrus_hook_read_gr(s, 0x23, &value);
  1651 + break;
  1652 + case (CIRRUS_MMIO_BLTDESTPITCH + 0):
  1653 + cirrus_hook_read_gr(s, 0x24, &value);
  1654 + break;
  1655 + case (CIRRUS_MMIO_BLTDESTPITCH + 1):
  1656 + cirrus_hook_read_gr(s, 0x25, &value);
  1657 + break;
  1658 + case (CIRRUS_MMIO_BLTSRCPITCH + 0):
  1659 + cirrus_hook_read_gr(s, 0x26, &value);
  1660 + break;
  1661 + case (CIRRUS_MMIO_BLTSRCPITCH + 1):
  1662 + cirrus_hook_read_gr(s, 0x27, &value);
  1663 + break;
  1664 + case (CIRRUS_MMIO_BLTDESTADDR + 0):
  1665 + cirrus_hook_read_gr(s, 0x28, &value);
  1666 + break;
  1667 + case (CIRRUS_MMIO_BLTDESTADDR + 1):
  1668 + cirrus_hook_read_gr(s, 0x29, &value);
  1669 + break;
  1670 + case (CIRRUS_MMIO_BLTDESTADDR + 2):
  1671 + cirrus_hook_read_gr(s, 0x2a, &value);
  1672 + break;
  1673 + case (CIRRUS_MMIO_BLTSRCADDR + 0):
  1674 + cirrus_hook_read_gr(s, 0x2c, &value);
  1675 + break;
  1676 + case (CIRRUS_MMIO_BLTSRCADDR + 1):
  1677 + cirrus_hook_read_gr(s, 0x2d, &value);
  1678 + break;
  1679 + case (CIRRUS_MMIO_BLTSRCADDR + 2):
  1680 + cirrus_hook_read_gr(s, 0x2e, &value);
  1681 + break;
  1682 + case CIRRUS_MMIO_BLTWRITEMASK:
  1683 + cirrus_hook_read_gr(s, 0x2f, &value);
  1684 + break;
  1685 + case CIRRUS_MMIO_BLTMODE:
  1686 + cirrus_hook_read_gr(s, 0x30, &value);
  1687 + break;
  1688 + case CIRRUS_MMIO_BLTROP:
  1689 + cirrus_hook_read_gr(s, 0x32, &value);
  1690 + break;
  1691 + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
  1692 + cirrus_hook_read_gr(s, 0x34, &value);
  1693 + break;
  1694 + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
  1695 + cirrus_hook_read_gr(s, 0x35, &value);
  1696 + break;
  1697 + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
  1698 + cirrus_hook_read_gr(s, 0x38, &value);
  1699 + break;
  1700 + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
  1701 + cirrus_hook_read_gr(s, 0x39, &value);
  1702 + break;
  1703 + case CIRRUS_MMIO_BLTSTATUS:
  1704 + cirrus_hook_read_gr(s, 0x31, &value);
  1705 + break;
  1706 + default:
  1707 +#ifdef DEBUG_CIRRUS
  1708 + printf("cirrus: mmio read - address 0x%04x\n", address);
  1709 +#endif
  1710 + break;
  1711 + }
  1712 +
  1713 + return (uint8_t) value;
  1714 +}
  1715 +
  1716 +static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address,
  1717 + uint8_t value)
  1718 +{
  1719 + switch (address) {
  1720 + case (CIRRUS_MMIO_BLTBGCOLOR + 0):
  1721 + cirrus_hook_write_gr(s, 0x00, value);
  1722 + break;
  1723 + case (CIRRUS_MMIO_BLTBGCOLOR + 1):
  1724 + cirrus_hook_write_gr(s, 0x10, value);
  1725 + break;
  1726 + case (CIRRUS_MMIO_BLTBGCOLOR + 2):
  1727 + cirrus_hook_write_gr(s, 0x12, value);
  1728 + break;
  1729 + case (CIRRUS_MMIO_BLTBGCOLOR + 3):
  1730 + cirrus_hook_write_gr(s, 0x14, value);
  1731 + break;
  1732 + case (CIRRUS_MMIO_BLTFGCOLOR + 0):
  1733 + cirrus_hook_write_gr(s, 0x01, value);
  1734 + break;
  1735 + case (CIRRUS_MMIO_BLTFGCOLOR + 1):
  1736 + cirrus_hook_write_gr(s, 0x11, value);
  1737 + break;
  1738 + case (CIRRUS_MMIO_BLTFGCOLOR + 2):
  1739 + cirrus_hook_write_gr(s, 0x13, value);
  1740 + break;
  1741 + case (CIRRUS_MMIO_BLTFGCOLOR + 3):
  1742 + cirrus_hook_write_gr(s, 0x15, value);
  1743 + break;
  1744 + case (CIRRUS_MMIO_BLTWIDTH + 0):
  1745 + cirrus_hook_write_gr(s, 0x20, value);
  1746 + break;
  1747 + case (CIRRUS_MMIO_BLTWIDTH + 1):
  1748 + cirrus_hook_write_gr(s, 0x21, value);
  1749 + break;
  1750 + case (CIRRUS_MMIO_BLTHEIGHT + 0):
  1751 + cirrus_hook_write_gr(s, 0x22, value);
  1752 + break;
  1753 + case (CIRRUS_MMIO_BLTHEIGHT + 1):
  1754 + cirrus_hook_write_gr(s, 0x23, value);
  1755 + break;
  1756 + case (CIRRUS_MMIO_BLTDESTPITCH + 0):
  1757 + cirrus_hook_write_gr(s, 0x24, value);
  1758 + break;
  1759 + case (CIRRUS_MMIO_BLTDESTPITCH + 1):
  1760 + cirrus_hook_write_gr(s, 0x25, value);
  1761 + break;
  1762 + case (CIRRUS_MMIO_BLTSRCPITCH + 0):
  1763 + cirrus_hook_write_gr(s, 0x26, value);
  1764 + break;
  1765 + case (CIRRUS_MMIO_BLTSRCPITCH + 1):
  1766 + cirrus_hook_write_gr(s, 0x27, value);
  1767 + break;
  1768 + case (CIRRUS_MMIO_BLTDESTADDR + 0):
  1769 + cirrus_hook_write_gr(s, 0x28, value);
  1770 + break;
  1771 + case (CIRRUS_MMIO_BLTDESTADDR + 1):
  1772 + cirrus_hook_write_gr(s, 0x29, value);
  1773 + break;
  1774 + case (CIRRUS_MMIO_BLTDESTADDR + 2):
  1775 + cirrus_hook_write_gr(s, 0x2a, value);
  1776 + break;
  1777 + case (CIRRUS_MMIO_BLTDESTADDR + 3):
  1778 + /* ignored */
  1779 + break;
  1780 + case (CIRRUS_MMIO_BLTSRCADDR + 0):
  1781 + cirrus_hook_write_gr(s, 0x2c, value);
  1782 + break;
  1783 + case (CIRRUS_MMIO_BLTSRCADDR + 1):
  1784 + cirrus_hook_write_gr(s, 0x2d, value);
  1785 + break;
  1786 + case (CIRRUS_MMIO_BLTSRCADDR + 2):
  1787 + cirrus_hook_write_gr(s, 0x2e, value);
  1788 + break;
  1789 + case CIRRUS_MMIO_BLTWRITEMASK:
  1790 + cirrus_hook_write_gr(s, 0x2f, value);
  1791 + break;
  1792 + case CIRRUS_MMIO_BLTMODE:
  1793 + cirrus_hook_write_gr(s, 0x30, value);
  1794 + break;
  1795 + case CIRRUS_MMIO_BLTROP:
  1796 + cirrus_hook_write_gr(s, 0x32, value);
  1797 + break;
  1798 + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
  1799 + cirrus_hook_write_gr(s, 0x34, value);
  1800 + break;
  1801 + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
  1802 + cirrus_hook_write_gr(s, 0x35, value);
  1803 + break;
  1804 + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
  1805 + cirrus_hook_write_gr(s, 0x38, value);
  1806 + break;
  1807 + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
  1808 + cirrus_hook_write_gr(s, 0x39, value);
  1809 + break;
  1810 + case CIRRUS_MMIO_BLTSTATUS:
  1811 + cirrus_hook_write_gr(s, 0x31, value);
  1812 + break;
  1813 + default:
  1814 +#ifdef DEBUG_CIRRUS
  1815 + printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n",
  1816 + address, value);
  1817 +#endif
  1818 + break;
  1819 + }
  1820 +}
  1821 +
  1822 +/***************************************
  1823 + *
  1824 + * memory-mapped I/O (vga)
  1825 + *
  1826 + ***************************************/
  1827 +
  1828 +static uint8_t cirrus_mmio_vga_read(CirrusVGAState * s, unsigned address)
  1829 +{
  1830 +#ifdef DEBUG_CIRRUS
  1831 + printf("cirrus: mmio vga read (unimplemented) - address 0x%04x\n",
  1832 + address);
  1833 +#endif
  1834 + return 0xff;
  1835 +}
  1836 +
  1837 +static void cirrus_mmio_vga_write(CirrusVGAState * s, unsigned address,
  1838 + uint8_t value)
  1839 +{
  1840 +#ifdef DEBUG_CIRRUS
  1841 + printf
  1842 + ("cirrus: mmio vga write (unimplemented) - address 0x%04x, value 0x%02x\n",
  1843 + address, value);
  1844 +#endif
  1845 +}
  1846 +
  1847 +/***************************************
  1848 + *
  1849 + * write mode 4/5
  1850 + *
  1851 + * assume TARGET_PAGE_SIZE >= 16
  1852 + *
  1853 + ***************************************/
  1854 +
  1855 +static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
  1856 + unsigned mode,
  1857 + unsigned offset,
  1858 + uint32_t mem_value)
  1859 +{
  1860 + int x;
  1861 + unsigned val = mem_value;
  1862 + uint8_t *dst;
  1863 +
  1864 + dst = s->vram_ptr + offset;
  1865 + for (x = 0; x < 8; x++) {
  1866 + if (val & 0x80) {
  1867 + *dst++ = s->gr[0x01];
  1868 + } else if (mode == 5) {
  1869 + *dst++ = s->gr[0x00];
  1870 + }
  1871 + val <<= 1;
  1872 + }
  1873 + cpu_physical_memory_set_dirty(s->vram_offset + offset);
  1874 + cpu_physical_memory_set_dirty(s->vram_offset + offset + 7);
  1875 +}
  1876 +
  1877 +static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
  1878 + unsigned mode,
  1879 + unsigned offset,
  1880 + uint32_t mem_value)
  1881 +{
  1882 + int x;
  1883 + unsigned val = mem_value;
  1884 + uint8_t *dst;
  1885 +
  1886 + dst = s->vram_ptr + offset;
  1887 + for (x = 0; x < 8; x++) {
  1888 + if (val & 0x80) {
  1889 + *dst++ = s->gr[0x01];
  1890 + *dst++ = s->gr[0x11];
  1891 + } else if (mode == 5) {
  1892 + *dst++ = s->gr[0x00];
  1893 + *dst++ = s->gr[0x10];
  1894 + }
  1895 + val <<= 1;
  1896 + }
  1897 + cpu_physical_memory_set_dirty(s->vram_offset + offset);
  1898 + cpu_physical_memory_set_dirty(s->vram_offset + offset + 15);
  1899 +}
  1900 +
  1901 +/***************************************
  1902 + *
  1903 + * memory access between 0xa0000-0xbffff
  1904 + *
  1905 + ***************************************/
  1906 +
  1907 +static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
  1908 +{
  1909 + CirrusVGAState *s = opaque;
  1910 + unsigned bank_index;
  1911 + unsigned bank_offset;
  1912 + uint32_t val;
  1913 +
  1914 + if ((s->sr[0x07] & 0x01) == 0) {
  1915 + return vga_mem_readb(s, addr);
  1916 + }
  1917 +
  1918 + if (addr < 0x10000) {
  1919 + /* XXX handle bitblt */
  1920 + /* video memory */
  1921 + bank_index = addr >> 15;
  1922 + bank_offset = addr & 0x7fff;
  1923 + if (bank_offset < s->cirrus_bank_limit[bank_index]) {
  1924 + bank_offset += s->cirrus_bank_base[bank_index];
  1925 + if ((s->gr[0x0B] & 0x14) == 0x14) {
  1926 + bank_offset <<= 4;
  1927 + } else if (s->gr[0x0B] & 0x02) {
  1928 + bank_offset <<= 3;
  1929 + }
  1930 + bank_offset &= s->cirrus_addr_mask;
  1931 + val = *(s->vram_ptr + bank_offset);
  1932 + } else
  1933 + val = 0xff;
  1934 + } else if (addr >= 0x18000 && addr < 0x18100) {
  1935 + /* memory-mapped I/O */
  1936 + val = 0xff;
  1937 + if ((s->sr[0x17] & 0x44) == 0x04) {
  1938 + val = cirrus_mmio_blt_read(s, addr & 0xff);
  1939 + }
  1940 + } else {
  1941 + val = 0xff;
  1942 +#ifdef DEBUG_CIRRUS
  1943 + printf("cirrus: mem_readb %06x\n", addr);
  1944 +#endif
  1945 + }
  1946 + return val;
  1947 +}
  1948 +
  1949 +static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
  1950 +{
  1951 + uint32_t v;
  1952 +#ifdef TARGET_WORDS_BIGENDIAN
  1953 + v = cirrus_vga_mem_readb(opaque, addr) << 8;
  1954 + v |= cirrus_vga_mem_readb(opaque, addr + 1);
  1955 +#else
  1956 + v = cirrus_vga_mem_readb(opaque, addr);
  1957 + v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
  1958 +#endif
  1959 + return v;
  1960 +}
  1961 +
  1962 +static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
  1963 +{
  1964 + uint32_t v;
  1965 +#ifdef TARGET_WORDS_BIGENDIAN
  1966 + v = cirrus_vga_mem_readb(opaque, addr) << 24;
  1967 + v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16;
  1968 + v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8;
  1969 + v |= cirrus_vga_mem_readb(opaque, addr + 3);
  1970 +#else
  1971 + v = cirrus_vga_mem_readb(opaque, addr);
  1972 + v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
  1973 + v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
  1974 + v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
  1975 +#endif
  1976 + return v;
  1977 +}
  1978 +
  1979 +static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
  1980 + uint32_t mem_value)
  1981 +{
  1982 + CirrusVGAState *s = opaque;
  1983 + unsigned bank_index;
  1984 + unsigned bank_offset;
  1985 + unsigned mode;
  1986 +
  1987 + if ((s->sr[0x07] & 0x01) == 0) {
  1988 + vga_mem_writeb(s, addr, mem_value);
  1989 + return;
  1990 + }
  1991 +
  1992 + if (addr < 0x10000) {
  1993 + if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
  1994 + /* bitblt */
  1995 + *s->cirrus_srcptr++ = (uint8_t) mem_value;
  1996 + if (s->cirrus_srcptr == s->cirrus_srcptr_end) {
  1997 + cirrus_bitblt_cputovideo_next(s);
  1998 + }
  1999 + } else {
  2000 + /* video memory */
  2001 + bank_index = addr >> 15;
  2002 + bank_offset = addr & 0x7fff;
  2003 + if (bank_offset < s->cirrus_bank_limit[bank_index]) {
  2004 + bank_offset += s->cirrus_bank_base[bank_index];
  2005 + if ((s->gr[0x0B] & 0x14) == 0x14) {
  2006 + bank_offset <<= 4;
  2007 + } else if (s->gr[0x0B] & 0x02) {
  2008 + bank_offset <<= 3;
  2009 + }
  2010 + bank_offset &= s->cirrus_addr_mask;
  2011 + mode = s->gr[0x05] & 0x7;
  2012 + if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
  2013 + *(s->vram_ptr + bank_offset) = mem_value;
  2014 + cpu_physical_memory_set_dirty(s->vram_offset +
  2015 + bank_offset);
  2016 + } else {
  2017 + if ((s->gr[0x0B] & 0x14) != 0x14) {
  2018 + cirrus_mem_writeb_mode4and5_8bpp(s, mode,
  2019 + bank_offset,
  2020 + mem_value);
  2021 + } else {
  2022 + cirrus_mem_writeb_mode4and5_16bpp(s, mode,
  2023 + bank_offset,
  2024 + mem_value);
  2025 + }
  2026 + }
  2027 + }
  2028 + }
  2029 + } else if (addr >= 0x18000 && addr < 0x18100) {
  2030 + /* memory-mapped I/O */
  2031 + if ((s->sr[0x17] & 0x44) == 0x04) {
  2032 + cirrus_mmio_blt_write(s, addr & 0xff, mem_value);
  2033 + }
  2034 + } else {
  2035 +#ifdef DEBUG_CIRRUS
  2036 + printf("cirrus: mem_writeb %06x value %02x\n", addr, mem_value);
  2037 +#endif
  2038 + }
  2039 +}
  2040 +
  2041 +static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
  2042 +{
  2043 +#ifdef TARGET_WORDS_BIGENDIAN
  2044 + cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
  2045 + cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff);
  2046 +#else
  2047 + cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
  2048 + cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  2049 +#endif
  2050 +}
  2051 +
  2052 +static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  2053 +{
  2054 +#ifdef TARGET_WORDS_BIGENDIAN
  2055 + cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
  2056 + cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
  2057 + cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
  2058 + cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff);
  2059 +#else
  2060 + cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
  2061 + cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  2062 + cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
  2063 + cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
  2064 +#endif
  2065 +}
  2066 +
  2067 +static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = {
  2068 + cirrus_vga_mem_readb,
  2069 + cirrus_vga_mem_readw,
  2070 + cirrus_vga_mem_readl,
  2071 +};
  2072 +
  2073 +static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = {
  2074 + cirrus_vga_mem_writeb,
  2075 + cirrus_vga_mem_writew,
  2076 + cirrus_vga_mem_writel,
  2077 +};
  2078 +
  2079 +/***************************************
  2080 + *
  2081 + * LFB memory access
  2082 + *
  2083 + ***************************************/
  2084 +
  2085 +static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
  2086 +{
  2087 + CirrusVGAState *s = (CirrusVGAState *) opaque;
  2088 + uint32_t ret;
  2089 +
  2090 + /* XXX: s->vram_size must be a power of two */
  2091 + addr &= s->cirrus_addr_mask;
  2092 +
  2093 + if (((s->sr[0x17] & 0x44) == 0x44) && ((addr & 0x1fff00) == 0x1fff00)) {
  2094 + /* memory-mapped I/O */
  2095 + ret = cirrus_mmio_blt_read(s, addr & 0xff);
  2096 + } else if (0) {
  2097 + /* XXX handle bitblt */
  2098 + ret = 0xff;
  2099 + } else {
  2100 + /* video memory */
  2101 + if ((s->gr[0x0B] & 0x14) == 0x14) {
  2102 + addr <<= 4;
  2103 + } else if (s->gr[0x0B] & 0x02) {
  2104 + addr <<= 3;
  2105 + }
  2106 + addr &= s->cirrus_addr_mask;
  2107 + ret = *(s->vram_ptr + addr);
  2108 + }
  2109 +
  2110 + return ret;
  2111 +}
  2112 +
  2113 +static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
  2114 +{
  2115 + uint32_t v;
  2116 +#ifdef TARGET_WORDS_BIGENDIAN
  2117 + v = cirrus_linear_readb(opaque, addr) << 8;
  2118 + v |= cirrus_linear_readb(opaque, addr + 1);
  2119 +#else
  2120 + v = cirrus_linear_readb(opaque, addr);
  2121 + v |= cirrus_linear_readb(opaque, addr + 1) << 8;
  2122 +#endif
  2123 + return v;
  2124 +}
  2125 +
  2126 +static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
  2127 +{
  2128 + uint32_t v;
  2129 +#ifdef TARGET_WORDS_BIGENDIAN
  2130 + v = cirrus_linear_readb(opaque, addr) << 24;
  2131 + v |= cirrus_linear_readb(opaque, addr + 1) << 16;
  2132 + v |= cirrus_linear_readb(opaque, addr + 2) << 8;
  2133 + v |= cirrus_linear_readb(opaque, addr + 3);
  2134 +#else
  2135 + v = cirrus_linear_readb(opaque, addr);
  2136 + v |= cirrus_linear_readb(opaque, addr + 1) << 8;
  2137 + v |= cirrus_linear_readb(opaque, addr + 2) << 16;
  2138 + v |= cirrus_linear_readb(opaque, addr + 3) << 24;
  2139 +#endif
  2140 + return v;
  2141 +}
  2142 +
  2143 +static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
  2144 + uint32_t val)
  2145 +{
  2146 + CirrusVGAState *s = (CirrusVGAState *) opaque;
  2147 + unsigned mode;
  2148 +
  2149 + addr &= s->cirrus_addr_mask;
  2150 +
  2151 + if (((s->sr[0x17] & 0x44) == 0x44) && ((addr & 0x1fff00) == 0x1fff00)) {
  2152 + /* memory-mapped I/O */
  2153 + cirrus_mmio_blt_write(s, addr & 0xff, val);
  2154 + } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
  2155 + /* bitblt */
  2156 + *s->cirrus_srcptr++ = (uint8_t) val;
  2157 + if (s->cirrus_srcptr == s->cirrus_srcptr_end) {
  2158 + cirrus_bitblt_cputovideo_next(s);
  2159 + }
  2160 + } else {
  2161 + /* video memory */
  2162 + if ((s->gr[0x0B] & 0x14) == 0x14) {
  2163 + addr <<= 4;
  2164 + } else if (s->gr[0x0B] & 0x02) {
  2165 + addr <<= 3;
  2166 + }
  2167 + addr &= s->cirrus_addr_mask;
  2168 +
  2169 + mode = s->gr[0x05] & 0x7;
  2170 + if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
  2171 + *(s->vram_ptr + addr) = (uint8_t) val;
  2172 + cpu_physical_memory_set_dirty(s->vram_offset + addr);
  2173 + } else {
  2174 + if ((s->gr[0x0B] & 0x14) != 0x14) {
  2175 + cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
  2176 + } else {
  2177 + cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val);
  2178 + }
  2179 + }
  2180 + }
  2181 +}
  2182 +
  2183 +static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
  2184 + uint32_t val)
  2185 +{
  2186 +#ifdef TARGET_WORDS_BIGENDIAN
  2187 + cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff);
  2188 + cirrus_linear_writeb(opaque, addr + 1, val & 0xff);
  2189 +#else
  2190 + cirrus_linear_writeb(opaque, addr, val & 0xff);
  2191 + cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  2192 +#endif
  2193 +}
  2194 +
  2195 +static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
  2196 + uint32_t val)
  2197 +{
  2198 +#ifdef TARGET_WORDS_BIGENDIAN
  2199 + cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff);
  2200 + cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff);
  2201 + cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff);
  2202 + cirrus_linear_writeb(opaque, addr + 3, val & 0xff);
  2203 +#else
  2204 + cirrus_linear_writeb(opaque, addr, val & 0xff);
  2205 + cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  2206 + cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
  2207 + cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
  2208 +#endif
  2209 +}
  2210 +
  2211 +
  2212 +static CPUReadMemoryFunc *cirrus_linear_read[3] = {
  2213 + cirrus_linear_readb,
  2214 + cirrus_linear_readw,
  2215 + cirrus_linear_readl,
  2216 +};
  2217 +
  2218 +static CPUWriteMemoryFunc *cirrus_linear_write[3] = {
  2219 + cirrus_linear_writeb,
  2220 + cirrus_linear_writew,
  2221 + cirrus_linear_writel,
  2222 +};
  2223 +
  2224 +/***************************************
  2225 + *
  2226 + * memory-mapped I/O access
  2227 + *
  2228 + ***************************************/
  2229 +
  2230 +static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
  2231 +{
  2232 + CirrusVGAState *s = (CirrusVGAState *) opaque;
  2233 +
  2234 + addr &= CIRRUS_PNPMMIO_SIZE - 1;
  2235 + /* ??? Does CLGD5430 have memory-mapped VGA registers ??? */
  2236 + return (addr >= 0x100) ?
  2237 + cirrus_mmio_blt_read(s, addr - 0x100) :
  2238 + cirrus_mmio_vga_read(s, addr);
  2239 +}
  2240 +
  2241 +static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
  2242 +{
  2243 + uint32_t v;
  2244 +#ifdef TARGET_WORDS_BIGENDIAN
  2245 + v = cirrus_mmio_readb(opaque, addr) << 8;
  2246 + v |= cirrus_mmio_readb(opaque, addr + 1);
  2247 +#else
  2248 + v = cirrus_mmio_readb(opaque, addr);
  2249 + v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
  2250 +#endif
  2251 + return v;
  2252 +}
  2253 +
  2254 +static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
  2255 +{
  2256 + uint32_t v;
  2257 +#ifdef TARGET_WORDS_BIGENDIAN
  2258 + v = cirrus_mmio_readb(opaque, addr) << 24;
  2259 + v |= cirrus_mmio_readb(opaque, addr + 1) << 16;
  2260 + v |= cirrus_mmio_readb(opaque, addr + 2) << 8;
  2261 + v |= cirrus_mmio_readb(opaque, addr + 3);
  2262 +#else
  2263 + v = cirrus_mmio_readb(opaque, addr);
  2264 + v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
  2265 + v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
  2266 + v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
  2267 +#endif
  2268 + return v;
  2269 +}
  2270 +
  2271 +static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
  2272 + uint32_t val)
  2273 +{
  2274 + CirrusVGAState *s = (CirrusVGAState *) opaque;
  2275 +
  2276 + addr &= CIRRUS_PNPMMIO_SIZE - 1;
  2277 + /* ??? Does CLGD5430 have memory-mapped VGA registers ??? */
  2278 + if (addr >= 0x100) {
  2279 + cirrus_mmio_blt_write(s, addr - 0x100, val);
  2280 + } else {
  2281 + cirrus_mmio_vga_write(s, addr, val);
  2282 + }
  2283 +}
  2284 +
  2285 +static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
  2286 + uint32_t val)
  2287 +{
  2288 +#ifdef TARGET_WORDS_BIGENDIAN
  2289 + cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff);
  2290 + cirrus_mmio_writeb(opaque, addr + 1, val & 0xff);
  2291 +#else
  2292 + cirrus_mmio_writeb(opaque, addr, val & 0xff);
  2293 + cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  2294 +#endif
  2295 +}
  2296 +
  2297 +static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
  2298 + uint32_t val)
  2299 +{
  2300 +#ifdef TARGET_WORDS_BIGENDIAN
  2301 + cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff);
  2302 + cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff);
  2303 + cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff);
  2304 + cirrus_mmio_writeb(opaque, addr + 3, val & 0xff);
  2305 +#else
  2306 + cirrus_mmio_writeb(opaque, addr, val & 0xff);
  2307 + cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  2308 + cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
  2309 + cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
  2310 +#endif
  2311 +}
  2312 +
  2313 +
  2314 +static CPUReadMemoryFunc *cirrus_mmio_read[3] = {
  2315 + cirrus_mmio_readb,
  2316 + cirrus_mmio_readw,
  2317 + cirrus_mmio_readl,
  2318 +};
  2319 +
  2320 +static CPUWriteMemoryFunc *cirrus_mmio_write[3] = {
  2321 + cirrus_mmio_writeb,
  2322 + cirrus_mmio_writew,
  2323 + cirrus_mmio_writel,
  2324 +};
  2325 +
  2326 +/* I/O ports */
  2327 +
  2328 +static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
  2329 +{
  2330 + CirrusVGAState *s = opaque;
  2331 + int val, index;
  2332 +
  2333 + /* check port range access depending on color/monochrome mode */
  2334 + if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
  2335 + || (addr >= 0x3d0 && addr <= 0x3df
  2336 + && !(s->msr & MSR_COLOR_EMULATION))) {
  2337 + val = 0xff;
  2338 + } else {
  2339 + switch (addr) {
  2340 + case 0x3c0:
  2341 + if (s->ar_flip_flop == 0) {
  2342 + val = s->ar_index;
  2343 + } else {
  2344 + val = 0;
  2345 + }
  2346 + break;
  2347 + case 0x3c1:
  2348 + index = s->ar_index & 0x1f;
  2349 + if (index < 21)
  2350 + val = s->ar[index];
  2351 + else
  2352 + val = 0;
  2353 + break;
  2354 + case 0x3c2:
  2355 + val = s->st00;
  2356 + break;
  2357 + case 0x3c4:
  2358 + val = s->sr_index;
  2359 + break;
  2360 + case 0x3c5:
  2361 + if (cirrus_hook_read_sr(s, s->sr_index, &val))
  2362 + break;
  2363 + val = s->sr[s->sr_index];
  2364 +#ifdef DEBUG_VGA_REG
  2365 + printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
  2366 +#endif
  2367 + break;
  2368 + case 0x3c6:
  2369 + cirrus_read_hidden_dac(s, &val);
  2370 + break;
  2371 + case 0x3c7:
  2372 + val = s->dac_state;
  2373 + break;
  2374 + case 0x3c9:
  2375 + if (cirrus_hook_read_palette(s, &val))
  2376 + break;
  2377 + val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
  2378 + if (++s->dac_sub_index == 3) {
  2379 + s->dac_sub_index = 0;
  2380 + s->dac_read_index++;
  2381 + }
  2382 + break;
  2383 + case 0x3ca:
  2384 + val = s->fcr;
  2385 + break;
  2386 + case 0x3cc:
  2387 + val = s->msr;
  2388 + break;
  2389 + case 0x3ce:
  2390 + val = s->gr_index;
  2391 + break;
  2392 + case 0x3cf:
  2393 + if (cirrus_hook_read_gr(s, s->gr_index, &val))
  2394 + break;
  2395 + val = s->gr[s->gr_index];
  2396 +#ifdef DEBUG_VGA_REG
  2397 + printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
  2398 +#endif
  2399 + break;
  2400 + case 0x3b4:
  2401 + case 0x3d4:
  2402 + val = s->cr_index;
  2403 + break;
  2404 + case 0x3b5:
  2405 + case 0x3d5:
  2406 + if (cirrus_hook_read_cr(s, s->cr_index, &val))
  2407 + break;
  2408 + val = s->cr[s->cr_index];
  2409 +#ifdef DEBUG_VGA_REG
  2410 + printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
  2411 +#endif
  2412 +#ifdef DEBUG_S3
  2413 + if (s->cr_index >= 0x20)
  2414 + printf("S3: CR read index=0x%x val=0x%x\n",
  2415 + s->cr_index, val);
  2416 +#endif
  2417 + break;
  2418 + case 0x3ba:
  2419 + case 0x3da:
  2420 + /* just toggle to fool polling */
  2421 + s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
  2422 + val = s->st01;
  2423 + s->ar_flip_flop = 0;
  2424 + break;
  2425 + default:
  2426 + val = 0x00;
  2427 + break;
  2428 + }
  2429 + }
  2430 +#if defined(DEBUG_VGA)
  2431 + printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
  2432 +#endif
  2433 + return val;
  2434 +}
  2435 +
  2436 +static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
  2437 +{
  2438 + CirrusVGAState *s = opaque;
  2439 + int index;
  2440 +
  2441 + /* check port range access depending on color/monochrome mode */
  2442 + if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
  2443 + || (addr >= 0x3d0 && addr <= 0x3df
  2444 + && !(s->msr & MSR_COLOR_EMULATION)))
  2445 + return;
  2446 +
  2447 +#ifdef DEBUG_VGA
  2448 + printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
  2449 +#endif
  2450 +
  2451 + switch (addr) {
  2452 + case 0x3c0:
  2453 + if (s->ar_flip_flop == 0) {
  2454 + val &= 0x3f;
  2455 + s->ar_index = val;
  2456 + } else {
  2457 + index = s->ar_index & 0x1f;
  2458 + switch (index) {
  2459 + case 0x00 ... 0x0f:
  2460 + s->ar[index] = val & 0x3f;
  2461 + break;
  2462 + case 0x10:
  2463 + s->ar[index] = val & ~0x10;
  2464 + break;
  2465 + case 0x11:
  2466 + s->ar[index] = val;
  2467 + break;
  2468 + case 0x12:
  2469 + s->ar[index] = val & ~0xc0;
  2470 + break;
  2471 + case 0x13:
  2472 + s->ar[index] = val & ~0xf0;
  2473 + break;
  2474 + case 0x14:
  2475 + s->ar[index] = val & ~0xf0;
  2476 + break;
  2477 + default:
  2478 + break;
  2479 + }
  2480 + }
  2481 + s->ar_flip_flop ^= 1;
  2482 + break;
  2483 + case 0x3c2:
  2484 + s->msr = val & ~0x10;
  2485 + break;
  2486 + case 0x3c4:
  2487 + s->sr_index = val;
  2488 + break;
  2489 + case 0x3c5:
  2490 + if (cirrus_hook_write_sr(s, s->sr_index, val))
  2491 + break;
  2492 +#ifdef DEBUG_VGA_REG
  2493 + printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
  2494 +#endif
  2495 + s->sr[s->sr_index] = val & sr_mask[s->sr_index];
  2496 + break;
  2497 + case 0x3c6:
  2498 + cirrus_write_hidden_dac(s, val);
  2499 + break;
  2500 + case 0x3c7:
  2501 + s->dac_read_index = val;
  2502 + s->dac_sub_index = 0;
  2503 + s->dac_state = 3;
  2504 + break;
  2505 + case 0x3c8:
  2506 + s->dac_write_index = val;
  2507 + s->dac_sub_index = 0;
  2508 + s->dac_state = 0;
  2509 + break;
  2510 + case 0x3c9:
  2511 + if (cirrus_hook_write_palette(s, val))
  2512 + break;
  2513 + s->dac_cache[s->dac_sub_index] = val;
  2514 + if (++s->dac_sub_index == 3) {
  2515 + memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
  2516 + s->dac_sub_index = 0;
  2517 + s->dac_write_index++;
  2518 + }
  2519 + break;
  2520 + case 0x3ce:
  2521 + s->gr_index = val;
  2522 + break;
  2523 + case 0x3cf:
  2524 + if (cirrus_hook_write_gr(s, s->gr_index, val))
  2525 + break;
  2526 +#ifdef DEBUG_VGA_REG
  2527 + printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
  2528 +#endif
  2529 + s->gr[s->gr_index] = val & gr_mask[s->gr_index];
  2530 + break;
  2531 + case 0x3b4:
  2532 + case 0x3d4:
  2533 + s->cr_index = val;
  2534 + break;
  2535 + case 0x3b5:
  2536 + case 0x3d5:
  2537 + if (cirrus_hook_write_cr(s, s->cr_index, val))
  2538 + break;
  2539 +#ifdef DEBUG_VGA_REG
  2540 + printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
  2541 +#endif
  2542 + /* handle CR0-7 protection */
  2543 + if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
  2544 + /* can always write bit 4 of CR7 */
  2545 + if (s->cr_index == 7)
  2546 + s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
  2547 + return;
  2548 + }
  2549 + switch (s->cr_index) {
  2550 + case 0x01: /* horizontal display end */
  2551 + case 0x07:
  2552 + case 0x09:
  2553 + case 0x0c:
  2554 + case 0x0d:
  2555 + case 0x12: /* veritcal display end */
  2556 + s->cr[s->cr_index] = val;
  2557 + break;
  2558 +
  2559 + default:
  2560 + s->cr[s->cr_index] = val;
  2561 + break;
  2562 + }
  2563 + break;
  2564 + case 0x3ba:
  2565 + case 0x3da:
  2566 + s->fcr = val & 0x10;
  2567 + break;
  2568 + }
  2569 +}
  2570 +
  2571 +/***************************************
  2572 + *
  2573 + * initialize
  2574 + *
  2575 + ***************************************/
  2576 +
  2577 +static void cirrus_init_common(CirrusVGAState * s)
  2578 +{
  2579 + int vga_io_memory;
  2580 +
  2581 + register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
  2582 +
  2583 + register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
  2584 + register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
  2585 + register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
  2586 + register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
  2587 +
  2588 + register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
  2589 +
  2590 + register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
  2591 + register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
  2592 + register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
  2593 + register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
  2594 +
  2595 + vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read,
  2596 + cirrus_vga_mem_write, s);
  2597 + cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
  2598 + vga_io_memory);
  2599 +
  2600 + s->sr[0x06] = 0x0f;
  2601 + s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
  2602 + s->sr[0x1F] = 0x22; // MemClock
  2603 +
  2604 + s->cr[0x27] = CIRRUS_ID_CLGD5430;
  2605 +
  2606 + s->cirrus_hidden_dac_lockindex = 5;
  2607 + s->cirrus_hidden_dac_data = 0;
  2608 +
  2609 + /* I/O handler for LFB */
  2610 + s->cirrus_linear_io_addr =
  2611 + cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write,
  2612 + s);
  2613 + /* I/O handler for memory-mapped I/O */
  2614 + s->cirrus_mmio_io_addr =
  2615 + cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s);
  2616 +
  2617 + /* XXX: s->vram_size must be a power of two */
  2618 + s->cirrus_addr_mask = s->vram_size - 1;
  2619 +
  2620 + s->get_bpp = cirrus_get_bpp;
  2621 + s->get_offsets = cirrus_get_offsets;
  2622 +}
  2623 +
  2624 +/***************************************
  2625 + *
  2626 + * ISA bus support
  2627 + *
  2628 + ***************************************/
  2629 +
  2630 +void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
  2631 + unsigned long vga_ram_offset, int vga_ram_size)
  2632 +{
  2633 + CirrusVGAState *s;
  2634 +
  2635 + s = qemu_mallocz(sizeof(CirrusVGAState));
  2636 +
  2637 + vga_common_init((VGAState *)s,
  2638 + ds, vga_ram_base, vga_ram_offset, vga_ram_size);
  2639 + cirrus_init_common(s);
  2640 + s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
  2641 + /* XXX ISA-LFB support */
  2642 +}
  2643 +
  2644 +/***************************************
  2645 + *
  2646 + * PCI bus support
  2647 + *
  2648 + ***************************************/
  2649 +
  2650 +static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
  2651 + uint32_t addr, uint32_t size, int type)
  2652 +{
  2653 + CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
  2654 +
  2655 + cpu_register_physical_memory(addr, s->vram_size,
  2656 + s->cirrus_linear_io_addr);
  2657 +}
  2658 +
  2659 +static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
  2660 + uint32_t addr, uint32_t size, int type)
  2661 +{
  2662 + CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
  2663 +
  2664 + cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
  2665 + s->cirrus_mmio_io_addr);
  2666 +}
  2667 +
  2668 +void pci_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
  2669 + unsigned long vga_ram_offset, int vga_ram_size)
  2670 +{
  2671 + PCICirrusVGAState *d;
  2672 + uint8_t *pci_conf;
  2673 + CirrusVGAState *s;
  2674 +
  2675 + /* setup PCI configuration registers */
  2676 + d = (PCICirrusVGAState *)pci_register_device("Cirrus VGA",
  2677 + sizeof(PCICirrusVGAState),
  2678 + 0, -1, NULL, NULL);
  2679 + pci_conf = d->dev.config;
  2680 + pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
  2681 + pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8);
  2682 + pci_conf[0x02] = (uint8_t) (PCI_DEVICE_CLGD5430 & 0xff);
  2683 + pci_conf[0x03] = (uint8_t) (PCI_DEVICE_CLGD5430 >> 8);
  2684 + pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
  2685 + pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
  2686 + pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
  2687 + pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
  2688 +
  2689 + /* setup VGA */
  2690 + s = &d->cirrus_vga;
  2691 + vga_common_init((VGAState *)s,
  2692 + ds, vga_ram_base, vga_ram_offset, vga_ram_size);
  2693 + cirrus_init_common(s);
  2694 + s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
  2695 +
  2696 + /* setup memory space */
  2697 + /* memory #0 LFB */
  2698 + /* memory #1 memory-mapped I/O */
  2699 + /* XXX: s->vram_size must be a power of two */
  2700 + pci_register_io_region((PCIDevice *)d, 0, s->vram_size,
  2701 + PCI_ADDRESS_SPACE_MEM, cirrus_pci_lfb_map);
  2702 + pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
  2703 + PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
  2704 + /* XXX: ROM BIOS */
  2705 +}
... ...