6305c94936e85435a7b34f359c873ec4127ec353
[qemu] / hw / cirrus_vga.c
1 /*
2  * QEMU Cirrus CLGD 54xx VGA Emulator.
3  * 
4  * Copyright (c) 2004 Fabrice Bellard
5  * Copyright (c) 2004 Makoto Suzuki (suzu)
6  * 
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 /*
26  * Reference: Finn Thogersons' VGADOC4b
27  *   available at http://home.worldonline.dk/~finth/
28  */
29 #include "vl.h"
30 #include "vga_int.h"
31
32 //#define DEBUG_CIRRUS
33 //#define DEBUG_BITBLT
34
35 /***************************************
36  *
37  *  definitions
38  *
39  ***************************************/
40
41 #define qemu_MIN(a,b) ((a) < (b) ? (a) : (b))
42
43 // ID
44 #define CIRRUS_ID_CLGD5422  (0x23<<2)
45 #define CIRRUS_ID_CLGD5426  (0x24<<2)
46 #define CIRRUS_ID_CLGD5424  (0x25<<2)
47 #define CIRRUS_ID_CLGD5428  (0x26<<2)
48 #define CIRRUS_ID_CLGD5430  (0x28<<2)
49 #define CIRRUS_ID_CLGD5434  (0x2A<<2)
50 #define CIRRUS_ID_CLGD5436  (0x2B<<2)
51 #define CIRRUS_ID_CLGD5446  (0x2E<<2)
52
53 /* this define is used to select the exact CLGD implementation we
54    emulate. */
55 //#define CIRRUS_ID CIRRUS_ID_CLGD5430
56 #define CIRRUS_ID CIRRUS_ID_CLGD5446
57
58 // sequencer 0x07
59 #define CIRRUS_SR7_BPP_VGA            0x00
60 #define CIRRUS_SR7_BPP_SVGA           0x01
61 #define CIRRUS_SR7_BPP_MASK           0x0e
62 #define CIRRUS_SR7_BPP_8              0x00
63 #define CIRRUS_SR7_BPP_16_DOUBLEVCLK  0x02
64 #define CIRRUS_SR7_BPP_24             0x04
65 #define CIRRUS_SR7_BPP_16             0x06
66 #define CIRRUS_SR7_BPP_32             0x08
67 #define CIRRUS_SR7_ISAADDR_MASK       0xe0
68
69 // sequencer 0x0f
70 #define CIRRUS_MEMSIZE_512k        0x08
71 #define CIRRUS_MEMSIZE_1M          0x10
72 #define CIRRUS_MEMSIZE_2M          0x18
73 #define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled.
74
75 // sequencer 0x12
76 #define CIRRUS_CURSOR_SHOW         0x01
77 #define CIRRUS_CURSOR_HIDDENPEL    0x02
78 #define CIRRUS_CURSOR_LARGE        0x04 // 64x64 if set, 32x32 if clear
79
80 // sequencer 0x17
81 #define CIRRUS_BUSTYPE_VLBFAST   0x10
82 #define CIRRUS_BUSTYPE_PCI       0x20
83 #define CIRRUS_BUSTYPE_VLBSLOW   0x30
84 #define CIRRUS_BUSTYPE_ISA       0x38
85 #define CIRRUS_MMIO_ENABLE       0x04
86 #define CIRRUS_MMIO_USE_PCIADDR  0x40   // 0xb8000 if cleared.
87 #define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
88
89 // control 0x0b
90 #define CIRRUS_BANKING_DUAL             0x01
91 #define CIRRUS_BANKING_GRANULARITY_16K  0x20    // set:16k, clear:4k
92
93 // control 0x30
94 #define CIRRUS_BLTMODE_BACKWARDS        0x01
95 #define CIRRUS_BLTMODE_MEMSYSDEST       0x02
96 #define CIRRUS_BLTMODE_MEMSYSSRC        0x04
97 #define CIRRUS_BLTMODE_TRANSPARENTCOMP  0x08
98 #define CIRRUS_BLTMODE_PATTERNCOPY      0x40
99 #define CIRRUS_BLTMODE_COLOREXPAND      0x80
100 #define CIRRUS_BLTMODE_PIXELWIDTHMASK   0x30
101 #define CIRRUS_BLTMODE_PIXELWIDTH8      0x00
102 #define CIRRUS_BLTMODE_PIXELWIDTH16     0x10
103 #define CIRRUS_BLTMODE_PIXELWIDTH24     0x20
104 #define CIRRUS_BLTMODE_PIXELWIDTH32     0x30
105
106 // control 0x31
107 #define CIRRUS_BLT_BUSY                 0x01
108 #define CIRRUS_BLT_START                0x02
109 #define CIRRUS_BLT_RESET                0x04
110 #define CIRRUS_BLT_FIFOUSED             0x10
111
112 // control 0x32
113 #define CIRRUS_ROP_0                    0x00
114 #define CIRRUS_ROP_SRC_AND_DST          0x05
115 #define CIRRUS_ROP_NOP                  0x06
116 #define CIRRUS_ROP_SRC_AND_NOTDST       0x09
117 #define CIRRUS_ROP_NOTDST               0x0b
118 #define CIRRUS_ROP_SRC                  0x0d
119 #define CIRRUS_ROP_1                    0x0e
120 #define CIRRUS_ROP_NOTSRC_AND_DST       0x50
121 #define CIRRUS_ROP_SRC_XOR_DST          0x59
122 #define CIRRUS_ROP_SRC_OR_DST           0x6d
123 #define CIRRUS_ROP_NOTSRC_OR_NOTDST     0x90
124 #define CIRRUS_ROP_SRC_NOTXOR_DST       0x95
125 #define CIRRUS_ROP_SRC_OR_NOTDST        0xad
126 #define CIRRUS_ROP_NOTSRC               0xd0
127 #define CIRRUS_ROP_NOTSRC_OR_DST        0xd6
128 #define CIRRUS_ROP_NOTSRC_AND_NOTDST    0xda
129
130 // control 0x33
131 #define CIRRUS_BLTMODEEXT_SOLIDFILL     0x04
132
133 // memory-mapped IO
134 #define CIRRUS_MMIO_BLTBGCOLOR        0x00      // dword
135 #define CIRRUS_MMIO_BLTFGCOLOR        0x04      // dword
136 #define CIRRUS_MMIO_BLTWIDTH          0x08      // word
137 #define CIRRUS_MMIO_BLTHEIGHT         0x0a      // word
138 #define CIRRUS_MMIO_BLTDESTPITCH      0x0c      // word
139 #define CIRRUS_MMIO_BLTSRCPITCH       0x0e      // word
140 #define CIRRUS_MMIO_BLTDESTADDR       0x10      // dword
141 #define CIRRUS_MMIO_BLTSRCADDR        0x14      // dword
142 #define CIRRUS_MMIO_BLTWRITEMASK      0x17      // byte
143 #define CIRRUS_MMIO_BLTMODE           0x18      // byte
144 #define CIRRUS_MMIO_BLTROP            0x1a      // byte
145 #define CIRRUS_MMIO_BLTMODEEXT        0x1b      // byte
146 #define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c    // word?
147 #define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20        // word?
148 #define CIRRUS_MMIO_LINEARDRAW_START_X 0x24     // word
149 #define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26     // word
150 #define CIRRUS_MMIO_LINEARDRAW_END_X  0x28      // word
151 #define CIRRUS_MMIO_LINEARDRAW_END_Y  0x2a      // word
152 #define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c       // byte
153 #define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d  // byte
154 #define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e      // byte
155 #define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f     // byte
156 #define CIRRUS_MMIO_BRESENHAM_K1      0x30      // word
157 #define CIRRUS_MMIO_BRESENHAM_K3      0x32      // word
158 #define CIRRUS_MMIO_BRESENHAM_ERROR   0x34      // word
159 #define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36  // word
160 #define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38    // byte
161 #define CIRRUS_MMIO_LINEDRAW_MODE     0x39      // byte
162 #define CIRRUS_MMIO_BLTSTATUS         0x40      // byte
163
164 // PCI 0x00: vendor, 0x02: device
165 #define PCI_VENDOR_CIRRUS             0x1013
166 #define PCI_DEVICE_ID                 CIRRUS_ID
167 #define PCI_DEVICE_CLGD5462           0x00d0
168 #define PCI_DEVICE_CLGD5465           0x00d6
169
170 // PCI 0x04: command(word), 0x06(word): status
171 #define PCI_COMMAND_IOACCESS                0x0001
172 #define PCI_COMMAND_MEMACCESS               0x0002
173 #define PCI_COMMAND_BUSMASTER               0x0004
174 #define PCI_COMMAND_SPECIALCYCLE            0x0008
175 #define PCI_COMMAND_MEMWRITEINVALID         0x0010
176 #define PCI_COMMAND_PALETTESNOOPING         0x0020
177 #define PCI_COMMAND_PARITYDETECTION         0x0040
178 #define PCI_COMMAND_ADDRESSDATASTEPPING     0x0080
179 #define PCI_COMMAND_SERR                    0x0100
180 #define PCI_COMMAND_BACKTOBACKTRANS         0x0200
181 // PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
182 #define PCI_CLASS_BASE_DISPLAY        0x03
183 // PCI 0x08, 0x00ff0000
184 #define PCI_CLASS_SUB_VGA             0x00
185 // PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test)
186 #define PCI_CLASS_HEADERTYPE_00h  0x00
187 // 0x10-0x3f (headertype 00h)
188 // PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers
189 //   0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x)
190 #define PCI_MAP_MEM                 0x0
191 #define PCI_MAP_IO                  0x1
192 #define PCI_MAP_MEM_ADDR_MASK       (~0xf)
193 #define PCI_MAP_IO_ADDR_MASK        (~0x3)
194 #define PCI_MAP_MEMFLAGS_32BIT      0x0
195 #define PCI_MAP_MEMFLAGS_32BIT_1M   0x1
196 #define PCI_MAP_MEMFLAGS_64BIT      0x4
197 #define PCI_MAP_MEMFLAGS_CACHEABLE  0x8
198 // PCI 0x28: cardbus CIS pointer
199 // PCI 0x2c: subsystem vendor id, 0x2e: subsystem id
200 // PCI 0x30: expansion ROM base address
201 #define PCI_ROMBIOS_ENABLED         0x1
202 // PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer
203 // PCI 0x38: reserved
204 // PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat
205
206 #define CIRRUS_PNPMMIO_SIZE         0x1000
207
208
209 /* I/O and memory hook */
210 #define CIRRUS_HOOK_NOT_HANDLED 0
211 #define CIRRUS_HOOK_HANDLED 1
212
213 typedef void (*cirrus_bitblt_rop_t) (uint8_t * dst, const uint8_t * src,
214                                      int dstpitch, int srcpitch,
215                                      int bltwidth, int bltheight);
216
217 typedef void (*cirrus_bitblt_handler_t) (void *opaque);
218
219 typedef struct CirrusVGAState {
220     VGA_STATE_COMMON
221
222     int cirrus_linear_io_addr;
223     int cirrus_mmio_io_addr;
224     uint32_t cirrus_addr_mask;
225     uint8_t cirrus_shadow_gr0;
226     uint8_t cirrus_shadow_gr1;
227     uint8_t cirrus_hidden_dac_lockindex;
228     uint8_t cirrus_hidden_dac_data;
229     uint32_t cirrus_bank_base[2];
230     uint32_t cirrus_bank_limit[2];
231     uint8_t cirrus_hidden_palette[48];
232     uint32_t cirrus_hw_cursor_x;
233     uint32_t cirrus_hw_cursor_y;
234     int cirrus_blt_pixelwidth;
235     int cirrus_blt_width;
236     int cirrus_blt_height;
237     int cirrus_blt_dstpitch;
238     int cirrus_blt_srcpitch;
239     uint32_t cirrus_blt_dstaddr;
240     uint32_t cirrus_blt_srcaddr;
241     uint8_t cirrus_blt_mode;
242     cirrus_bitblt_rop_t cirrus_rop;
243 #define CIRRUS_BLTBUFSIZE 256
244     uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE];
245     uint8_t *cirrus_srcptr;
246     uint8_t *cirrus_srcptr_end;
247     uint32_t cirrus_srccounter;
248     uint8_t *cirrus_dstptr;
249     uint8_t *cirrus_dstptr_end;
250     uint32_t cirrus_dstcounter;
251     cirrus_bitblt_handler_t cirrus_blt_handler;
252     int cirrus_blt_horz_counter;
253 } CirrusVGAState;
254
255 typedef struct PCICirrusVGAState {
256     PCIDevice dev;
257     CirrusVGAState cirrus_vga;
258 } PCICirrusVGAState;
259
260 /***************************************
261  *
262  *  prototypes.
263  *
264  ***************************************/
265
266
267 static void cirrus_bitblt_reset(CirrusVGAState * s);
268
269 /***************************************
270  *
271  *  raster operations
272  *
273  ***************************************/
274
275 #define IMPLEMENT_BITBLT(name,opline) \
276   static void \
277   cirrus_bitblt_rop_fwd_##name( \
278     uint8_t *dst,const uint8_t *src, \
279     int dstpitch,int srcpitch, \
280     int bltwidth,int bltheight) \
281   { \
282     int x,y; \
283     dstpitch -= bltwidth; \
284     srcpitch -= bltwidth; \
285     for (y = 0; y < bltheight; y++) { \
286       for (x = 0; x < bltwidth; x++) { \
287         opline; \
288         dst++; \
289         src++; \
290         } \
291       dst += dstpitch; \
292       src += srcpitch; \
293       } \
294     } \
295  \
296   static void \
297   cirrus_bitblt_rop_bkwd_##name( \
298     uint8_t *dst,const uint8_t *src, \
299     int dstpitch,int srcpitch, \
300     int bltwidth,int bltheight) \
301   { \
302     int x,y; \
303     dstpitch += bltwidth; \
304     srcpitch += bltwidth; \
305     for (y = 0; y < bltheight; y++) { \
306       for (x = 0; x < bltwidth; x++) { \
307         opline; \
308         dst--; \
309         src--; \
310       } \
311       dst += dstpitch; \
312       src += srcpitch; \
313     } \
314   }
315
316 IMPLEMENT_BITBLT(0, *dst = 0)
317 IMPLEMENT_BITBLT(src_and_dst, *dst = (*src) & (*dst))
318 IMPLEMENT_BITBLT(nop, (void) 0)
319 IMPLEMENT_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
320 IMPLEMENT_BITBLT(notdst, *dst = ~(*dst))
321 IMPLEMENT_BITBLT(src, *dst = *src)
322 IMPLEMENT_BITBLT(1, *dst = 0xff)
323 IMPLEMENT_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
324 IMPLEMENT_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
325 IMPLEMENT_BITBLT(src_or_dst, *dst = (*src) | (*dst))
326 IMPLEMENT_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
327 IMPLEMENT_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
328 IMPLEMENT_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
329 IMPLEMENT_BITBLT(notsrc, *dst = (~(*src)))
330 IMPLEMENT_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
331 IMPLEMENT_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
332
333 static cirrus_bitblt_rop_t cirrus_get_fwd_rop_handler(uint8_t rop)
334 {
335     cirrus_bitblt_rop_t rop_handler = cirrus_bitblt_rop_fwd_nop;
336
337     switch (rop) {
338     case CIRRUS_ROP_0:
339         rop_handler = cirrus_bitblt_rop_fwd_0;
340         break;
341     case CIRRUS_ROP_SRC_AND_DST:
342         rop_handler = cirrus_bitblt_rop_fwd_src_and_dst;
343         break;
344     case CIRRUS_ROP_NOP:
345         rop_handler = cirrus_bitblt_rop_fwd_nop;
346         break;
347     case CIRRUS_ROP_SRC_AND_NOTDST:
348         rop_handler = cirrus_bitblt_rop_fwd_src_and_notdst;
349         break;
350     case CIRRUS_ROP_NOTDST:
351         rop_handler = cirrus_bitblt_rop_fwd_notdst;
352         break;
353     case CIRRUS_ROP_SRC:
354         rop_handler = cirrus_bitblt_rop_fwd_src;
355         break;
356     case CIRRUS_ROP_1:
357         rop_handler = cirrus_bitblt_rop_fwd_1;
358         break;
359     case CIRRUS_ROP_NOTSRC_AND_DST:
360         rop_handler = cirrus_bitblt_rop_fwd_notsrc_and_dst;
361         break;
362     case CIRRUS_ROP_SRC_XOR_DST:
363         rop_handler = cirrus_bitblt_rop_fwd_src_xor_dst;
364         break;
365     case CIRRUS_ROP_SRC_OR_DST:
366         rop_handler = cirrus_bitblt_rop_fwd_src_or_dst;
367         break;
368     case CIRRUS_ROP_NOTSRC_OR_NOTDST:
369         rop_handler = cirrus_bitblt_rop_fwd_notsrc_or_notdst;
370         break;
371     case CIRRUS_ROP_SRC_NOTXOR_DST:
372         rop_handler = cirrus_bitblt_rop_fwd_src_notxor_dst;
373         break;
374     case CIRRUS_ROP_SRC_OR_NOTDST:
375         rop_handler = cirrus_bitblt_rop_fwd_src_or_notdst;
376         break;
377     case CIRRUS_ROP_NOTSRC:
378         rop_handler = cirrus_bitblt_rop_fwd_notsrc;
379         break;
380     case CIRRUS_ROP_NOTSRC_OR_DST:
381         rop_handler = cirrus_bitblt_rop_fwd_notsrc_or_dst;
382         break;
383     case CIRRUS_ROP_NOTSRC_AND_NOTDST:
384         rop_handler = cirrus_bitblt_rop_fwd_notsrc_and_notdst;
385         break;
386     default:
387 #ifdef DEBUG_CIRRUS
388         printf("unknown ROP %02x\n", rop);
389 #endif
390         break;
391     }
392
393     return rop_handler;
394 }
395
396 static cirrus_bitblt_rop_t cirrus_get_bkwd_rop_handler(uint8_t rop)
397 {
398     cirrus_bitblt_rop_t rop_handler = cirrus_bitblt_rop_bkwd_nop;
399
400     switch (rop) {
401     case CIRRUS_ROP_0:
402         rop_handler = cirrus_bitblt_rop_bkwd_0;
403         break;
404     case CIRRUS_ROP_SRC_AND_DST:
405         rop_handler = cirrus_bitblt_rop_bkwd_src_and_dst;
406         break;
407     case CIRRUS_ROP_NOP:
408         rop_handler = cirrus_bitblt_rop_bkwd_nop;
409         break;
410     case CIRRUS_ROP_SRC_AND_NOTDST:
411         rop_handler = cirrus_bitblt_rop_bkwd_src_and_notdst;
412         break;
413     case CIRRUS_ROP_NOTDST:
414         rop_handler = cirrus_bitblt_rop_bkwd_notdst;
415         break;
416     case CIRRUS_ROP_SRC:
417         rop_handler = cirrus_bitblt_rop_bkwd_src;
418         break;
419     case CIRRUS_ROP_1:
420         rop_handler = cirrus_bitblt_rop_bkwd_1;
421         break;
422     case CIRRUS_ROP_NOTSRC_AND_DST:
423         rop_handler = cirrus_bitblt_rop_bkwd_notsrc_and_dst;
424         break;
425     case CIRRUS_ROP_SRC_XOR_DST:
426         rop_handler = cirrus_bitblt_rop_bkwd_src_xor_dst;
427         break;
428     case CIRRUS_ROP_SRC_OR_DST:
429         rop_handler = cirrus_bitblt_rop_bkwd_src_or_dst;
430         break;
431     case CIRRUS_ROP_NOTSRC_OR_NOTDST:
432         rop_handler = cirrus_bitblt_rop_bkwd_notsrc_or_notdst;
433         break;
434     case CIRRUS_ROP_SRC_NOTXOR_DST:
435         rop_handler = cirrus_bitblt_rop_bkwd_src_notxor_dst;
436         break;
437     case CIRRUS_ROP_SRC_OR_NOTDST:
438         rop_handler = cirrus_bitblt_rop_bkwd_src_or_notdst;
439         break;
440     case CIRRUS_ROP_NOTSRC:
441         rop_handler = cirrus_bitblt_rop_bkwd_notsrc;
442         break;
443     case CIRRUS_ROP_NOTSRC_OR_DST:
444         rop_handler = cirrus_bitblt_rop_bkwd_notsrc_or_dst;
445         break;
446     case CIRRUS_ROP_NOTSRC_AND_NOTDST:
447         rop_handler = cirrus_bitblt_rop_bkwd_notsrc_and_notdst;
448         break;
449     default:
450 #ifdef DEBUG_CIRRUS
451         printf("unknown ROP %02x\n", rop);
452 #endif
453         break;
454     }
455
456     return rop_handler;
457 }
458
459 /***************************************
460  *
461  *  color expansion
462  *
463  ***************************************/
464
465 static void
466 cirrus_colorexpand_8(CirrusVGAState * s, uint8_t * dst,
467                      const uint8_t * src, int count)
468 {
469     int x;
470     uint8_t colors[2];
471     unsigned bits;
472     unsigned bitmask;
473     int srcskipleft = 0;
474
475     colors[0] = s->cirrus_shadow_gr0;
476     colors[1] = s->cirrus_shadow_gr1;
477
478     bitmask = 0x80 >> srcskipleft;
479     bits = *src++;
480     for (x = 0; x < count; x++) {
481         if ((bitmask & 0xff) == 0) {
482             bitmask = 0x80;
483             bits = *src++;
484         }
485         *dst++ = colors[!!(bits & bitmask)];
486         bitmask >>= 1;
487     }
488 }
489
490 static void
491 cirrus_colorexpand_16(CirrusVGAState * s, uint8_t * dst,
492                       const uint8_t * src, int count)
493 {
494     int x;
495     uint8_t colors[2][2];
496     unsigned bits;
497     unsigned bitmask;
498     unsigned index;
499     int srcskipleft = 0;
500
501     colors[0][0] = s->cirrus_shadow_gr0;
502     colors[0][1] = s->gr[0x10];
503     colors[1][0] = s->cirrus_shadow_gr1;
504     colors[1][1] = s->gr[0x11];
505
506     bitmask = 0x80 >> srcskipleft;
507     bits = *src++;
508     for (x = 0; x < count; x++) {
509         if ((bitmask & 0xff) == 0) {
510             bitmask = 0x80;
511             bits = *src++;
512         }
513         index = !!(bits & bitmask);
514         *dst++ = colors[index][0];
515         *dst++ = colors[index][1];
516         bitmask >>= 1;
517     }
518 }
519
520 static void
521 cirrus_colorexpand_24(CirrusVGAState * s, uint8_t * dst,
522                       const uint8_t * src, int count)
523 {
524     int x;
525     uint8_t colors[2][3];
526     unsigned bits;
527     unsigned bitmask;
528     unsigned index;
529     int srcskipleft = 0;
530
531     colors[0][0] = s->cirrus_shadow_gr0;
532     colors[0][1] = s->gr[0x10];
533     colors[0][2] = s->gr[0x12];
534     colors[1][0] = s->cirrus_shadow_gr1;
535     colors[1][1] = s->gr[0x11];
536     colors[1][2] = s->gr[0x13];
537
538     bitmask = 0x80 << srcskipleft;
539     bits = *src++;
540     for (x = 0; x < count; x++) {
541         if ((bitmask & 0xff) == 0) {
542             bitmask = 0x80;
543             bits = *src++;
544         }
545         index = !!(bits & bitmask);
546         *dst++ = colors[index][0];
547         *dst++ = colors[index][1];
548         *dst++ = colors[index][2];
549         bitmask >>= 1;
550     }
551 }
552
553 static void
554 cirrus_colorexpand_32(CirrusVGAState * s, uint8_t * dst,
555                       const uint8_t * src, int count)
556 {
557     int x;
558     uint8_t colors[2][4];
559     unsigned bits;
560     unsigned bitmask;
561     unsigned index;
562     int srcskipleft = 0;
563
564     colors[0][0] = s->cirrus_shadow_gr0;
565     colors[0][1] = s->gr[0x10];
566     colors[0][2] = s->gr[0x12];
567     colors[0][3] = s->gr[0x14];
568     colors[1][0] = s->cirrus_shadow_gr1;
569     colors[1][1] = s->gr[0x11];
570     colors[1][2] = s->gr[0x13];
571     colors[1][3] = s->gr[0x15];
572
573     bitmask = 0x80 << srcskipleft;
574     bits = *src++;
575     for (x = 0; x < count; x++) {
576         if ((bitmask & 0xff) == 0) {
577             bitmask = 0x80;
578             bits = *src++;
579         }
580         index = !!(bits & bitmask);
581         *dst++ = colors[index][0];
582         *dst++ = colors[index][1];
583         *dst++ = colors[index][2];
584         *dst++ = colors[index][3];
585         bitmask >>= 1;
586     }
587 }
588
589 static void
590 cirrus_colorexpand(CirrusVGAState * s, uint8_t * dst, const uint8_t * src,
591                    int count)
592 {
593     switch (s->cirrus_blt_pixelwidth) {
594     case 1:
595         cirrus_colorexpand_8(s, dst, src, count);
596         break;
597     case 2:
598         cirrus_colorexpand_16(s, dst, src, count);
599         break;
600     case 3:
601         cirrus_colorexpand_24(s, dst, src, count);
602         break;
603     case 4:
604         cirrus_colorexpand_32(s, dst, src, count);
605         break;
606     default:
607 #ifdef DEBUG_CIRRUS
608         printf("cirrus: COLOREXPAND pixelwidth %d - unimplemented\n",
609                s->cirrus_blt_pixelwidth);
610 #endif
611         break;
612     }
613 }
614
615 static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
616                                      int off_pitch, int bytesperline,
617                                      int lines)
618 {
619     int y;
620     int off_cur;
621     int off_cur_end;
622
623     for (y = 0; y < lines; y++) {
624         off_cur = off_begin;
625         off_cur_end = off_cur + bytesperline;
626         off_cur &= TARGET_PAGE_MASK;
627         while (off_cur < off_cur_end) {
628             cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
629             off_cur += TARGET_PAGE_SIZE;
630         }
631         off_begin += off_pitch;
632     }
633 }
634
635
636
637 static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
638                                             const uint8_t * src)
639 {
640     uint8_t work_colorexp[256];
641     uint8_t *dst;
642     uint8_t *dstc;
643     int x, y;
644     int tilewidth, tileheight;
645     int patternbytes = s->cirrus_blt_pixelwidth * 8;
646
647     if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
648         cirrus_colorexpand(s, work_colorexp, src, 8 * 8);
649         src = work_colorexp;
650         s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_COLOREXPAND;
651     }
652     if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_PATTERNCOPY) {
653 #ifdef DEBUG_CIRRUS
654         printf("cirrus: blt mode %02x (pattercopy) - unimplemented\n",
655                s->cirrus_blt_mode);
656 #endif
657         return 0;
658     }
659     
660     dst = s->vram_ptr + s->cirrus_blt_dstaddr;
661     for (y = 0; y < s->cirrus_blt_height; y += 8) {
662         dstc = dst;
663         tileheight = qemu_MIN(8, s->cirrus_blt_height - y);
664         for (x = 0; x < s->cirrus_blt_width; x += patternbytes) {
665             tilewidth = qemu_MIN(patternbytes, s->cirrus_blt_width - x);
666             (*s->cirrus_rop) (dstc, src,
667                               s->cirrus_blt_dstpitch, patternbytes,
668                               tilewidth, tileheight);
669             dstc += patternbytes;
670         }
671         dst += s->cirrus_blt_dstpitch * 8;
672     }
673     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
674                              s->cirrus_blt_dstpitch, s->cirrus_blt_width,
675                              s->cirrus_blt_height);
676     return 1;
677 }
678
679 /* fill */
680
681 static void cirrus_fill_8(CirrusVGAState *s,
682                           uint8_t *dst, int dst_pitch, int width, int height)
683 {
684     uint8_t *d, *d1;
685     uint32_t val;
686     int x, y;
687
688     val = s->cirrus_shadow_gr1;
689
690     d1 = dst;
691     for(y = 0; y < height; y++) {
692         d = d1;
693         for(x = 0; x < width; x++) {
694             *d++ = val;
695         }
696         d1 += dst_pitch;
697     }
698 }
699
700 static void cirrus_fill_16(CirrusVGAState *s,
701                            uint8_t *dst, int dst_pitch, int width, int height)
702 {
703     uint8_t *d, *d1;
704     uint32_t val;
705     int x, y;
706
707     val = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8);
708     val = le16_to_cpu(val);
709     width >>= 1;
710
711     d1 = dst;
712     for(y = 0; y < height; y++) {
713         d = d1;
714         for(x = 0; x < width; x++) {
715             ((uint16_t *)d)[0] = val;
716             d += 2;
717         }
718         d1 += dst_pitch;
719     }
720 }
721
722 static void cirrus_fill_24(CirrusVGAState *s,
723                            uint8_t *dst, int dst_pitch, int width, int height)
724 {
725     uint8_t *d, *d1;
726     int x, y;
727
728     d1 = dst;
729     for(y = 0; y < height; y++) {
730         d = d1;
731         for(x = 0; x < width; x += 3) {
732             *d++ = s->cirrus_shadow_gr1;
733             *d++ = s->gr[0x11];
734             *d++ = s->gr[0x13];
735         }
736         d1 += dst_pitch;
737     }
738 }
739
740 static void cirrus_fill_32(CirrusVGAState *s,
741                            uint8_t *dst, int dst_pitch, int width, int height)
742 {
743     uint8_t *d, *d1;
744     uint32_t val;
745     int x, y;
746
747     val = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) | 
748         (s->gr[0x13] << 8) | (s->gr[0x15] << 8);
749     val = le32_to_cpu(val);
750     width >>= 2;
751
752     d1 = dst;
753     for(y = 0; y < height; y++) {
754         d = d1;
755         for(x = 0; x < width; x++) {
756             ((uint32_t *)d)[0] = val;
757             d += 4;
758         }
759         d1 += dst_pitch;
760     }
761 }
762
763 static int cirrus_bitblt_solidfill(CirrusVGAState *s)
764 {
765     uint8_t *dst;
766     dst = s->vram_ptr + s->cirrus_blt_dstaddr;
767     switch (s->cirrus_blt_pixelwidth) {
768     case 1:
769         cirrus_fill_8(s, dst, s->cirrus_blt_dstpitch,
770                       s->cirrus_blt_width, s->cirrus_blt_height);
771         break;
772     case 2:
773         cirrus_fill_16(s, dst, s->cirrus_blt_dstpitch,
774                        s->cirrus_blt_width, s->cirrus_blt_height);
775         break;
776     case 3:
777         cirrus_fill_24(s, dst, s->cirrus_blt_dstpitch,
778                        s->cirrus_blt_width, s->cirrus_blt_height);
779         break;
780     default:
781     case 4:
782         cirrus_fill_32(s, dst, s->cirrus_blt_dstpitch,
783                        s->cirrus_blt_width, s->cirrus_blt_height);
784         break;
785     }
786     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
787                              s->cirrus_blt_dstpitch, s->cirrus_blt_width,
788                              s->cirrus_blt_height);
789     cirrus_bitblt_reset(s);
790     return 1;
791 }
792
793 /***************************************
794  *
795  *  bitblt (video-to-video)
796  *
797  ***************************************/
798
799 static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
800 {
801     return cirrus_bitblt_common_patterncopy(s,
802                                             s->vram_ptr +
803                                             s->cirrus_blt_srcaddr);
804 }
805
806 static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
807 {
808     if ((s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) != 0) {
809 #ifdef DEBUG_CIRRUS
810         printf("cirrus: CIRRUS_BLTMODE_COLOREXPAND - unimplemented\n");
811 #endif
812         return 0;
813     }
814     if ((s->cirrus_blt_mode & (~CIRRUS_BLTMODE_BACKWARDS)) != 0) {
815 #ifdef DEBUG_CIRRUS
816         printf("cirrus: blt mode %02x - unimplemented\n",
817                s->cirrus_blt_mode);
818 #endif
819         return 0;
820     }
821
822     (*s->cirrus_rop) (s->vram_ptr + s->cirrus_blt_dstaddr,
823                       s->vram_ptr + s->cirrus_blt_srcaddr,
824                       s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
825                       s->cirrus_blt_width, s->cirrus_blt_height);
826     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
827                              s->cirrus_blt_dstpitch, s->cirrus_blt_width,
828                              s->cirrus_blt_height);
829     return 1;
830 }
831
832 /***************************************
833  *
834  *  bitblt (cpu-to-video)
835  *
836  ***************************************/
837
838 static void cirrus_bitblt_cputovideo_patterncopy(void *opaque)
839 {
840     CirrusVGAState *s = (CirrusVGAState *) opaque;
841     int data_count;
842
843     data_count = s->cirrus_srcptr - &s->cirrus_bltbuf[0];
844
845     if (data_count > 0) {
846         if (data_count != s->cirrus_srccounter) {
847 #ifdef DEBUG_CIRRUS
848             printf("cirrus: internal error\n");
849 #endif
850         } else {
851             cirrus_bitblt_common_patterncopy(s, &s->cirrus_bltbuf[0]);
852         }
853         cirrus_bitblt_reset(s);
854     }
855 }
856
857 static void cirrus_bitblt_cputovideo_copy(void *opaque)
858 {
859     CirrusVGAState *s = (CirrusVGAState *) opaque;
860     int data_count;
861     int data_avail;
862     uint8_t work_colorexp[256];
863     uint8_t *src_ptr = NULL;
864     int src_avail = 0;
865     int src_processing;
866     int src_linepad = 0;
867
868     if (s->cirrus_blt_height <= 0) {
869         s->cirrus_srcptr = s->cirrus_srcptr_end;
870         return;
871     }
872
873     s->cirrus_srcptr = &s->cirrus_bltbuf[0];
874     while (1) {
875         /* get BLT source. */
876         if (src_avail <= 0) {
877             data_count = s->cirrus_srcptr_end - s->cirrus_srcptr;
878             if (data_count <= 0)
879                 break;
880
881             if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
882                 if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_COLOREXPAND) {
883 #ifdef DEBUG_CIRRUS
884                     printf("cirrus: unsupported\n");
885 #endif
886                     cirrus_bitblt_reset(s);
887                     return;
888                 }
889                 data_avail = qemu_MIN(data_count, 256 / 32);
890                 cirrus_colorexpand(s, work_colorexp, s->cirrus_srcptr,
891                                    data_avail * 8);
892                 src_ptr = &work_colorexp[0];
893                 src_avail = data_avail * 8 * s->cirrus_blt_pixelwidth;
894                 s->cirrus_srcptr += data_avail;
895                 src_linepad =
896                     ((s->cirrus_blt_width + 7) / 8) * 8 -
897                     s->cirrus_blt_width;
898                 src_linepad *= s->cirrus_blt_pixelwidth;
899             } else {
900                 if (s->cirrus_blt_mode != 0) {
901 #ifdef DEBUG_CIRRUS
902                     printf("cirrus: unsupported\n");
903 #endif
904                     cirrus_bitblt_reset(s);
905                     return;
906                 }
907                 src_ptr = s->cirrus_srcptr;
908                 src_avail =
909                     data_count / s->cirrus_blt_pixelwidth *
910                     s->cirrus_blt_pixelwidth;
911                 s->cirrus_srcptr += src_avail;
912             }
913             if (src_avail <= 0)
914                 break;
915         }
916
917         /* 1-line BLT */
918         src_processing =
919             s->cirrus_blt_srcpitch - s->cirrus_blt_horz_counter;
920         src_processing = qemu_MIN(src_avail, src_processing);
921         (*s->cirrus_rop) (s->vram_ptr + s->cirrus_blt_dstaddr,
922                           src_ptr, 0, 0, src_processing, 1);
923         cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
924                                  src_processing, 1);
925
926         s->cirrus_blt_dstaddr += src_processing;
927         src_ptr += src_processing;
928         src_avail -= src_processing;
929         s->cirrus_blt_horz_counter += src_processing;
930         if (s->cirrus_blt_horz_counter >= s->cirrus_blt_srcpitch) {
931             src_ptr += src_linepad;
932             src_avail -= src_linepad;
933             s->cirrus_blt_dstaddr +=
934                 s->cirrus_blt_dstpitch - s->cirrus_blt_srcpitch;
935             s->cirrus_blt_horz_counter = 0;
936             s->cirrus_blt_height--;
937             if (s->cirrus_blt_height <= 0) {
938                 s->cirrus_srcptr = s->cirrus_srcptr_end;
939                 return;
940             }
941         }
942     }
943 }
944
945 static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
946 {
947     int copy_count;
948     int avail_count;
949
950     s->cirrus_blt_handler(s);
951
952     if (s->cirrus_srccounter > 0) {
953         s->cirrus_srccounter -= s->cirrus_srcptr - &s->cirrus_bltbuf[0];
954         copy_count = s->cirrus_srcptr_end - s->cirrus_srcptr;
955         memmove(&s->cirrus_bltbuf[0], s->cirrus_srcptr, copy_count);
956         avail_count = qemu_MIN(CIRRUS_BLTBUFSIZE, s->cirrus_srccounter);
957         s->cirrus_srcptr = &s->cirrus_bltbuf[0];
958         s->cirrus_srcptr_end = s->cirrus_srcptr + avail_count;
959         if (s->cirrus_srccounter <= 0) {
960             cirrus_bitblt_reset(s);
961         }
962     }
963 }
964
965 /***************************************
966  *
967  *  bitblt wrapper
968  *
969  ***************************************/
970
971 static void cirrus_bitblt_reset(CirrusVGAState * s)
972 {
973     s->gr[0x31] &=
974         ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED);
975     s->cirrus_srcptr = &s->cirrus_bltbuf[0];
976     s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
977     s->cirrus_srccounter = 0;
978     s->cirrus_dstptr = &s->cirrus_bltbuf[0];
979     s->cirrus_dstptr_end = &s->cirrus_bltbuf[0];
980     s->cirrus_dstcounter = 0;
981     s->cirrus_blt_handler = NULL;
982 }
983
984 static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
985 {
986     s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
987     s->cirrus_srcptr = &s->cirrus_bltbuf[0];
988     s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
989
990     if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
991         if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
992             s->cirrus_srccounter = 8;
993         } else {
994             s->cirrus_srccounter = 8 * 8 * s->cirrus_blt_pixelwidth;
995         }
996         s->cirrus_blt_srcpitch = 0;
997         s->cirrus_blt_handler = cirrus_bitblt_cputovideo_patterncopy;
998     } else {
999         if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
1000             s->cirrus_srccounter =
1001                 ((s->cirrus_blt_width + 7) / 8) * s->cirrus_blt_height;
1002             s->cirrus_blt_srcpitch =
1003                 s->cirrus_blt_width * s->cirrus_blt_pixelwidth;
1004         } else {
1005             s->cirrus_srccounter =
1006                 s->cirrus_blt_width * s->cirrus_blt_height;
1007             s->cirrus_blt_srcpitch = s->cirrus_blt_width;
1008         }
1009         /* 4-byte alignment */
1010         s->cirrus_srccounter = (s->cirrus_srccounter + 3) & (~3);
1011
1012         s->cirrus_blt_handler = cirrus_bitblt_cputovideo_copy;
1013         s->cirrus_blt_horz_counter = 0;
1014     }
1015
1016     cirrus_bitblt_cputovideo_next(s);
1017     return 1;
1018 }
1019
1020 static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
1021 {
1022     /* XXX */
1023 #ifdef DEBUG_CIRRUS
1024     printf("cirrus: bitblt (video to cpu) is not implemented yet\n");
1025 #endif
1026     return 0;
1027 }
1028
1029 static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
1030 {
1031     int ret;
1032
1033     if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
1034         ret = cirrus_bitblt_videotovideo_patterncopy(s);
1035     } else {
1036         ret = cirrus_bitblt_videotovideo_copy(s);
1037     }
1038
1039     if (ret)
1040         cirrus_bitblt_reset(s);
1041     return ret;
1042 }
1043
1044 static void cirrus_bitblt_start(CirrusVGAState * s)
1045 {
1046     uint8_t blt_rop;
1047
1048     s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1;
1049     s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1;
1050     s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8));
1051     s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8));
1052     s->cirrus_blt_dstaddr =
1053         (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16));
1054     s->cirrus_blt_srcaddr =
1055         (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16));
1056     s->cirrus_blt_mode = s->gr[0x30];
1057     blt_rop = s->gr[0x32];
1058
1059 #ifdef DEBUG_BITBLT
1060     printf("rop=%02x mode=%02x modeext=%02x w=%d h=%d dpitch=%d spicth=%d daddr=%08x saddr=%08x\n",
1061            blt_rop, 
1062            s->cirrus_blt_mode,
1063            s->gr[0x33],
1064            s->cirrus_blt_width,
1065            s->cirrus_blt_height,
1066            s->cirrus_blt_dstpitch,
1067            s->cirrus_blt_srcpitch,
1068            s->cirrus_blt_dstaddr,
1069            s->cirrus_blt_srcaddr);
1070 #endif
1071
1072     switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
1073     case CIRRUS_BLTMODE_PIXELWIDTH8:
1074         s->cirrus_blt_pixelwidth = 1;
1075         break;
1076     case CIRRUS_BLTMODE_PIXELWIDTH16:
1077         s->cirrus_blt_pixelwidth = 2;
1078         break;
1079     case CIRRUS_BLTMODE_PIXELWIDTH24:
1080         s->cirrus_blt_pixelwidth = 3;
1081         break;
1082     case CIRRUS_BLTMODE_PIXELWIDTH32:
1083         s->cirrus_blt_pixelwidth = 4;
1084         break;
1085     default:
1086 #ifdef DEBUG_CIRRUS
1087         printf("cirrus: bitblt - pixel width is unknown\n");
1088 #endif
1089         goto bitblt_ignore;
1090     }
1091     s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
1092
1093     if ((s->
1094          cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
1095                             CIRRUS_BLTMODE_MEMSYSDEST))
1096         == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
1097 #ifdef DEBUG_CIRRUS
1098         printf("cirrus: bitblt - memory-to-memory copy is requested\n");
1099 #endif
1100         goto bitblt_ignore;
1101     }
1102
1103     if ((s->gr[0x33] & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
1104         (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | 
1105                                CIRRUS_BLTMODE_TRANSPARENTCOMP |
1106                                CIRRUS_BLTMODE_PATTERNCOPY | 
1107                                CIRRUS_BLTMODE_COLOREXPAND)) == 
1108          (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
1109         cirrus_bitblt_solidfill(s);
1110     } else {
1111         if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
1112             s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
1113             s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
1114             s->cirrus_rop = cirrus_get_bkwd_rop_handler(blt_rop);
1115         } else {
1116             s->cirrus_rop = cirrus_get_fwd_rop_handler(blt_rop);
1117         }
1118         
1119         // setup bitblt engine.
1120         if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
1121             if (!cirrus_bitblt_cputovideo(s))
1122                 goto bitblt_ignore;
1123         } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
1124             if (!cirrus_bitblt_videotocpu(s))
1125                 goto bitblt_ignore;
1126         } else {
1127             if (!cirrus_bitblt_videotovideo(s))
1128                 goto bitblt_ignore;
1129         }
1130     }
1131     return;
1132   bitblt_ignore:;
1133     cirrus_bitblt_reset(s);
1134 }
1135
1136 static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
1137 {
1138     unsigned old_value;
1139
1140     old_value = s->gr[0x31];
1141     s->gr[0x31] = reg_value;
1142
1143     if (((old_value & CIRRUS_BLT_RESET) != 0) &&
1144         ((reg_value & CIRRUS_BLT_RESET) == 0)) {
1145         cirrus_bitblt_reset(s);
1146     } else if (((old_value & CIRRUS_BLT_START) == 0) &&
1147                ((reg_value & CIRRUS_BLT_START) != 0)) {
1148         s->gr[0x31] |= CIRRUS_BLT_BUSY;
1149         cirrus_bitblt_start(s);
1150     }
1151 }
1152
1153
1154 /***************************************
1155  *
1156  *  basic parameters
1157  *
1158  ***************************************/
1159
1160 static void cirrus_get_offsets(VGAState *s1, 
1161                                    uint32_t *pline_offset,
1162                                    uint32_t *pstart_addr)
1163 {
1164     CirrusVGAState * s = (CirrusVGAState *)s1;
1165     uint32_t start_addr;
1166     uint32_t line_offset;
1167
1168     line_offset = s->cr[0x13]
1169         | ((s->cr[0x1b] & 0x10) << 4);
1170     line_offset <<= 3;
1171     *pline_offset = line_offset;
1172
1173     start_addr = (s->cr[0x0c] << 8)
1174         | s->cr[0x0d]
1175         | ((s->cr[0x1b] & 0x01) << 16)
1176         | ((s->cr[0x1b] & 0x0c) << 15)
1177         | ((s->cr[0x1d] & 0x80) << 12);
1178     *pstart_addr = start_addr;
1179 }
1180
1181 static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
1182 {
1183     uint32_t ret = 16;
1184
1185     switch (s->cirrus_hidden_dac_data & 0xf) {
1186     case 0:
1187         ret = 15;
1188         break;                  /* Sierra HiColor */
1189     case 1:
1190         ret = 16;
1191         break;                  /* XGA HiColor */
1192     default:
1193 #ifdef DEBUG_CIRRUS
1194         printf("cirrus: invalid DAC value %x in 16bpp\n",
1195                (s->cirrus_hidden_dac_data & 0xf));
1196 #endif
1197         ret = 15;               /* XXX */
1198         break;
1199     }
1200     return ret;
1201 }
1202
1203 static int cirrus_get_bpp(VGAState *s1)
1204 {
1205     CirrusVGAState * s = (CirrusVGAState *)s1;
1206     uint32_t ret = 8;
1207
1208     if ((s->sr[0x07] & 0x01) != 0) {
1209         /* Cirrus SVGA */
1210         switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) {
1211         case CIRRUS_SR7_BPP_8:
1212             ret = 8;
1213             break;
1214         case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
1215             ret = cirrus_get_bpp16_depth(s);
1216             break;
1217         case CIRRUS_SR7_BPP_24:
1218             ret = 24;
1219             break;
1220         case CIRRUS_SR7_BPP_16:
1221             ret = cirrus_get_bpp16_depth(s);
1222             break;
1223         case CIRRUS_SR7_BPP_32:
1224             ret = 32;
1225             break;
1226         default:
1227 #ifdef DEBUG_CIRRUS
1228             printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]);
1229 #endif
1230             ret = 8;
1231             break;
1232         }
1233     } else {
1234         /* VGA */
1235         ret = 0;
1236     }
1237
1238     return ret;
1239 }
1240
1241 /***************************************
1242  *
1243  * bank memory
1244  *
1245  ***************************************/
1246
1247 static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
1248 {
1249     unsigned offset;
1250     unsigned limit;
1251
1252     if ((s->gr[0x0b] & 0x01) != 0)      /* dual bank */
1253         offset = s->gr[0x09 + bank_index];
1254     else                        /* single bank */
1255         offset = s->gr[0x09];
1256
1257     if ((s->gr[0x0b] & 0x20) != 0)
1258         offset <<= 14;
1259     else
1260         offset <<= 12;
1261
1262     if (s->vram_size <= offset)
1263         limit = 0;
1264     else
1265         limit = s->vram_size - offset;
1266
1267     if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
1268         if (limit > 0x8000) {
1269             offset += 0x8000;
1270             limit -= 0x8000;
1271         } else {
1272             limit = 0;
1273         }
1274     }
1275
1276     if (limit > 0) {
1277         s->cirrus_bank_base[bank_index] = offset;
1278         s->cirrus_bank_limit[bank_index] = limit;
1279     } else {
1280         s->cirrus_bank_base[bank_index] = 0;
1281         s->cirrus_bank_limit[bank_index] = 0;
1282     }
1283 }
1284
1285 /***************************************
1286  *
1287  *  I/O access between 0x3c4-0x3c5
1288  *
1289  ***************************************/
1290
1291 static int
1292 cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1293 {
1294     switch (reg_index) {
1295     case 0x00:                  // Standard VGA
1296     case 0x01:                  // Standard VGA
1297     case 0x02:                  // Standard VGA
1298     case 0x03:                  // Standard VGA
1299     case 0x04:                  // Standard VGA
1300         return CIRRUS_HOOK_NOT_HANDLED;
1301     case 0x06:                  // Unlock Cirrus extensions
1302         *reg_value = s->sr[reg_index];
1303         break;
1304     case 0x10:
1305     case 0x30:
1306     case 0x50:
1307     case 0x70:                  // Graphics Cursor X
1308     case 0x90:
1309     case 0xb0:
1310     case 0xd0:
1311     case 0xf0:                  // Graphics Cursor X
1312         *reg_value = s->sr[0x10];
1313         break;
1314     case 0x11:
1315     case 0x31:
1316     case 0x51:
1317     case 0x71:                  // Graphics Cursor Y
1318     case 0x91:
1319     case 0xb1:
1320     case 0xd1:
1321         *reg_value = s->sr[0x11];
1322         break;
1323     case 0x05:                  // ???
1324     case 0x07:                  // Extended Sequencer Mode
1325     case 0x08:                  // EEPROM Control
1326     case 0x09:                  // Scratch Register 0
1327     case 0x0a:                  // Scratch Register 1
1328     case 0x0b:                  // VCLK 0
1329     case 0x0c:                  // VCLK 1
1330     case 0x0d:                  // VCLK 2
1331     case 0x0e:                  // VCLK 3
1332     case 0x0f:                  // DRAM Control
1333     case 0xf1:                  // Graphics Cursor Y
1334     case 0x12:                  // Graphics Cursor Attribute
1335     case 0x13:                  // Graphics Cursor Pattern Address
1336     case 0x14:                  // Scratch Register 2
1337     case 0x15:                  // Scratch Register 3
1338     case 0x16:                  // Performance Tuning Register
1339     case 0x17:                  // Configuration Readback and Extended Control
1340     case 0x18:                  // Signature Generator Control
1341     case 0x19:                  // Signal Generator Result
1342     case 0x1a:                  // Signal Generator Result
1343     case 0x1b:                  // VCLK 0 Denominator & Post
1344     case 0x1c:                  // VCLK 1 Denominator & Post
1345     case 0x1d:                  // VCLK 2 Denominator & Post
1346     case 0x1e:                  // VCLK 3 Denominator & Post
1347     case 0x1f:                  // BIOS Write Enable and MCLK select
1348 #ifdef DEBUG_CIRRUS
1349         printf("cirrus: handled inport sr_index %02x\n", reg_index);
1350 #endif
1351         *reg_value = s->sr[reg_index];
1352         break;
1353     default:
1354 #ifdef DEBUG_CIRRUS
1355         printf("cirrus: inport sr_index %02x\n", reg_index);
1356 #endif
1357         *reg_value = 0xff;
1358         break;
1359     }
1360
1361     return CIRRUS_HOOK_HANDLED;
1362 }
1363
1364 static int
1365 cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1366 {
1367     switch (reg_index) {
1368     case 0x00:                  // Standard VGA
1369     case 0x01:                  // Standard VGA
1370     case 0x02:                  // Standard VGA
1371     case 0x03:                  // Standard VGA
1372     case 0x04:                  // Standard VGA
1373         return CIRRUS_HOOK_NOT_HANDLED;
1374     case 0x06:                  // Unlock Cirrus extensions
1375         reg_value &= 0x17;
1376         if (reg_value == 0x12) {
1377             s->sr[reg_index] = 0x12;
1378         } else {
1379             s->sr[reg_index] = 0x0f;
1380         }
1381         break;
1382     case 0x10:
1383     case 0x30:
1384     case 0x50:
1385     case 0x70:                  // Graphics Cursor X
1386     case 0x90:
1387     case 0xb0:
1388     case 0xd0:
1389     case 0xf0:                  // Graphics Cursor X
1390         s->sr[0x10] = reg_value;
1391         s->cirrus_hw_cursor_x = ((reg_index << 3) & 0x700) | reg_value;
1392         break;
1393     case 0x11:
1394     case 0x31:
1395     case 0x51:
1396     case 0x71:                  // Graphics Cursor Y
1397     case 0x91:
1398     case 0xb1:
1399     case 0xd1:
1400     case 0xf1:                  // Graphics Cursor Y
1401         s->sr[0x11] = reg_value;
1402         s->cirrus_hw_cursor_y = ((reg_index << 3) & 0x700) | reg_value;
1403         break;
1404     case 0x07:                  // Extended Sequencer Mode
1405     case 0x08:                  // EEPROM Control
1406     case 0x09:                  // Scratch Register 0
1407     case 0x0a:                  // Scratch Register 1
1408     case 0x0b:                  // VCLK 0
1409     case 0x0c:                  // VCLK 1
1410     case 0x0d:                  // VCLK 2
1411     case 0x0e:                  // VCLK 3
1412     case 0x0f:                  // DRAM Control
1413     case 0x12:                  // Graphics Cursor Attribute
1414     case 0x13:                  // Graphics Cursor Pattern Address
1415     case 0x14:                  // Scratch Register 2
1416     case 0x15:                  // Scratch Register 3
1417     case 0x16:                  // Performance Tuning Register
1418     case 0x17:                  // Configuration Readback and Extended Control
1419     case 0x18:                  // Signature Generator Control
1420     case 0x19:                  // Signature Generator Result
1421     case 0x1a:                  // Signature Generator Result
1422     case 0x1b:                  // VCLK 0 Denominator & Post
1423     case 0x1c:                  // VCLK 1 Denominator & Post
1424     case 0x1d:                  // VCLK 2 Denominator & Post
1425     case 0x1e:                  // VCLK 3 Denominator & Post
1426     case 0x1f:                  // BIOS Write Enable and MCLK select
1427         s->sr[reg_index] = reg_value;
1428 #ifdef DEBUG_CIRRUS
1429         printf("cirrus: handled outport sr_index %02x, sr_value %02x\n",
1430                reg_index, reg_value);
1431 #endif
1432         break;
1433     default:
1434 #ifdef DEBUG_CIRRUS
1435         printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index,
1436                reg_value);
1437 #endif
1438         break;
1439     }
1440
1441     return CIRRUS_HOOK_HANDLED;
1442 }
1443
1444 /***************************************
1445  *
1446  *  I/O access at 0x3c6
1447  *
1448  ***************************************/
1449
1450 static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value)
1451 {
1452     *reg_value = 0xff;
1453     if (++s->cirrus_hidden_dac_lockindex == 5) {
1454         *reg_value = s->cirrus_hidden_dac_data;
1455         s->cirrus_hidden_dac_lockindex = 0;
1456     }
1457 }
1458
1459 static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
1460 {
1461     if (s->cirrus_hidden_dac_lockindex == 4) {
1462         s->cirrus_hidden_dac_data = reg_value;
1463 #if defined(DEBUG_CIRRUS)
1464         printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
1465 #endif
1466     }
1467     s->cirrus_hidden_dac_lockindex = 0;
1468 }
1469
1470 /***************************************
1471  *
1472  *  I/O access at 0x3c9
1473  *
1474  ***************************************/
1475
1476 static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value)
1477 {
1478     if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1479         return CIRRUS_HOOK_NOT_HANDLED;
1480     if (s->dac_read_index < 0x10) {
1481         *reg_value =
1482             s->cirrus_hidden_palette[s->dac_read_index * 3 +
1483                                      s->dac_sub_index];
1484     } else {
1485         *reg_value = 0xff;      /* XXX */
1486     }
1487     if (++s->dac_sub_index == 3) {
1488         s->dac_sub_index = 0;
1489         s->dac_read_index++;
1490     }
1491     return CIRRUS_HOOK_HANDLED;
1492 }
1493
1494 static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value)
1495 {
1496     if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1497         return CIRRUS_HOOK_NOT_HANDLED;
1498     s->dac_cache[s->dac_sub_index] = reg_value;
1499     if (++s->dac_sub_index == 3) {
1500         if (s->dac_read_index < 0x10) {
1501             memcpy(&s->cirrus_hidden_palette[s->dac_write_index * 3],
1502                    s->dac_cache, 3);
1503             /* XXX update cursor */
1504         }
1505         s->dac_sub_index = 0;
1506         s->dac_write_index++;
1507     }
1508     return CIRRUS_HOOK_HANDLED;
1509 }
1510
1511 /***************************************
1512  *
1513  *  I/O access between 0x3ce-0x3cf
1514  *
1515  ***************************************/
1516
1517 static int
1518 cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1519 {
1520     switch (reg_index) {
1521     case 0x00: // Standard VGA, BGCOLOR 0x000000ff
1522       *reg_value = s->cirrus_shadow_gr0;
1523       return CIRRUS_HOOK_HANDLED;
1524     case 0x01: // Standard VGA, FGCOLOR 0x000000ff
1525       *reg_value = s->cirrus_shadow_gr1;
1526       return CIRRUS_HOOK_HANDLED;
1527     case 0x02:                  // Standard VGA
1528     case 0x03:                  // Standard VGA
1529     case 0x04:                  // Standard VGA
1530     case 0x06:                  // Standard VGA
1531     case 0x07:                  // Standard VGA
1532     case 0x08:                  // Standard VGA
1533         return CIRRUS_HOOK_NOT_HANDLED;
1534     case 0x05:                  // Standard VGA, Cirrus extended mode
1535     default:
1536         break;
1537     }
1538
1539     if (reg_index < 0x3a) {
1540         *reg_value = s->gr[reg_index];
1541     } else {
1542 #ifdef DEBUG_CIRRUS
1543         printf("cirrus: inport gr_index %02x\n", reg_index);
1544 #endif
1545         *reg_value = 0xff;
1546     }
1547
1548     return CIRRUS_HOOK_HANDLED;
1549 }
1550
1551 static int
1552 cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1553 {
1554     switch (reg_index) {
1555     case 0x00:                  // Standard VGA, BGCOLOR 0x000000ff
1556         s->cirrus_shadow_gr0 = reg_value;
1557         return CIRRUS_HOOK_NOT_HANDLED;
1558     case 0x01:                  // Standard VGA, FGCOLOR 0x000000ff
1559         s->cirrus_shadow_gr1 = reg_value;
1560         return CIRRUS_HOOK_NOT_HANDLED;
1561     case 0x02:                  // Standard VGA
1562     case 0x03:                  // Standard VGA
1563     case 0x04:                  // Standard VGA
1564     case 0x06:                  // Standard VGA
1565     case 0x07:                  // Standard VGA
1566     case 0x08:                  // Standard VGA
1567         return CIRRUS_HOOK_NOT_HANDLED;
1568     case 0x05:                  // Standard VGA, Cirrus extended mode
1569         s->gr[reg_index] = reg_value & 0x7f;
1570         break;
1571     case 0x09:                  // bank offset #0
1572     case 0x0A:                  // bank offset #1
1573     case 0x0B:
1574         s->gr[reg_index] = reg_value;
1575         cirrus_update_bank_ptr(s, 0);
1576         cirrus_update_bank_ptr(s, 1);
1577         break;
1578     case 0x10:                  // BGCOLOR 0x0000ff00
1579     case 0x11:                  // FGCOLOR 0x0000ff00
1580     case 0x12:                  // BGCOLOR 0x00ff0000
1581     case 0x13:                  // FGCOLOR 0x00ff0000
1582     case 0x14:                  // BGCOLOR 0xff000000
1583     case 0x15:                  // FGCOLOR 0xff000000
1584     case 0x20:                  // BLT WIDTH 0x0000ff
1585     case 0x22:                  // BLT HEIGHT 0x0000ff
1586     case 0x24:                  // BLT DEST PITCH 0x0000ff
1587     case 0x26:                  // BLT SRC PITCH 0x0000ff
1588     case 0x28:                  // BLT DEST ADDR 0x0000ff
1589     case 0x29:                  // BLT DEST ADDR 0x00ff00
1590     case 0x2c:                  // BLT SRC ADDR 0x0000ff
1591     case 0x2d:                  // BLT SRC ADDR 0x00ff00
1592     case 0x30:                  // BLT MODE
1593     case 0x32:                  // RASTER OP
1594     case 0x33:                  // BLT MODEEXT
1595     case 0x34:                  // BLT TRANSPARENT COLOR 0x00ff
1596     case 0x35:                  // BLT TRANSPARENT COLOR 0xff00
1597     case 0x38:                  // BLT TRANSPARENT COLOR MASK 0x00ff
1598     case 0x39:                  // BLT TRANSPARENT COLOR MASK 0xff00
1599         s->gr[reg_index] = reg_value;
1600         break;
1601     case 0x21:                  // BLT WIDTH 0x001f00
1602     case 0x23:                  // BLT HEIGHT 0x001f00
1603     case 0x25:                  // BLT DEST PITCH 0x001f00
1604     case 0x27:                  // BLT SRC PITCH 0x001f00
1605         s->gr[reg_index] = reg_value & 0x1f;
1606         break;
1607     case 0x2a:                  // BLT DEST ADDR 0x3f0000
1608     case 0x2e:                  // BLT SRC ADDR 0x3f0000
1609         s->gr[reg_index] = reg_value & 0x3f;
1610         break;
1611     case 0x31:                  // BLT STATUS/START
1612         cirrus_write_bitblt(s, reg_value);
1613         break;
1614     default:
1615 #ifdef DEBUG_CIRRUS
1616         printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
1617                reg_value);
1618 #endif
1619         break;
1620     }
1621
1622     return CIRRUS_HOOK_HANDLED;
1623 }
1624
1625 /***************************************
1626  *
1627  *  I/O access between 0x3d4-0x3d5
1628  *
1629  ***************************************/
1630
1631 static int
1632 cirrus_hook_read_cr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1633 {
1634     switch (reg_index) {
1635     case 0x00:                  // Standard VGA
1636     case 0x01:                  // Standard VGA
1637     case 0x02:                  // Standard VGA
1638     case 0x03:                  // Standard VGA
1639     case 0x04:                  // Standard VGA
1640     case 0x05:                  // Standard VGA
1641     case 0x06:                  // Standard VGA
1642     case 0x07:                  // Standard VGA
1643     case 0x08:                  // Standard VGA
1644     case 0x09:                  // Standard VGA
1645     case 0x0a:                  // Standard VGA
1646     case 0x0b:                  // Standard VGA
1647     case 0x0c:                  // Standard VGA
1648     case 0x0d:                  // Standard VGA
1649     case 0x0e:                  // Standard VGA
1650     case 0x0f:                  // Standard VGA
1651     case 0x10:                  // Standard VGA
1652     case 0x11:                  // Standard VGA
1653     case 0x12:                  // Standard VGA
1654     case 0x13:                  // Standard VGA
1655     case 0x14:                  // Standard VGA
1656     case 0x15:                  // Standard VGA
1657     case 0x16:                  // Standard VGA
1658     case 0x17:                  // Standard VGA
1659     case 0x18:                  // Standard VGA
1660         return CIRRUS_HOOK_NOT_HANDLED;
1661     case 0x19:                  // Interlace End
1662     case 0x1a:                  // Miscellaneous Control
1663     case 0x1b:                  // Extended Display Control
1664     case 0x1c:                  // Sync Adjust and Genlock
1665     case 0x1d:                  // Overlay Extended Control
1666     case 0x22:                  // Graphics Data Latches Readback (R)
1667     case 0x24:                  // Attribute Controller Toggle Readback (R)
1668     case 0x25:                  // Part Status
1669     case 0x27:                  // Part ID (R)
1670         *reg_value = s->cr[reg_index];
1671         break;
1672     case 0x26:                  // Attribute Controller Index Readback (R)
1673         *reg_value = s->ar_index & 0x3f;
1674         break;
1675     default:
1676 #ifdef DEBUG_CIRRUS
1677         printf("cirrus: inport cr_index %02x\n", reg_index);
1678         *reg_value = 0xff;
1679 #endif
1680         break;
1681     }
1682
1683     return CIRRUS_HOOK_HANDLED;
1684 }
1685
1686 static int
1687 cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1688 {
1689     switch (reg_index) {
1690     case 0x00:                  // Standard VGA
1691     case 0x01:                  // Standard VGA
1692     case 0x02:                  // Standard VGA
1693     case 0x03:                  // Standard VGA
1694     case 0x04:                  // Standard VGA
1695     case 0x05:                  // Standard VGA
1696     case 0x06:                  // Standard VGA
1697     case 0x07:                  // Standard VGA
1698     case 0x08:                  // Standard VGA
1699     case 0x09:                  // Standard VGA
1700     case 0x0a:                  // Standard VGA
1701     case 0x0b:                  // Standard VGA
1702     case 0x0c:                  // Standard VGA
1703     case 0x0d:                  // Standard VGA
1704     case 0x0e:                  // Standard VGA
1705     case 0x0f:                  // Standard VGA
1706     case 0x10:                  // Standard VGA
1707     case 0x11:                  // Standard VGA
1708     case 0x12:                  // Standard VGA
1709     case 0x13:                  // Standard VGA
1710     case 0x14:                  // Standard VGA
1711     case 0x15:                  // Standard VGA
1712     case 0x16:                  // Standard VGA
1713     case 0x17:                  // Standard VGA
1714     case 0x18:                  // Standard VGA
1715         return CIRRUS_HOOK_NOT_HANDLED;
1716     case 0x19:                  // Interlace End
1717     case 0x1a:                  // Miscellaneous Control
1718     case 0x1b:                  // Extended Display Control
1719     case 0x1c:                  // Sync Adjust and Genlock
1720         s->cr[reg_index] = reg_value;
1721 #ifdef DEBUG_CIRRUS
1722         printf("cirrus: handled outport cr_index %02x, cr_value %02x\n",
1723                reg_index, reg_value);
1724 #endif
1725         break;
1726     case 0x22:                  // Graphics Data Latches Readback (R)
1727     case 0x24:                  // Attribute Controller Toggle Readback (R)
1728     case 0x26:                  // Attribute Controller Index Readback (R)
1729     case 0x27:                  // Part ID (R)
1730         break;
1731     case 0x1d:                  // Overlay Extended Control
1732     case 0x25:                  // Part Status
1733     default:
1734 #ifdef DEBUG_CIRRUS
1735         printf("cirrus: outport cr_index %02x, cr_value %02x\n", reg_index,
1736                reg_value);
1737 #endif
1738         break;
1739     }
1740
1741     return CIRRUS_HOOK_HANDLED;
1742 }
1743
1744 /***************************************
1745  *
1746  *  memory-mapped I/O (bitblt)
1747  *
1748  ***************************************/
1749
1750 static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
1751 {
1752     int value = 0xff;
1753
1754     switch (address) {
1755     case (CIRRUS_MMIO_BLTBGCOLOR + 0):
1756         cirrus_hook_read_gr(s, 0x00, &value);
1757         break;
1758     case (CIRRUS_MMIO_BLTBGCOLOR + 1):
1759         cirrus_hook_read_gr(s, 0x10, &value);
1760         break;
1761     case (CIRRUS_MMIO_BLTBGCOLOR + 2):
1762         cirrus_hook_read_gr(s, 0x12, &value);
1763         break;
1764     case (CIRRUS_MMIO_BLTBGCOLOR + 3):
1765         cirrus_hook_read_gr(s, 0x14, &value);
1766         break;
1767     case (CIRRUS_MMIO_BLTFGCOLOR + 0):
1768         cirrus_hook_read_gr(s, 0x01, &value);
1769         break;
1770     case (CIRRUS_MMIO_BLTFGCOLOR + 1):
1771         cirrus_hook_read_gr(s, 0x11, &value);
1772         break;
1773     case (CIRRUS_MMIO_BLTFGCOLOR + 2):
1774         cirrus_hook_read_gr(s, 0x13, &value);
1775         break;
1776     case (CIRRUS_MMIO_BLTFGCOLOR + 3):
1777         cirrus_hook_read_gr(s, 0x15, &value);
1778         break;
1779     case (CIRRUS_MMIO_BLTWIDTH + 0):
1780         cirrus_hook_read_gr(s, 0x20, &value);
1781         break;
1782     case (CIRRUS_MMIO_BLTWIDTH + 1):
1783         cirrus_hook_read_gr(s, 0x21, &value);
1784         break;
1785     case (CIRRUS_MMIO_BLTHEIGHT + 0):
1786         cirrus_hook_read_gr(s, 0x22, &value);
1787         break;
1788     case (CIRRUS_MMIO_BLTHEIGHT + 1):
1789         cirrus_hook_read_gr(s, 0x23, &value);
1790         break;
1791     case (CIRRUS_MMIO_BLTDESTPITCH + 0):
1792         cirrus_hook_read_gr(s, 0x24, &value);
1793         break;
1794     case (CIRRUS_MMIO_BLTDESTPITCH + 1):
1795         cirrus_hook_read_gr(s, 0x25, &value);
1796         break;
1797     case (CIRRUS_MMIO_BLTSRCPITCH + 0):
1798         cirrus_hook_read_gr(s, 0x26, &value);
1799         break;
1800     case (CIRRUS_MMIO_BLTSRCPITCH + 1):
1801         cirrus_hook_read_gr(s, 0x27, &value);
1802         break;
1803     case (CIRRUS_MMIO_BLTDESTADDR + 0):
1804         cirrus_hook_read_gr(s, 0x28, &value);
1805         break;
1806     case (CIRRUS_MMIO_BLTDESTADDR + 1):
1807         cirrus_hook_read_gr(s, 0x29, &value);
1808         break;
1809     case (CIRRUS_MMIO_BLTDESTADDR + 2):
1810         cirrus_hook_read_gr(s, 0x2a, &value);
1811         break;
1812     case (CIRRUS_MMIO_BLTSRCADDR + 0):
1813         cirrus_hook_read_gr(s, 0x2c, &value);
1814         break;
1815     case (CIRRUS_MMIO_BLTSRCADDR + 1):
1816         cirrus_hook_read_gr(s, 0x2d, &value);
1817         break;
1818     case (CIRRUS_MMIO_BLTSRCADDR + 2):
1819         cirrus_hook_read_gr(s, 0x2e, &value);
1820         break;
1821     case CIRRUS_MMIO_BLTWRITEMASK:
1822         cirrus_hook_read_gr(s, 0x2f, &value);
1823         break;
1824     case CIRRUS_MMIO_BLTMODE:
1825         cirrus_hook_read_gr(s, 0x30, &value);
1826         break;
1827     case CIRRUS_MMIO_BLTROP:
1828         cirrus_hook_read_gr(s, 0x32, &value);
1829         break;
1830     case CIRRUS_MMIO_BLTMODEEXT:
1831         cirrus_hook_read_gr(s, 0x33, &value);
1832         break;
1833     case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
1834         cirrus_hook_read_gr(s, 0x34, &value);
1835         break;
1836     case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
1837         cirrus_hook_read_gr(s, 0x35, &value);
1838         break;
1839     case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
1840         cirrus_hook_read_gr(s, 0x38, &value);
1841         break;
1842     case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
1843         cirrus_hook_read_gr(s, 0x39, &value);
1844         break;
1845     case CIRRUS_MMIO_BLTSTATUS:
1846         cirrus_hook_read_gr(s, 0x31, &value);
1847         break;
1848     default:
1849 #ifdef DEBUG_CIRRUS
1850         printf("cirrus: mmio read - address 0x%04x\n", address);
1851 #endif
1852         break;
1853     }
1854
1855     return (uint8_t) value;
1856 }
1857
1858 static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address,
1859                                   uint8_t value)
1860 {
1861     switch (address) {
1862     case (CIRRUS_MMIO_BLTBGCOLOR + 0):
1863         cirrus_hook_write_gr(s, 0x00, value);
1864         break;
1865     case (CIRRUS_MMIO_BLTBGCOLOR + 1):
1866         cirrus_hook_write_gr(s, 0x10, value);
1867         break;
1868     case (CIRRUS_MMIO_BLTBGCOLOR + 2):
1869         cirrus_hook_write_gr(s, 0x12, value);
1870         break;
1871     case (CIRRUS_MMIO_BLTBGCOLOR + 3):
1872         cirrus_hook_write_gr(s, 0x14, value);
1873         break;
1874     case (CIRRUS_MMIO_BLTFGCOLOR + 0):
1875         cirrus_hook_write_gr(s, 0x01, value);
1876         break;
1877     case (CIRRUS_MMIO_BLTFGCOLOR + 1):
1878         cirrus_hook_write_gr(s, 0x11, value);
1879         break;
1880     case (CIRRUS_MMIO_BLTFGCOLOR + 2):
1881         cirrus_hook_write_gr(s, 0x13, value);
1882         break;
1883     case (CIRRUS_MMIO_BLTFGCOLOR + 3):
1884         cirrus_hook_write_gr(s, 0x15, value);
1885         break;
1886     case (CIRRUS_MMIO_BLTWIDTH + 0):
1887         cirrus_hook_write_gr(s, 0x20, value);
1888         break;
1889     case (CIRRUS_MMIO_BLTWIDTH + 1):
1890         cirrus_hook_write_gr(s, 0x21, value);
1891         break;
1892     case (CIRRUS_MMIO_BLTHEIGHT + 0):
1893         cirrus_hook_write_gr(s, 0x22, value);
1894         break;
1895     case (CIRRUS_MMIO_BLTHEIGHT + 1):
1896         cirrus_hook_write_gr(s, 0x23, value);
1897         break;
1898     case (CIRRUS_MMIO_BLTDESTPITCH + 0):
1899         cirrus_hook_write_gr(s, 0x24, value);
1900         break;
1901     case (CIRRUS_MMIO_BLTDESTPITCH + 1):
1902         cirrus_hook_write_gr(s, 0x25, value);
1903         break;
1904     case (CIRRUS_MMIO_BLTSRCPITCH + 0):
1905         cirrus_hook_write_gr(s, 0x26, value);
1906         break;
1907     case (CIRRUS_MMIO_BLTSRCPITCH + 1):
1908         cirrus_hook_write_gr(s, 0x27, value);
1909         break;
1910     case (CIRRUS_MMIO_BLTDESTADDR + 0):
1911         cirrus_hook_write_gr(s, 0x28, value);
1912         break;
1913     case (CIRRUS_MMIO_BLTDESTADDR + 1):
1914         cirrus_hook_write_gr(s, 0x29, value);
1915         break;
1916     case (CIRRUS_MMIO_BLTDESTADDR + 2):
1917         cirrus_hook_write_gr(s, 0x2a, value);
1918         break;
1919     case (CIRRUS_MMIO_BLTDESTADDR + 3):
1920         /* ignored */
1921         break;
1922     case (CIRRUS_MMIO_BLTSRCADDR + 0):
1923         cirrus_hook_write_gr(s, 0x2c, value);
1924         break;
1925     case (CIRRUS_MMIO_BLTSRCADDR + 1):
1926         cirrus_hook_write_gr(s, 0x2d, value);
1927         break;
1928     case (CIRRUS_MMIO_BLTSRCADDR + 2):
1929         cirrus_hook_write_gr(s, 0x2e, value);
1930         break;
1931     case CIRRUS_MMIO_BLTWRITEMASK:
1932         cirrus_hook_write_gr(s, 0x2f, value);
1933         break;
1934     case CIRRUS_MMIO_BLTMODE:
1935         cirrus_hook_write_gr(s, 0x30, value);
1936         break;
1937     case CIRRUS_MMIO_BLTROP:
1938         cirrus_hook_write_gr(s, 0x32, value);
1939         break;
1940     case CIRRUS_MMIO_BLTMODEEXT:
1941         cirrus_hook_write_gr(s, 0x33, value);
1942         break;
1943     case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
1944         cirrus_hook_write_gr(s, 0x34, value);
1945         break;
1946     case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
1947         cirrus_hook_write_gr(s, 0x35, value);
1948         break;
1949     case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
1950         cirrus_hook_write_gr(s, 0x38, value);
1951         break;
1952     case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
1953         cirrus_hook_write_gr(s, 0x39, value);
1954         break;
1955     case CIRRUS_MMIO_BLTSTATUS:
1956         cirrus_hook_write_gr(s, 0x31, value);
1957         break;
1958     default:
1959 #ifdef DEBUG_CIRRUS
1960         printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n",
1961                address, value);
1962 #endif
1963         break;
1964     }
1965 }
1966
1967 /***************************************
1968  *
1969  *  write mode 4/5
1970  *
1971  * assume TARGET_PAGE_SIZE >= 16
1972  *
1973  ***************************************/
1974
1975 static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
1976                                              unsigned mode,
1977                                              unsigned offset,
1978                                              uint32_t mem_value)
1979 {
1980     int x;
1981     unsigned val = mem_value;
1982     uint8_t *dst;
1983
1984     dst = s->vram_ptr + offset;
1985     for (x = 0; x < 8; x++) {
1986         if (val & 0x80) {
1987             *dst++ = s->cirrus_shadow_gr1;
1988         } else if (mode == 5) {
1989             *dst++ = s->cirrus_shadow_gr0;
1990         }
1991         val <<= 1;
1992     }
1993     cpu_physical_memory_set_dirty(s->vram_offset + offset);
1994     cpu_physical_memory_set_dirty(s->vram_offset + offset + 7);
1995 }
1996
1997 static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
1998                                               unsigned mode,
1999                                               unsigned offset,
2000                                               uint32_t mem_value)
2001 {
2002     int x;
2003     unsigned val = mem_value;
2004     uint8_t *dst;
2005
2006     dst = s->vram_ptr + offset;
2007     for (x = 0; x < 8; x++) {
2008         if (val & 0x80) {
2009             *dst++ = s->cirrus_shadow_gr1;
2010             *dst++ = s->gr[0x11];
2011         } else if (mode == 5) {
2012             *dst++ = s->cirrus_shadow_gr0;
2013             *dst++ = s->gr[0x10];
2014         }
2015         val <<= 1;
2016     }
2017     cpu_physical_memory_set_dirty(s->vram_offset + offset);
2018     cpu_physical_memory_set_dirty(s->vram_offset + offset + 15);
2019 }
2020
2021 /***************************************
2022  *
2023  *  memory access between 0xa0000-0xbffff
2024  *
2025  ***************************************/
2026
2027 static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
2028 {
2029     CirrusVGAState *s = opaque;
2030     unsigned bank_index;
2031     unsigned bank_offset;
2032     uint32_t val;
2033
2034     if ((s->sr[0x07] & 0x01) == 0) {
2035         return vga_mem_readb(s, addr);
2036     }
2037
2038     addr &= 0x1ffff;
2039
2040     if (addr < 0x10000) {
2041         /* XXX handle bitblt */
2042         /* video memory */
2043         bank_index = addr >> 15;
2044         bank_offset = addr & 0x7fff;
2045         if (bank_offset < s->cirrus_bank_limit[bank_index]) {
2046             bank_offset += s->cirrus_bank_base[bank_index];
2047             if ((s->gr[0x0B] & 0x14) == 0x14) {
2048                 bank_offset <<= 4;
2049             } else if (s->gr[0x0B] & 0x02) {
2050                 bank_offset <<= 3;
2051             }
2052             bank_offset &= s->cirrus_addr_mask;
2053             val = *(s->vram_ptr + bank_offset);
2054         } else
2055             val = 0xff;
2056     } else if (addr >= 0x18000 && addr < 0x18100) {
2057         /* memory-mapped I/O */
2058         val = 0xff;
2059         if ((s->sr[0x17] & 0x44) == 0x04) {
2060             val = cirrus_mmio_blt_read(s, addr & 0xff);
2061         }
2062     } else {
2063         val = 0xff;
2064 #ifdef DEBUG_CIRRUS
2065         printf("cirrus: mem_readb %06x\n", addr);
2066 #endif
2067     }
2068     return val;
2069 }
2070
2071 static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
2072 {
2073     uint32_t v;
2074 #ifdef TARGET_WORDS_BIGENDIAN
2075     v = cirrus_vga_mem_readb(opaque, addr) << 8;
2076     v |= cirrus_vga_mem_readb(opaque, addr + 1);
2077 #else
2078     v = cirrus_vga_mem_readb(opaque, addr);
2079     v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
2080 #endif
2081     return v;
2082 }
2083
2084 static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
2085 {
2086     uint32_t v;
2087 #ifdef TARGET_WORDS_BIGENDIAN
2088     v = cirrus_vga_mem_readb(opaque, addr) << 24;
2089     v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16;
2090     v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8;
2091     v |= cirrus_vga_mem_readb(opaque, addr + 3);
2092 #else
2093     v = cirrus_vga_mem_readb(opaque, addr);
2094     v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
2095     v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
2096     v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
2097 #endif
2098     return v;
2099 }
2100
2101 static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, 
2102                                   uint32_t mem_value)
2103 {
2104     CirrusVGAState *s = opaque;
2105     unsigned bank_index;
2106     unsigned bank_offset;
2107     unsigned mode;
2108
2109     if ((s->sr[0x07] & 0x01) == 0) {
2110         vga_mem_writeb(s, addr, mem_value);
2111         return;
2112     }
2113
2114     addr &= 0x1ffff;
2115
2116     if (addr < 0x10000) {
2117         if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2118             /* bitblt */
2119             *s->cirrus_srcptr++ = (uint8_t) mem_value;
2120             if (s->cirrus_srcptr == s->cirrus_srcptr_end) {
2121                 cirrus_bitblt_cputovideo_next(s);
2122             }
2123         } else {
2124             /* video memory */
2125             bank_index = addr >> 15;
2126             bank_offset = addr & 0x7fff;
2127             if (bank_offset < s->cirrus_bank_limit[bank_index]) {
2128                 bank_offset += s->cirrus_bank_base[bank_index];
2129                 if ((s->gr[0x0B] & 0x14) == 0x14) {
2130                     bank_offset <<= 4;
2131                 } else if (s->gr[0x0B] & 0x02) {
2132                     bank_offset <<= 3;
2133                 }
2134                 bank_offset &= s->cirrus_addr_mask;
2135                 mode = s->gr[0x05] & 0x7;
2136                 if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2137                     *(s->vram_ptr + bank_offset) = mem_value;
2138                     cpu_physical_memory_set_dirty(s->vram_offset +
2139                                                   bank_offset);
2140                 } else {
2141                     if ((s->gr[0x0B] & 0x14) != 0x14) {
2142                         cirrus_mem_writeb_mode4and5_8bpp(s, mode,
2143                                                          bank_offset,
2144                                                          mem_value);
2145                     } else {
2146                         cirrus_mem_writeb_mode4and5_16bpp(s, mode,
2147                                                           bank_offset,
2148                                                           mem_value);
2149                     }
2150                 }
2151             }
2152         }
2153     } else if (addr >= 0x18000 && addr < 0x18100) {
2154         /* memory-mapped I/O */
2155         if ((s->sr[0x17] & 0x44) == 0x04) {
2156             cirrus_mmio_blt_write(s, addr & 0xff, mem_value);
2157         }
2158     } else {
2159 #ifdef DEBUG_CIRRUS
2160         printf("cirrus: mem_writeb %06x value %02x\n", addr, mem_value);
2161 #endif
2162     }
2163 }
2164
2165 static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2166 {
2167 #ifdef TARGET_WORDS_BIGENDIAN
2168     cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
2169     cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff);
2170 #else
2171     cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
2172     cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2173 #endif
2174 }
2175
2176 static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2177 {
2178 #ifdef TARGET_WORDS_BIGENDIAN
2179     cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
2180     cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2181     cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2182     cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff);
2183 #else
2184     cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
2185     cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2186     cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2187     cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2188 #endif
2189 }
2190
2191 static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = {
2192     cirrus_vga_mem_readb,
2193     cirrus_vga_mem_readw,
2194     cirrus_vga_mem_readl,
2195 };
2196
2197 static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = {
2198     cirrus_vga_mem_writeb,
2199     cirrus_vga_mem_writew,
2200     cirrus_vga_mem_writel,
2201 };
2202
2203 /***************************************
2204  *
2205  *  LFB memory access
2206  *
2207  ***************************************/
2208
2209 static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
2210 {
2211     CirrusVGAState *s = (CirrusVGAState *) opaque;
2212     uint32_t ret;
2213
2214     /* XXX: s->vram_size must be a power of two */
2215     addr &= s->cirrus_addr_mask;
2216
2217     if (((s->sr[0x17] & 0x44) == 0x44) && ((addr & 0x1fff00) == 0x1fff00)) {
2218         /* memory-mapped I/O */
2219         ret = cirrus_mmio_blt_read(s, addr & 0xff);
2220     } else if (0) {
2221         /* XXX handle bitblt */
2222         ret = 0xff;
2223     } else {
2224         /* video memory */
2225         if ((s->gr[0x0B] & 0x14) == 0x14) {
2226             addr <<= 4;
2227         } else if (s->gr[0x0B] & 0x02) {
2228             addr <<= 3;
2229         }
2230         addr &= s->cirrus_addr_mask;
2231         ret = *(s->vram_ptr + addr);
2232     }
2233
2234     return ret;
2235 }
2236
2237 static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
2238 {
2239     uint32_t v;
2240 #ifdef TARGET_WORDS_BIGENDIAN
2241     v = cirrus_linear_readb(opaque, addr) << 8;
2242     v |= cirrus_linear_readb(opaque, addr + 1);
2243 #else
2244     v = cirrus_linear_readb(opaque, addr);
2245     v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2246 #endif
2247     return v;
2248 }
2249
2250 static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
2251 {
2252     uint32_t v;
2253 #ifdef TARGET_WORDS_BIGENDIAN
2254     v = cirrus_linear_readb(opaque, addr) << 24;
2255     v |= cirrus_linear_readb(opaque, addr + 1) << 16;
2256     v |= cirrus_linear_readb(opaque, addr + 2) << 8;
2257     v |= cirrus_linear_readb(opaque, addr + 3);
2258 #else
2259     v = cirrus_linear_readb(opaque, addr);
2260     v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2261     v |= cirrus_linear_readb(opaque, addr + 2) << 16;
2262     v |= cirrus_linear_readb(opaque, addr + 3) << 24;
2263 #endif
2264     return v;
2265 }
2266
2267 static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
2268                                  uint32_t val)
2269 {
2270     CirrusVGAState *s = (CirrusVGAState *) opaque;
2271     unsigned mode;
2272
2273     addr &= s->cirrus_addr_mask;
2274
2275     if (((s->sr[0x17] & 0x44) == 0x44) && ((addr & 0x1fff00) == 0x1fff00)) {
2276         /* memory-mapped I/O */
2277         cirrus_mmio_blt_write(s, addr & 0xff, val);
2278     } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2279         /* bitblt */
2280         *s->cirrus_srcptr++ = (uint8_t) val;
2281         if (s->cirrus_srcptr == s->cirrus_srcptr_end) {
2282             cirrus_bitblt_cputovideo_next(s);
2283         }
2284     } else {
2285         /* video memory */
2286         if ((s->gr[0x0B] & 0x14) == 0x14) {
2287             addr <<= 4;
2288         } else if (s->gr[0x0B] & 0x02) {
2289             addr <<= 3;
2290         }
2291         addr &= s->cirrus_addr_mask;
2292
2293         mode = s->gr[0x05] & 0x7;
2294         if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2295             *(s->vram_ptr + addr) = (uint8_t) val;
2296             cpu_physical_memory_set_dirty(s->vram_offset + addr);
2297         } else {
2298             if ((s->gr[0x0B] & 0x14) != 0x14) {
2299                 cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
2300             } else {
2301                 cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val);
2302             }
2303         }
2304     }
2305 }
2306
2307 static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
2308                                  uint32_t val)
2309 {
2310 #ifdef TARGET_WORDS_BIGENDIAN
2311     cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff);
2312     cirrus_linear_writeb(opaque, addr + 1, val & 0xff);
2313 #else
2314     cirrus_linear_writeb(opaque, addr, val & 0xff);
2315     cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2316 #endif
2317 }
2318
2319 static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
2320                                  uint32_t val)
2321 {
2322 #ifdef TARGET_WORDS_BIGENDIAN
2323     cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff);
2324     cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2325     cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2326     cirrus_linear_writeb(opaque, addr + 3, val & 0xff);
2327 #else
2328     cirrus_linear_writeb(opaque, addr, val & 0xff);
2329     cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2330     cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2331     cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2332 #endif
2333 }
2334
2335
2336 static CPUReadMemoryFunc *cirrus_linear_read[3] = {
2337     cirrus_linear_readb,
2338     cirrus_linear_readw,
2339     cirrus_linear_readl,
2340 };
2341
2342 static CPUWriteMemoryFunc *cirrus_linear_write[3] = {
2343     cirrus_linear_writeb,
2344     cirrus_linear_writew,
2345     cirrus_linear_writel,
2346 };
2347
2348 /* I/O ports */
2349
2350 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
2351 {
2352     CirrusVGAState *s = opaque;
2353     int val, index;
2354
2355     /* check port range access depending on color/monochrome mode */
2356     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2357         || (addr >= 0x3d0 && addr <= 0x3df
2358             && !(s->msr & MSR_COLOR_EMULATION))) {
2359         val = 0xff;
2360     } else {
2361         switch (addr) {
2362         case 0x3c0:
2363             if (s->ar_flip_flop == 0) {
2364                 val = s->ar_index;
2365             } else {
2366                 val = 0;
2367             }
2368             break;
2369         case 0x3c1:
2370             index = s->ar_index & 0x1f;
2371             if (index < 21)
2372                 val = s->ar[index];
2373             else
2374                 val = 0;
2375             break;
2376         case 0x3c2:
2377             val = s->st00;
2378             break;
2379         case 0x3c4:
2380             val = s->sr_index;
2381             break;
2382         case 0x3c5:
2383             if (cirrus_hook_read_sr(s, s->sr_index, &val))
2384                 break;
2385             val = s->sr[s->sr_index];
2386 #ifdef DEBUG_VGA_REG
2387             printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
2388 #endif
2389             break;
2390         case 0x3c6:
2391             cirrus_read_hidden_dac(s, &val);
2392             break;
2393         case 0x3c7:
2394             val = s->dac_state;
2395             break;
2396         case 0x3c9:
2397             if (cirrus_hook_read_palette(s, &val))
2398                 break;
2399             val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
2400             if (++s->dac_sub_index == 3) {
2401                 s->dac_sub_index = 0;
2402                 s->dac_read_index++;
2403             }
2404             break;
2405         case 0x3ca:
2406             val = s->fcr;
2407             break;
2408         case 0x3cc:
2409             val = s->msr;
2410             break;
2411         case 0x3ce:
2412             val = s->gr_index;
2413             break;
2414         case 0x3cf:
2415             if (cirrus_hook_read_gr(s, s->gr_index, &val))
2416                 break;
2417             val = s->gr[s->gr_index];
2418 #ifdef DEBUG_VGA_REG
2419             printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
2420 #endif
2421             break;
2422         case 0x3b4:
2423         case 0x3d4:
2424             val = s->cr_index;
2425             break;
2426         case 0x3b5:
2427         case 0x3d5:
2428             if (cirrus_hook_read_cr(s, s->cr_index, &val))
2429                 break;
2430             val = s->cr[s->cr_index];
2431 #ifdef DEBUG_VGA_REG
2432             printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
2433 #endif
2434             break;
2435         case 0x3ba:
2436         case 0x3da:
2437             /* just toggle to fool polling */
2438             s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
2439             val = s->st01;
2440             s->ar_flip_flop = 0;
2441             break;
2442         default:
2443             val = 0x00;
2444             break;
2445         }
2446     }
2447 #if defined(DEBUG_VGA)
2448     printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
2449 #endif
2450     return val;
2451 }
2452
2453 static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2454 {
2455     CirrusVGAState *s = opaque;
2456     int index;
2457
2458     /* check port range access depending on color/monochrome mode */
2459     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2460         || (addr >= 0x3d0 && addr <= 0x3df
2461             && !(s->msr & MSR_COLOR_EMULATION)))
2462         return;
2463
2464 #ifdef DEBUG_VGA
2465     printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
2466 #endif
2467
2468     switch (addr) {
2469     case 0x3c0:
2470         if (s->ar_flip_flop == 0) {
2471             val &= 0x3f;
2472             s->ar_index = val;
2473         } else {
2474             index = s->ar_index & 0x1f;
2475             switch (index) {
2476             case 0x00 ... 0x0f:
2477                 s->ar[index] = val & 0x3f;
2478                 break;
2479             case 0x10:
2480                 s->ar[index] = val & ~0x10;
2481                 break;
2482             case 0x11:
2483                 s->ar[index] = val;
2484                 break;
2485             case 0x12:
2486                 s->ar[index] = val & ~0xc0;
2487                 break;
2488             case 0x13:
2489                 s->ar[index] = val & ~0xf0;
2490                 break;
2491             case 0x14:
2492                 s->ar[index] = val & ~0xf0;
2493                 break;
2494             default:
2495                 break;
2496             }
2497         }
2498         s->ar_flip_flop ^= 1;
2499         break;
2500     case 0x3c2:
2501         s->msr = val & ~0x10;
2502         break;
2503     case 0x3c4:
2504         s->sr_index = val;
2505         break;
2506     case 0x3c5:
2507         if (cirrus_hook_write_sr(s, s->sr_index, val))
2508             break;
2509 #ifdef DEBUG_VGA_REG
2510         printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
2511 #endif
2512         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
2513         break;
2514     case 0x3c6:
2515         cirrus_write_hidden_dac(s, val);
2516         break;
2517     case 0x3c7:
2518         s->dac_read_index = val;
2519         s->dac_sub_index = 0;
2520         s->dac_state = 3;
2521         break;
2522     case 0x3c8:
2523         s->dac_write_index = val;
2524         s->dac_sub_index = 0;
2525         s->dac_state = 0;
2526         break;
2527     case 0x3c9:
2528         if (cirrus_hook_write_palette(s, val))
2529             break;
2530         s->dac_cache[s->dac_sub_index] = val;
2531         if (++s->dac_sub_index == 3) {
2532             memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
2533             s->dac_sub_index = 0;
2534             s->dac_write_index++;
2535         }
2536         break;
2537     case 0x3ce:
2538         s->gr_index = val;
2539         break;
2540     case 0x3cf:
2541         if (cirrus_hook_write_gr(s, s->gr_index, val))
2542             break;
2543 #ifdef DEBUG_VGA_REG
2544         printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
2545 #endif
2546         s->gr[s->gr_index] = val & gr_mask[s->gr_index];
2547         break;
2548     case 0x3b4:
2549     case 0x3d4:
2550         s->cr_index = val;
2551         break;
2552     case 0x3b5:
2553     case 0x3d5:
2554         if (cirrus_hook_write_cr(s, s->cr_index, val))
2555             break;
2556 #ifdef DEBUG_VGA_REG
2557         printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
2558 #endif
2559         /* handle CR0-7 protection */
2560         if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
2561             /* can always write bit 4 of CR7 */
2562             if (s->cr_index == 7)
2563                 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
2564             return;
2565         }
2566         switch (s->cr_index) {
2567         case 0x01:              /* horizontal display end */
2568         case 0x07:
2569         case 0x09:
2570         case 0x0c:
2571         case 0x0d:
2572         case 0x12:              /* veritcal display end */
2573             s->cr[s->cr_index] = val;
2574             break;
2575
2576         default:
2577             s->cr[s->cr_index] = val;
2578             break;
2579         }
2580         break;
2581     case 0x3ba:
2582     case 0x3da:
2583         s->fcr = val & 0x10;
2584         break;
2585     }
2586 }
2587
2588 /***************************************
2589  *
2590  *  memory-mapped I/O access
2591  *
2592  ***************************************/
2593
2594 static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
2595 {
2596     CirrusVGAState *s = (CirrusVGAState *) opaque;
2597
2598     addr &= CIRRUS_PNPMMIO_SIZE - 1;
2599
2600     if (addr >= 0x100) {
2601         return cirrus_mmio_blt_read(s, addr - 0x100);
2602     } else {
2603         return vga_ioport_read(s, addr + 0x3c0);
2604     }
2605 }
2606
2607 static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
2608 {
2609     uint32_t v;
2610 #ifdef TARGET_WORDS_BIGENDIAN
2611     v = cirrus_mmio_readb(opaque, addr) << 8;
2612     v |= cirrus_mmio_readb(opaque, addr + 1);
2613 #else
2614     v = cirrus_mmio_readb(opaque, addr);
2615     v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
2616 #endif
2617     return v;
2618 }
2619
2620 static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
2621 {
2622     uint32_t v;
2623 #ifdef TARGET_WORDS_BIGENDIAN
2624     v = cirrus_mmio_readb(opaque, addr) << 24;
2625     v |= cirrus_mmio_readb(opaque, addr + 1) << 16;
2626     v |= cirrus_mmio_readb(opaque, addr + 2) << 8;
2627     v |= cirrus_mmio_readb(opaque, addr + 3);
2628 #else
2629     v = cirrus_mmio_readb(opaque, addr);
2630     v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
2631     v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
2632     v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
2633 #endif
2634     return v;
2635 }
2636
2637 static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
2638                                uint32_t val)
2639 {
2640     CirrusVGAState *s = (CirrusVGAState *) opaque;
2641
2642     addr &= CIRRUS_PNPMMIO_SIZE - 1;
2643
2644     if (addr >= 0x100) {
2645         cirrus_mmio_blt_write(s, addr - 0x100, val);
2646     } else {
2647         vga_ioport_write(s, addr + 0x3c0, val);
2648     }
2649 }
2650
2651 static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
2652                                uint32_t val)
2653 {
2654 #ifdef TARGET_WORDS_BIGENDIAN
2655     cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff);
2656     cirrus_mmio_writeb(opaque, addr + 1, val & 0xff);
2657 #else
2658     cirrus_mmio_writeb(opaque, addr, val & 0xff);
2659     cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2660 #endif
2661 }
2662
2663 static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
2664                                uint32_t val)
2665 {
2666 #ifdef TARGET_WORDS_BIGENDIAN
2667     cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff);
2668     cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2669     cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2670     cirrus_mmio_writeb(opaque, addr + 3, val & 0xff);
2671 #else
2672     cirrus_mmio_writeb(opaque, addr, val & 0xff);
2673     cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2674     cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2675     cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2676 #endif
2677 }
2678
2679
2680 static CPUReadMemoryFunc *cirrus_mmio_read[3] = {
2681     cirrus_mmio_readb,
2682     cirrus_mmio_readw,
2683     cirrus_mmio_readl,
2684 };
2685
2686 static CPUWriteMemoryFunc *cirrus_mmio_write[3] = {
2687     cirrus_mmio_writeb,
2688     cirrus_mmio_writew,
2689     cirrus_mmio_writel,
2690 };
2691
2692 /***************************************
2693  *
2694  *  initialize
2695  *
2696  ***************************************/
2697
2698 static void cirrus_init_common(CirrusVGAState * s)
2699 {
2700     int vga_io_memory;
2701
2702     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2703
2704     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2705     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2706     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2707     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2708
2709     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2710
2711     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2712     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2713     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2714     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2715
2716     vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read, 
2717                                            cirrus_vga_mem_write, s);
2718     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
2719                                  vga_io_memory);
2720
2721     s->sr[0x06] = 0x0f;
2722     s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
2723     s->sr[0x1F] = 0x22;         // MemClock
2724
2725     s->cr[0x27] = CIRRUS_ID;
2726
2727     s->cirrus_hidden_dac_lockindex = 5;
2728     s->cirrus_hidden_dac_data = 0;
2729
2730     /* I/O handler for LFB */
2731     s->cirrus_linear_io_addr =
2732         cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write,
2733                                s);
2734     /* I/O handler for memory-mapped I/O */
2735     s->cirrus_mmio_io_addr =
2736         cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s);
2737
2738     /* XXX: s->vram_size must be a power of two */
2739     s->cirrus_addr_mask = s->vram_size - 1;
2740
2741     s->get_bpp = cirrus_get_bpp;
2742     s->get_offsets = cirrus_get_offsets;
2743 }
2744
2745 /***************************************
2746  *
2747  *  ISA bus support
2748  *
2749  ***************************************/
2750
2751 void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
2752                          unsigned long vga_ram_offset, int vga_ram_size)
2753 {
2754     CirrusVGAState *s;
2755
2756     s = qemu_mallocz(sizeof(CirrusVGAState));
2757     
2758     vga_common_init((VGAState *)s, 
2759                     ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2760     cirrus_init_common(s);
2761     s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
2762     /* XXX ISA-LFB support */
2763 }
2764
2765 /***************************************
2766  *
2767  *  PCI bus support
2768  *
2769  ***************************************/
2770
2771 static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
2772                                uint32_t addr, uint32_t size, int type)
2773 {
2774     CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
2775
2776     cpu_register_physical_memory(addr, s->vram_size,
2777                                  s->cirrus_linear_io_addr);
2778 }
2779
2780 static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
2781                                 uint32_t addr, uint32_t size, int type)
2782 {
2783     CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
2784
2785     cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
2786                                  s->cirrus_mmio_io_addr);
2787 }
2788
2789 void pci_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
2790                          unsigned long vga_ram_offset, int vga_ram_size)
2791 {
2792     PCICirrusVGAState *d;
2793     uint8_t *pci_conf;
2794     CirrusVGAState *s;
2795
2796     /* setup PCI configuration registers */
2797     d = (PCICirrusVGAState *)pci_register_device("Cirrus VGA", 
2798                                                  sizeof(PCICirrusVGAState), 
2799                                                  0, -1, NULL, NULL);
2800     pci_conf = d->dev.config;
2801     pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
2802     pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8);
2803     pci_conf[0x02] = (uint8_t) (PCI_DEVICE_ID & 0xff);
2804     pci_conf[0x03] = (uint8_t) (PCI_DEVICE_ID >> 8);
2805     pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
2806     pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
2807     pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
2808     pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
2809
2810     /* setup VGA */
2811     s = &d->cirrus_vga;
2812     vga_common_init((VGAState *)s, 
2813                     ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2814     cirrus_init_common(s);
2815     s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
2816
2817     /* setup memory space */
2818     /* memory #0 LFB */
2819     /* memory #1 memory-mapped I/O */
2820     /* XXX: s->vram_size must be a power of two */
2821     pci_register_io_region((PCIDevice *)d, 0, s->vram_size,
2822                            PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
2823     if (CIRRUS_ID == CIRRUS_ID_CLGD5446) {
2824         pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
2825                                PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
2826     }
2827     /* XXX: ROM BIOS */
2828 }