ia64/xen-unstable

view tools/ioemu/hw/cirrus_vga.c @ 6946:e703abaf6e3d

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