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