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