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