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