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