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