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