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