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