ia64/xen-unstable

view tools/ioemu/hw/cirrus_vga.c @ 16197:b3fa9b58a102

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