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