149ab747fSPaolo Bonzini /*
249ab747fSPaolo Bonzini * QEMU Cirrus CLGD 54xx VGA Emulator.
349ab747fSPaolo Bonzini *
449ab747fSPaolo Bonzini * Copyright (c) 2004 Fabrice Bellard
549ab747fSPaolo Bonzini * Copyright (c) 2004 Makoto Suzuki (suzu)
649ab747fSPaolo Bonzini *
749ab747fSPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy
849ab747fSPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal
949ab747fSPaolo Bonzini * in the Software without restriction, including without limitation the rights
1049ab747fSPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1149ab747fSPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is
1249ab747fSPaolo Bonzini * furnished to do so, subject to the following conditions:
1349ab747fSPaolo Bonzini *
1449ab747fSPaolo Bonzini * The above copyright notice and this permission notice shall be included in
1549ab747fSPaolo Bonzini * all copies or substantial portions of the Software.
1649ab747fSPaolo Bonzini *
1749ab747fSPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1849ab747fSPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1949ab747fSPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2049ab747fSPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2149ab747fSPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2249ab747fSPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2349ab747fSPaolo Bonzini * THE SOFTWARE.
2449ab747fSPaolo Bonzini */
2549ab747fSPaolo Bonzini /*
2629585468SPhilippe Mathieu-Daudé * Reference: Finn Thogersons' VGADOC4b:
2729585468SPhilippe Mathieu-Daudé *
2829585468SPhilippe Mathieu-Daudé * http://web.archive.org/web/20021019054927/http://home.worldonline.dk/finth/
2929585468SPhilippe Mathieu-Daudé *
3029585468SPhilippe Mathieu-Daudé * VGADOC4b.ZIP content available at:
3129585468SPhilippe Mathieu-Daudé *
3229585468SPhilippe Mathieu-Daudé * https://pdos.csail.mit.edu/6.828/2005/readings/hardware/vgadoc
3349ab747fSPaolo Bonzini */
340b8fa32fSMarkus Armbruster
3547df5154SPeter Maydell #include "qemu/osdep.h"
360b8fa32fSMarkus Armbruster #include "qemu/module.h"
37f0353b0dSPhilippe Mathieu-Daudé #include "qemu/units.h"
38bb6e9e94SPhilippe Mathieu-Daudé #include "qemu/log.h"
3971e8a915SMarkus Armbruster #include "sysemu/reset.h"
40da34e65cSMarkus Armbruster #include "qapi/error.h"
41ec87f206SGerd Hoffmann #include "trace.h"
42edf5ca5dSMarkus Armbruster #include "hw/pci/pci_device.h"
43a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
44d6454270SMarkus Armbruster #include "migration/vmstate.h"
45d3c2343aSBenjamin Herrenschmidt #include "ui/pixel_ops.h"
46*973a724eSPaolo Bonzini #include "vga_regs.h"
47ce3cf70eSThomas Huth #include "cirrus_vga_internal.h"
48db1015e9SEduardo Habkost #include "qom/object.h"
4928cf3960SMichael S. Tsirkin #include "ui/console.h"
5049ab747fSPaolo Bonzini
5149ab747fSPaolo Bonzini /*
5249ab747fSPaolo Bonzini * TODO:
5349ab747fSPaolo Bonzini * - destination write mask support not complete (bits 5..7)
5449ab747fSPaolo Bonzini * - optimize linear mappings
5549ab747fSPaolo Bonzini * - optimize bitblt functions
5649ab747fSPaolo Bonzini */
5749ab747fSPaolo Bonzini
5849ab747fSPaolo Bonzini //#define DEBUG_CIRRUS
5949ab747fSPaolo Bonzini
6049ab747fSPaolo Bonzini /***************************************
6149ab747fSPaolo Bonzini *
6249ab747fSPaolo Bonzini * definitions
6349ab747fSPaolo Bonzini *
6449ab747fSPaolo Bonzini ***************************************/
6549ab747fSPaolo Bonzini
6649ab747fSPaolo Bonzini // sequencer 0x07
6749ab747fSPaolo Bonzini #define CIRRUS_SR7_BPP_VGA 0x00
6849ab747fSPaolo Bonzini #define CIRRUS_SR7_BPP_SVGA 0x01
6949ab747fSPaolo Bonzini #define CIRRUS_SR7_BPP_MASK 0x0e
7049ab747fSPaolo Bonzini #define CIRRUS_SR7_BPP_8 0x00
7149ab747fSPaolo Bonzini #define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02
7249ab747fSPaolo Bonzini #define CIRRUS_SR7_BPP_24 0x04
7349ab747fSPaolo Bonzini #define CIRRUS_SR7_BPP_16 0x06
7449ab747fSPaolo Bonzini #define CIRRUS_SR7_BPP_32 0x08
7549ab747fSPaolo Bonzini #define CIRRUS_SR7_ISAADDR_MASK 0xe0
7649ab747fSPaolo Bonzini
7749ab747fSPaolo Bonzini // sequencer 0x0f
7849ab747fSPaolo Bonzini #define CIRRUS_MEMSIZE_512k 0x08
7949ab747fSPaolo Bonzini #define CIRRUS_MEMSIZE_1M 0x10
8049ab747fSPaolo Bonzini #define CIRRUS_MEMSIZE_2M 0x18
8149ab747fSPaolo Bonzini #define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled.
8249ab747fSPaolo Bonzini
8349ab747fSPaolo Bonzini // sequencer 0x12
8449ab747fSPaolo Bonzini #define CIRRUS_CURSOR_SHOW 0x01
8549ab747fSPaolo Bonzini #define CIRRUS_CURSOR_HIDDENPEL 0x02
8649ab747fSPaolo Bonzini #define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear
8749ab747fSPaolo Bonzini
8849ab747fSPaolo Bonzini // sequencer 0x17
8949ab747fSPaolo Bonzini #define CIRRUS_BUSTYPE_VLBFAST 0x10
9049ab747fSPaolo Bonzini #define CIRRUS_BUSTYPE_PCI 0x20
9149ab747fSPaolo Bonzini #define CIRRUS_BUSTYPE_VLBSLOW 0x30
9249ab747fSPaolo Bonzini #define CIRRUS_BUSTYPE_ISA 0x38
9349ab747fSPaolo Bonzini #define CIRRUS_MMIO_ENABLE 0x04
9449ab747fSPaolo Bonzini #define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared.
9549ab747fSPaolo Bonzini #define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
9649ab747fSPaolo Bonzini
9749ab747fSPaolo Bonzini // control 0x0b
9849ab747fSPaolo Bonzini #define CIRRUS_BANKING_DUAL 0x01
9949ab747fSPaolo Bonzini #define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k
10049ab747fSPaolo Bonzini
10149ab747fSPaolo Bonzini // control 0x30
10249ab747fSPaolo Bonzini #define CIRRUS_BLTMODE_BACKWARDS 0x01
10349ab747fSPaolo Bonzini #define CIRRUS_BLTMODE_MEMSYSDEST 0x02
10449ab747fSPaolo Bonzini #define CIRRUS_BLTMODE_MEMSYSSRC 0x04
10549ab747fSPaolo Bonzini #define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08
10649ab747fSPaolo Bonzini #define CIRRUS_BLTMODE_PATTERNCOPY 0x40
10749ab747fSPaolo Bonzini #define CIRRUS_BLTMODE_COLOREXPAND 0x80
10849ab747fSPaolo Bonzini #define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30
10949ab747fSPaolo Bonzini #define CIRRUS_BLTMODE_PIXELWIDTH8 0x00
11049ab747fSPaolo Bonzini #define CIRRUS_BLTMODE_PIXELWIDTH16 0x10
11149ab747fSPaolo Bonzini #define CIRRUS_BLTMODE_PIXELWIDTH24 0x20
11249ab747fSPaolo Bonzini #define CIRRUS_BLTMODE_PIXELWIDTH32 0x30
11349ab747fSPaolo Bonzini
11449ab747fSPaolo Bonzini // control 0x31
11549ab747fSPaolo Bonzini #define CIRRUS_BLT_BUSY 0x01
11649ab747fSPaolo Bonzini #define CIRRUS_BLT_START 0x02
11749ab747fSPaolo Bonzini #define CIRRUS_BLT_RESET 0x04
11849ab747fSPaolo Bonzini #define CIRRUS_BLT_FIFOUSED 0x10
11949ab747fSPaolo Bonzini #define CIRRUS_BLT_AUTOSTART 0x80
12049ab747fSPaolo Bonzini
12149ab747fSPaolo Bonzini // control 0x32
12249ab747fSPaolo Bonzini #define CIRRUS_ROP_0 0x00
12349ab747fSPaolo Bonzini #define CIRRUS_ROP_SRC_AND_DST 0x05
12449ab747fSPaolo Bonzini #define CIRRUS_ROP_NOP 0x06
12549ab747fSPaolo Bonzini #define CIRRUS_ROP_SRC_AND_NOTDST 0x09
12649ab747fSPaolo Bonzini #define CIRRUS_ROP_NOTDST 0x0b
12749ab747fSPaolo Bonzini #define CIRRUS_ROP_SRC 0x0d
12849ab747fSPaolo Bonzini #define CIRRUS_ROP_1 0x0e
12949ab747fSPaolo Bonzini #define CIRRUS_ROP_NOTSRC_AND_DST 0x50
13049ab747fSPaolo Bonzini #define CIRRUS_ROP_SRC_XOR_DST 0x59
13149ab747fSPaolo Bonzini #define CIRRUS_ROP_SRC_OR_DST 0x6d
13249ab747fSPaolo Bonzini #define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90
13349ab747fSPaolo Bonzini #define CIRRUS_ROP_SRC_NOTXOR_DST 0x95
13449ab747fSPaolo Bonzini #define CIRRUS_ROP_SRC_OR_NOTDST 0xad
13549ab747fSPaolo Bonzini #define CIRRUS_ROP_NOTSRC 0xd0
13649ab747fSPaolo Bonzini #define CIRRUS_ROP_NOTSRC_OR_DST 0xd6
13749ab747fSPaolo Bonzini #define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda
13849ab747fSPaolo Bonzini
13949ab747fSPaolo Bonzini #define CIRRUS_ROP_NOP_INDEX 2
14049ab747fSPaolo Bonzini #define CIRRUS_ROP_SRC_INDEX 5
14149ab747fSPaolo Bonzini
14249ab747fSPaolo Bonzini // control 0x33
14349ab747fSPaolo Bonzini #define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04
14449ab747fSPaolo Bonzini #define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02
14549ab747fSPaolo Bonzini #define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01
14649ab747fSPaolo Bonzini
14749ab747fSPaolo Bonzini // memory-mapped IO
14849ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword
14949ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword
15049ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTWIDTH 0x08 // word
15149ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTHEIGHT 0x0a // word
15249ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word
15349ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word
15449ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword
15549ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword
15649ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte
15749ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTMODE 0x18 // byte
15849ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTROP 0x1a // byte
15949ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte
16049ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c // word?
16149ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word?
16249ab747fSPaolo Bonzini #define CIRRUS_MMIO_LINEARDRAW_START_X 0x24 // word
16349ab747fSPaolo Bonzini #define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26 // word
16449ab747fSPaolo Bonzini #define CIRRUS_MMIO_LINEARDRAW_END_X 0x28 // word
16549ab747fSPaolo Bonzini #define CIRRUS_MMIO_LINEARDRAW_END_Y 0x2a // word
16649ab747fSPaolo Bonzini #define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c // byte
16749ab747fSPaolo Bonzini #define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d // byte
16849ab747fSPaolo Bonzini #define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e // byte
16949ab747fSPaolo Bonzini #define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f // byte
17049ab747fSPaolo Bonzini #define CIRRUS_MMIO_BRESENHAM_K1 0x30 // word
17149ab747fSPaolo Bonzini #define CIRRUS_MMIO_BRESENHAM_K3 0x32 // word
17249ab747fSPaolo Bonzini #define CIRRUS_MMIO_BRESENHAM_ERROR 0x34 // word
17349ab747fSPaolo Bonzini #define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36 // word
17449ab747fSPaolo Bonzini #define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38 // byte
17549ab747fSPaolo Bonzini #define CIRRUS_MMIO_LINEDRAW_MODE 0x39 // byte
17649ab747fSPaolo Bonzini #define CIRRUS_MMIO_BLTSTATUS 0x40 // byte
17749ab747fSPaolo Bonzini
17849ab747fSPaolo Bonzini #define CIRRUS_PNPMMIO_SIZE 0x1000
17949ab747fSPaolo Bonzini
18049ab747fSPaolo Bonzini typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
181026aeffcSGerd Hoffmann uint32_t dstaddr, int dst_pitch,
182026aeffcSGerd Hoffmann int width, int height);
18349ab747fSPaolo Bonzini
184db1015e9SEduardo Habkost struct PCICirrusVGAState {
18549ab747fSPaolo Bonzini PCIDevice dev;
18649ab747fSPaolo Bonzini CirrusVGAState cirrus_vga;
187db1015e9SEduardo Habkost };
18849ab747fSPaolo Bonzini
189d338bae3SGonglei #define TYPE_PCI_CIRRUS_VGA "cirrus-vga"
1908063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(PCICirrusVGAState, PCI_CIRRUS_VGA)
191d338bae3SGonglei
19249ab747fSPaolo Bonzini static uint8_t rop_to_index[256];
19349ab747fSPaolo Bonzini
19449ab747fSPaolo Bonzini /***************************************
19549ab747fSPaolo Bonzini *
19649ab747fSPaolo Bonzini * prototypes.
19749ab747fSPaolo Bonzini *
19849ab747fSPaolo Bonzini ***************************************/
19949ab747fSPaolo Bonzini
20049ab747fSPaolo Bonzini
20149ab747fSPaolo Bonzini static void cirrus_bitblt_reset(CirrusVGAState *s);
20249ab747fSPaolo Bonzini static void cirrus_update_memory_access(CirrusVGAState *s);
20349ab747fSPaolo Bonzini
20449ab747fSPaolo Bonzini /***************************************
20549ab747fSPaolo Bonzini *
20649ab747fSPaolo Bonzini * raster operations
20749ab747fSPaolo Bonzini *
20849ab747fSPaolo Bonzini ***************************************/
20949ab747fSPaolo Bonzini
blit_region_is_unsafe(struct CirrusVGAState * s,int32_t pitch,int32_t addr)210d3532a0dSGerd Hoffmann static bool blit_region_is_unsafe(struct CirrusVGAState *s,
211d3532a0dSGerd Hoffmann int32_t pitch, int32_t addr)
212d3532a0dSGerd Hoffmann {
21312e97ec3SGerd Hoffmann if (!pitch) {
21412e97ec3SGerd Hoffmann return true;
21512e97ec3SGerd Hoffmann }
216d3532a0dSGerd Hoffmann if (pitch < 0) {
217d3532a0dSGerd Hoffmann int64_t min = addr
21862d4c6bdSLi Qiang + ((int64_t)s->cirrus_blt_height - 1) * pitch
21962d4c6bdSLi Qiang - s->cirrus_blt_width;
22062d4c6bdSLi Qiang if (min < -1 || addr >= s->vga.vram_size) {
221d3532a0dSGerd Hoffmann return true;
222d3532a0dSGerd Hoffmann }
223d3532a0dSGerd Hoffmann } else {
224d3532a0dSGerd Hoffmann int64_t max = addr
225d3532a0dSGerd Hoffmann + ((int64_t)s->cirrus_blt_height-1) * pitch
226d3532a0dSGerd Hoffmann + s->cirrus_blt_width;
227d2ba7ecbSPaolo Bonzini if (max > s->vga.vram_size) {
228d3532a0dSGerd Hoffmann return true;
229d3532a0dSGerd Hoffmann }
230d3532a0dSGerd Hoffmann }
231d3532a0dSGerd Hoffmann return false;
232d3532a0dSGerd Hoffmann }
233d3532a0dSGerd Hoffmann
blit_is_unsafe(struct CirrusVGAState * s,bool dst_only)23412e97ec3SGerd Hoffmann static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only)
235d3532a0dSGerd Hoffmann {
236d3532a0dSGerd Hoffmann /* should be the case, see cirrus_bitblt_start */
237d3532a0dSGerd Hoffmann assert(s->cirrus_blt_width > 0);
238d3532a0dSGerd Hoffmann assert(s->cirrus_blt_height > 0);
239d3532a0dSGerd Hoffmann
240bf259833SGerd Hoffmann if (s->cirrus_blt_width > CIRRUS_BLTBUFSIZE) {
241bf259833SGerd Hoffmann return true;
242bf259833SGerd Hoffmann }
243bf259833SGerd Hoffmann
244d3532a0dSGerd Hoffmann if (blit_region_is_unsafe(s, s->cirrus_blt_dstpitch,
24560cd23e8SGerd Hoffmann s->cirrus_blt_dstaddr)) {
246d3532a0dSGerd Hoffmann return true;
247d3532a0dSGerd Hoffmann }
248913a8788SBruce Rogers if (dst_only) {
249913a8788SBruce Rogers return false;
250913a8788SBruce Rogers }
25112e97ec3SGerd Hoffmann if (blit_region_is_unsafe(s, s->cirrus_blt_srcpitch,
25260cd23e8SGerd Hoffmann s->cirrus_blt_srcaddr)) {
253d3532a0dSGerd Hoffmann return true;
254d3532a0dSGerd Hoffmann }
255d3532a0dSGerd Hoffmann
256d3532a0dSGerd Hoffmann return false;
257d3532a0dSGerd Hoffmann }
258d3532a0dSGerd Hoffmann
cirrus_bitblt_rop_nop(CirrusVGAState * s,uint32_t dstaddr,uint32_t srcaddr,int dstpitch,int srcpitch,int bltwidth,int bltheight)25949ab747fSPaolo Bonzini static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
260ffaf8577SGerd Hoffmann uint32_t dstaddr, uint32_t srcaddr,
26149ab747fSPaolo Bonzini int dstpitch,int srcpitch,
26249ab747fSPaolo Bonzini int bltwidth,int bltheight)
26349ab747fSPaolo Bonzini {
26449ab747fSPaolo Bonzini }
26549ab747fSPaolo Bonzini
cirrus_bitblt_fill_nop(CirrusVGAState * s,uint32_t dstaddr,int dstpitch,int bltwidth,int bltheight)26649ab747fSPaolo Bonzini static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
267026aeffcSGerd Hoffmann uint32_t dstaddr,
26849ab747fSPaolo Bonzini int dstpitch, int bltwidth,int bltheight)
26949ab747fSPaolo Bonzini {
27049ab747fSPaolo Bonzini }
27149ab747fSPaolo Bonzini
cirrus_src(CirrusVGAState * s,uint32_t srcaddr)272ffaf8577SGerd Hoffmann static inline uint8_t cirrus_src(CirrusVGAState *s, uint32_t srcaddr)
273ffaf8577SGerd Hoffmann {
274ffaf8577SGerd Hoffmann if (s->cirrus_srccounter) {
275ffaf8577SGerd Hoffmann /* cputovideo */
276ffaf8577SGerd Hoffmann return s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1)];
277ffaf8577SGerd Hoffmann } else {
278ffaf8577SGerd Hoffmann /* videotovideo */
279ffaf8577SGerd Hoffmann return s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask];
280ffaf8577SGerd Hoffmann }
281ffaf8577SGerd Hoffmann }
282ffaf8577SGerd Hoffmann
cirrus_src16(CirrusVGAState * s,uint32_t srcaddr)283ffaf8577SGerd Hoffmann static inline uint16_t cirrus_src16(CirrusVGAState *s, uint32_t srcaddr)
284ffaf8577SGerd Hoffmann {
285ffaf8577SGerd Hoffmann uint16_t *src;
286ffaf8577SGerd Hoffmann
287ffaf8577SGerd Hoffmann if (s->cirrus_srccounter) {
288ffaf8577SGerd Hoffmann /* cputovideo */
289ffaf8577SGerd Hoffmann src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~1];
290ffaf8577SGerd Hoffmann } else {
291ffaf8577SGerd Hoffmann /* videotovideo */
292ffaf8577SGerd Hoffmann src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~1];
293ffaf8577SGerd Hoffmann }
294ffaf8577SGerd Hoffmann return *src;
295ffaf8577SGerd Hoffmann }
296ffaf8577SGerd Hoffmann
cirrus_src32(CirrusVGAState * s,uint32_t srcaddr)297ffaf8577SGerd Hoffmann static inline uint32_t cirrus_src32(CirrusVGAState *s, uint32_t srcaddr)
298ffaf8577SGerd Hoffmann {
299ffaf8577SGerd Hoffmann uint32_t *src;
300ffaf8577SGerd Hoffmann
301ffaf8577SGerd Hoffmann if (s->cirrus_srccounter) {
302ffaf8577SGerd Hoffmann /* cputovideo */
303ffaf8577SGerd Hoffmann src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~3];
304ffaf8577SGerd Hoffmann } else {
305ffaf8577SGerd Hoffmann /* videotovideo */
306ffaf8577SGerd Hoffmann src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~3];
307ffaf8577SGerd Hoffmann }
308ffaf8577SGerd Hoffmann return *src;
309ffaf8577SGerd Hoffmann }
310ffaf8577SGerd Hoffmann
31149ab747fSPaolo Bonzini #define ROP_NAME 0
31249ab747fSPaolo Bonzini #define ROP_FN(d, s) 0
31347b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
31449ab747fSPaolo Bonzini
31549ab747fSPaolo Bonzini #define ROP_NAME src_and_dst
31649ab747fSPaolo Bonzini #define ROP_FN(d, s) (s) & (d)
31747b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
31849ab747fSPaolo Bonzini
31949ab747fSPaolo Bonzini #define ROP_NAME src_and_notdst
32049ab747fSPaolo Bonzini #define ROP_FN(d, s) (s) & (~(d))
32147b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
32249ab747fSPaolo Bonzini
32349ab747fSPaolo Bonzini #define ROP_NAME notdst
32449ab747fSPaolo Bonzini #define ROP_FN(d, s) ~(d)
32547b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
32649ab747fSPaolo Bonzini
32749ab747fSPaolo Bonzini #define ROP_NAME src
32849ab747fSPaolo Bonzini #define ROP_FN(d, s) s
32947b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
33049ab747fSPaolo Bonzini
33149ab747fSPaolo Bonzini #define ROP_NAME 1
33249ab747fSPaolo Bonzini #define ROP_FN(d, s) ~0
33347b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
33449ab747fSPaolo Bonzini
33549ab747fSPaolo Bonzini #define ROP_NAME notsrc_and_dst
33649ab747fSPaolo Bonzini #define ROP_FN(d, s) (~(s)) & (d)
33747b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
33849ab747fSPaolo Bonzini
33949ab747fSPaolo Bonzini #define ROP_NAME src_xor_dst
34049ab747fSPaolo Bonzini #define ROP_FN(d, s) (s) ^ (d)
34147b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
34249ab747fSPaolo Bonzini
34349ab747fSPaolo Bonzini #define ROP_NAME src_or_dst
34449ab747fSPaolo Bonzini #define ROP_FN(d, s) (s) | (d)
34547b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
34649ab747fSPaolo Bonzini
34749ab747fSPaolo Bonzini #define ROP_NAME notsrc_or_notdst
34849ab747fSPaolo Bonzini #define ROP_FN(d, s) (~(s)) | (~(d))
34947b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
35049ab747fSPaolo Bonzini
35149ab747fSPaolo Bonzini #define ROP_NAME src_notxor_dst
35249ab747fSPaolo Bonzini #define ROP_FN(d, s) ~((s) ^ (d))
35347b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
35449ab747fSPaolo Bonzini
35549ab747fSPaolo Bonzini #define ROP_NAME src_or_notdst
35649ab747fSPaolo Bonzini #define ROP_FN(d, s) (s) | (~(d))
35747b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
35849ab747fSPaolo Bonzini
35949ab747fSPaolo Bonzini #define ROP_NAME notsrc
36049ab747fSPaolo Bonzini #define ROP_FN(d, s) (~(s))
36147b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
36249ab747fSPaolo Bonzini
36349ab747fSPaolo Bonzini #define ROP_NAME notsrc_or_dst
36449ab747fSPaolo Bonzini #define ROP_FN(d, s) (~(s)) | (d)
36547b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
36649ab747fSPaolo Bonzini
36749ab747fSPaolo Bonzini #define ROP_NAME notsrc_and_notdst
36849ab747fSPaolo Bonzini #define ROP_FN(d, s) (~(s)) & (~(d))
36947b43a1fSPaolo Bonzini #include "cirrus_vga_rop.h"
37049ab747fSPaolo Bonzini
37149ab747fSPaolo Bonzini static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = {
37249ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_0,
37349ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_src_and_dst,
37449ab747fSPaolo Bonzini cirrus_bitblt_rop_nop,
37549ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_src_and_notdst,
37649ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_notdst,
37749ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_src,
37849ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_1,
37949ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_notsrc_and_dst,
38049ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_src_xor_dst,
38149ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_src_or_dst,
38249ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_notsrc_or_notdst,
38349ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_src_notxor_dst,
38449ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_src_or_notdst,
38549ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_notsrc,
38649ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_notsrc_or_dst,
38749ab747fSPaolo Bonzini cirrus_bitblt_rop_fwd_notsrc_and_notdst,
38849ab747fSPaolo Bonzini };
38949ab747fSPaolo Bonzini
39049ab747fSPaolo Bonzini static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = {
39149ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_0,
39249ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_src_and_dst,
39349ab747fSPaolo Bonzini cirrus_bitblt_rop_nop,
39449ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_src_and_notdst,
39549ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_notdst,
39649ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_src,
39749ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_1,
39849ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_notsrc_and_dst,
39949ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_src_xor_dst,
40049ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_src_or_dst,
40149ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_notsrc_or_notdst,
40249ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_src_notxor_dst,
40349ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_src_or_notdst,
40449ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_notsrc,
40549ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_notsrc_or_dst,
40649ab747fSPaolo Bonzini cirrus_bitblt_rop_bkwd_notsrc_and_notdst,
40749ab747fSPaolo Bonzini };
40849ab747fSPaolo Bonzini
40949ab747fSPaolo Bonzini #define TRANSP_ROP(name) {\
41049ab747fSPaolo Bonzini name ## _8,\
41149ab747fSPaolo Bonzini name ## _16,\
41249ab747fSPaolo Bonzini }
41349ab747fSPaolo Bonzini #define TRANSP_NOP(func) {\
41449ab747fSPaolo Bonzini func,\
41549ab747fSPaolo Bonzini func,\
41649ab747fSPaolo Bonzini }
41749ab747fSPaolo Bonzini
41849ab747fSPaolo Bonzini static const cirrus_bitblt_rop_t cirrus_fwd_transp_rop[16][2] = {
41949ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_0),
42049ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_dst),
42149ab747fSPaolo Bonzini TRANSP_NOP(cirrus_bitblt_rop_nop),
42249ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_notdst),
42349ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notdst),
42449ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src),
42549ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_1),
42649ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_dst),
42749ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_xor_dst),
42849ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_dst),
42949ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_notdst),
43049ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_notxor_dst),
43149ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_notdst),
43249ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc),
43349ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_dst),
43449ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_notdst),
43549ab747fSPaolo Bonzini };
43649ab747fSPaolo Bonzini
43749ab747fSPaolo Bonzini static const cirrus_bitblt_rop_t cirrus_bkwd_transp_rop[16][2] = {
43849ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_0),
43949ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_dst),
44049ab747fSPaolo Bonzini TRANSP_NOP(cirrus_bitblt_rop_nop),
44149ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_notdst),
44249ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notdst),
44349ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src),
44449ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_1),
44549ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_dst),
44649ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_xor_dst),
44749ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_dst),
44849ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_notdst),
44949ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_notxor_dst),
45049ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_notdst),
45149ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc),
45249ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_dst),
45349ab747fSPaolo Bonzini TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_notdst),
45449ab747fSPaolo Bonzini };
45549ab747fSPaolo Bonzini
45649ab747fSPaolo Bonzini #define ROP2(name) {\
45749ab747fSPaolo Bonzini name ## _8,\
45849ab747fSPaolo Bonzini name ## _16,\
45949ab747fSPaolo Bonzini name ## _24,\
46049ab747fSPaolo Bonzini name ## _32,\
46149ab747fSPaolo Bonzini }
46249ab747fSPaolo Bonzini
46349ab747fSPaolo Bonzini #define ROP_NOP2(func) {\
46449ab747fSPaolo Bonzini func,\
46549ab747fSPaolo Bonzini func,\
46649ab747fSPaolo Bonzini func,\
46749ab747fSPaolo Bonzini func,\
46849ab747fSPaolo Bonzini }
46949ab747fSPaolo Bonzini
47049ab747fSPaolo Bonzini static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = {
47149ab747fSPaolo Bonzini ROP2(cirrus_patternfill_0),
47249ab747fSPaolo Bonzini ROP2(cirrus_patternfill_src_and_dst),
47349ab747fSPaolo Bonzini ROP_NOP2(cirrus_bitblt_rop_nop),
47449ab747fSPaolo Bonzini ROP2(cirrus_patternfill_src_and_notdst),
47549ab747fSPaolo Bonzini ROP2(cirrus_patternfill_notdst),
47649ab747fSPaolo Bonzini ROP2(cirrus_patternfill_src),
47749ab747fSPaolo Bonzini ROP2(cirrus_patternfill_1),
47849ab747fSPaolo Bonzini ROP2(cirrus_patternfill_notsrc_and_dst),
47949ab747fSPaolo Bonzini ROP2(cirrus_patternfill_src_xor_dst),
48049ab747fSPaolo Bonzini ROP2(cirrus_patternfill_src_or_dst),
48149ab747fSPaolo Bonzini ROP2(cirrus_patternfill_notsrc_or_notdst),
48249ab747fSPaolo Bonzini ROP2(cirrus_patternfill_src_notxor_dst),
48349ab747fSPaolo Bonzini ROP2(cirrus_patternfill_src_or_notdst),
48449ab747fSPaolo Bonzini ROP2(cirrus_patternfill_notsrc),
48549ab747fSPaolo Bonzini ROP2(cirrus_patternfill_notsrc_or_dst),
48649ab747fSPaolo Bonzini ROP2(cirrus_patternfill_notsrc_and_notdst),
48749ab747fSPaolo Bonzini };
48849ab747fSPaolo Bonzini
48949ab747fSPaolo Bonzini static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = {
49049ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_0),
49149ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_src_and_dst),
49249ab747fSPaolo Bonzini ROP_NOP2(cirrus_bitblt_rop_nop),
49349ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_src_and_notdst),
49449ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_notdst),
49549ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_src),
49649ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_1),
49749ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_notsrc_and_dst),
49849ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_src_xor_dst),
49949ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_src_or_dst),
50049ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_notsrc_or_notdst),
50149ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_src_notxor_dst),
50249ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_src_or_notdst),
50349ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_notsrc),
50449ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_notsrc_or_dst),
50549ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_transp_notsrc_and_notdst),
50649ab747fSPaolo Bonzini };
50749ab747fSPaolo Bonzini
50849ab747fSPaolo Bonzini static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = {
50949ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_0),
51049ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_src_and_dst),
51149ab747fSPaolo Bonzini ROP_NOP2(cirrus_bitblt_rop_nop),
51249ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_src_and_notdst),
51349ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_notdst),
51449ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_src),
51549ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_1),
51649ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_notsrc_and_dst),
51749ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_src_xor_dst),
51849ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_src_or_dst),
51949ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_notsrc_or_notdst),
52049ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_src_notxor_dst),
52149ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_src_or_notdst),
52249ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_notsrc),
52349ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_notsrc_or_dst),
52449ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_notsrc_and_notdst),
52549ab747fSPaolo Bonzini };
52649ab747fSPaolo Bonzini
52749ab747fSPaolo Bonzini static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = {
52849ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_0),
52949ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_src_and_dst),
53049ab747fSPaolo Bonzini ROP_NOP2(cirrus_bitblt_rop_nop),
53149ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst),
53249ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_notdst),
53349ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_src),
53449ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_1),
53549ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst),
53649ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst),
53749ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_src_or_dst),
53849ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst),
53949ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst),
54049ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst),
54149ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_notsrc),
54249ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst),
54349ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst),
54449ab747fSPaolo Bonzini };
54549ab747fSPaolo Bonzini
54649ab747fSPaolo Bonzini static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = {
54749ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_0),
54849ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_src_and_dst),
54949ab747fSPaolo Bonzini ROP_NOP2(cirrus_bitblt_rop_nop),
55049ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_src_and_notdst),
55149ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_notdst),
55249ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_src),
55349ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_1),
55449ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_notsrc_and_dst),
55549ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_src_xor_dst),
55649ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_src_or_dst),
55749ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst),
55849ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_src_notxor_dst),
55949ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_src_or_notdst),
56049ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_notsrc),
56149ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_notsrc_or_dst),
56249ab747fSPaolo Bonzini ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst),
56349ab747fSPaolo Bonzini };
56449ab747fSPaolo Bonzini
56549ab747fSPaolo Bonzini static const cirrus_fill_t cirrus_fill[16][4] = {
56649ab747fSPaolo Bonzini ROP2(cirrus_fill_0),
56749ab747fSPaolo Bonzini ROP2(cirrus_fill_src_and_dst),
56849ab747fSPaolo Bonzini ROP_NOP2(cirrus_bitblt_fill_nop),
56949ab747fSPaolo Bonzini ROP2(cirrus_fill_src_and_notdst),
57049ab747fSPaolo Bonzini ROP2(cirrus_fill_notdst),
57149ab747fSPaolo Bonzini ROP2(cirrus_fill_src),
57249ab747fSPaolo Bonzini ROP2(cirrus_fill_1),
57349ab747fSPaolo Bonzini ROP2(cirrus_fill_notsrc_and_dst),
57449ab747fSPaolo Bonzini ROP2(cirrus_fill_src_xor_dst),
57549ab747fSPaolo Bonzini ROP2(cirrus_fill_src_or_dst),
57649ab747fSPaolo Bonzini ROP2(cirrus_fill_notsrc_or_notdst),
57749ab747fSPaolo Bonzini ROP2(cirrus_fill_src_notxor_dst),
57849ab747fSPaolo Bonzini ROP2(cirrus_fill_src_or_notdst),
57949ab747fSPaolo Bonzini ROP2(cirrus_fill_notsrc),
58049ab747fSPaolo Bonzini ROP2(cirrus_fill_notsrc_or_dst),
58149ab747fSPaolo Bonzini ROP2(cirrus_fill_notsrc_and_notdst),
58249ab747fSPaolo Bonzini };
58349ab747fSPaolo Bonzini
cirrus_bitblt_fgcol(CirrusVGAState * s)58449ab747fSPaolo Bonzini static inline void cirrus_bitblt_fgcol(CirrusVGAState *s)
58549ab747fSPaolo Bonzini {
58649ab747fSPaolo Bonzini unsigned int color;
58749ab747fSPaolo Bonzini switch (s->cirrus_blt_pixelwidth) {
58849ab747fSPaolo Bonzini case 1:
58949ab747fSPaolo Bonzini s->cirrus_blt_fgcol = s->cirrus_shadow_gr1;
59049ab747fSPaolo Bonzini break;
59149ab747fSPaolo Bonzini case 2:
59249ab747fSPaolo Bonzini color = s->cirrus_shadow_gr1 | (s->vga.gr[0x11] << 8);
59349ab747fSPaolo Bonzini s->cirrus_blt_fgcol = le16_to_cpu(color);
59449ab747fSPaolo Bonzini break;
59549ab747fSPaolo Bonzini case 3:
59649ab747fSPaolo Bonzini s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 |
59749ab747fSPaolo Bonzini (s->vga.gr[0x11] << 8) | (s->vga.gr[0x13] << 16);
59849ab747fSPaolo Bonzini break;
59949ab747fSPaolo Bonzini default:
60049ab747fSPaolo Bonzini case 4:
60149ab747fSPaolo Bonzini color = s->cirrus_shadow_gr1 | (s->vga.gr[0x11] << 8) |
60249ab747fSPaolo Bonzini (s->vga.gr[0x13] << 16) | (s->vga.gr[0x15] << 24);
60349ab747fSPaolo Bonzini s->cirrus_blt_fgcol = le32_to_cpu(color);
60449ab747fSPaolo Bonzini break;
60549ab747fSPaolo Bonzini }
60649ab747fSPaolo Bonzini }
60749ab747fSPaolo Bonzini
cirrus_bitblt_bgcol(CirrusVGAState * s)60849ab747fSPaolo Bonzini static inline void cirrus_bitblt_bgcol(CirrusVGAState *s)
60949ab747fSPaolo Bonzini {
61049ab747fSPaolo Bonzini unsigned int color;
61149ab747fSPaolo Bonzini switch (s->cirrus_blt_pixelwidth) {
61249ab747fSPaolo Bonzini case 1:
61349ab747fSPaolo Bonzini s->cirrus_blt_bgcol = s->cirrus_shadow_gr0;
61449ab747fSPaolo Bonzini break;
61549ab747fSPaolo Bonzini case 2:
61649ab747fSPaolo Bonzini color = s->cirrus_shadow_gr0 | (s->vga.gr[0x10] << 8);
61749ab747fSPaolo Bonzini s->cirrus_blt_bgcol = le16_to_cpu(color);
61849ab747fSPaolo Bonzini break;
61949ab747fSPaolo Bonzini case 3:
62049ab747fSPaolo Bonzini s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 |
62149ab747fSPaolo Bonzini (s->vga.gr[0x10] << 8) | (s->vga.gr[0x12] << 16);
62249ab747fSPaolo Bonzini break;
62349ab747fSPaolo Bonzini default:
62449ab747fSPaolo Bonzini case 4:
62549ab747fSPaolo Bonzini color = s->cirrus_shadow_gr0 | (s->vga.gr[0x10] << 8) |
62649ab747fSPaolo Bonzini (s->vga.gr[0x12] << 16) | (s->vga.gr[0x14] << 24);
62749ab747fSPaolo Bonzini s->cirrus_blt_bgcol = le32_to_cpu(color);
62849ab747fSPaolo Bonzini break;
62949ab747fSPaolo Bonzini }
63049ab747fSPaolo Bonzini }
63149ab747fSPaolo Bonzini
cirrus_invalidate_region(CirrusVGAState * s,int off_begin,int off_pitch,int bytesperline,int lines)63249ab747fSPaolo Bonzini static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
63349ab747fSPaolo Bonzini int off_pitch, int bytesperline,
63449ab747fSPaolo Bonzini int lines)
63549ab747fSPaolo Bonzini {
63649ab747fSPaolo Bonzini int y;
63749ab747fSPaolo Bonzini int off_cur;
63849ab747fSPaolo Bonzini int off_cur_end;
63949ab747fSPaolo Bonzini
640f153b563SWolfgang Bumiller if (off_pitch < 0) {
641f153b563SWolfgang Bumiller off_begin -= bytesperline - 1;
642f153b563SWolfgang Bumiller }
643f153b563SWolfgang Bumiller
64449ab747fSPaolo Bonzini for (y = 0; y < lines; y++) {
6455fcf7875SGerd Hoffmann off_cur = off_begin & s->cirrus_addr_mask;
646e048dac6SGerd Hoffmann off_cur_end = ((off_cur + bytesperline - 1) & s->cirrus_addr_mask) + 1;
6475fcf7875SGerd Hoffmann if (off_cur_end >= off_cur) {
64849ab747fSPaolo Bonzini memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur);
6495fcf7875SGerd Hoffmann } else {
6505fcf7875SGerd Hoffmann /* wraparound */
6515fcf7875SGerd Hoffmann memory_region_set_dirty(&s->vga.vram, off_cur,
6525fcf7875SGerd Hoffmann s->cirrus_addr_mask + 1 - off_cur);
6535fcf7875SGerd Hoffmann memory_region_set_dirty(&s->vga.vram, 0, off_cur_end);
6545fcf7875SGerd Hoffmann }
65549ab747fSPaolo Bonzini off_begin += off_pitch;
65649ab747fSPaolo Bonzini }
65749ab747fSPaolo Bonzini }
65849ab747fSPaolo Bonzini
cirrus_bitblt_common_patterncopy(CirrusVGAState * s)659ffaf8577SGerd Hoffmann static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s)
66049ab747fSPaolo Bonzini {
66195280c31SGerd Hoffmann uint32_t patternsize;
662ffaf8577SGerd Hoffmann bool videosrc = !s->cirrus_srccounter;
66349ab747fSPaolo Bonzini
66495280c31SGerd Hoffmann if (videosrc) {
66595280c31SGerd Hoffmann switch (s->vga.get_bpp(&s->vga)) {
66695280c31SGerd Hoffmann case 8:
66795280c31SGerd Hoffmann patternsize = 64;
66895280c31SGerd Hoffmann break;
66995280c31SGerd Hoffmann case 15:
67095280c31SGerd Hoffmann case 16:
67195280c31SGerd Hoffmann patternsize = 128;
67295280c31SGerd Hoffmann break;
67395280c31SGerd Hoffmann case 24:
67495280c31SGerd Hoffmann case 32:
67595280c31SGerd Hoffmann default:
67695280c31SGerd Hoffmann patternsize = 256;
67795280c31SGerd Hoffmann break;
67895280c31SGerd Hoffmann }
67995280c31SGerd Hoffmann s->cirrus_blt_srcaddr &= ~(patternsize - 1);
68095280c31SGerd Hoffmann if (s->cirrus_blt_srcaddr + patternsize > s->vga.vram_size) {
68195280c31SGerd Hoffmann return 0;
68295280c31SGerd Hoffmann }
68395280c31SGerd Hoffmann }
68495280c31SGerd Hoffmann
68512e97ec3SGerd Hoffmann if (blit_is_unsafe(s, true)) {
68649ab747fSPaolo Bonzini return 0;
6875858dd18SWolfgang Bumiller }
68849ab747fSPaolo Bonzini
689ffaf8577SGerd Hoffmann (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr,
690ffaf8577SGerd Hoffmann videosrc ? s->cirrus_blt_srcaddr : 0,
69149ab747fSPaolo Bonzini s->cirrus_blt_dstpitch, 0,
69249ab747fSPaolo Bonzini s->cirrus_blt_width, s->cirrus_blt_height);
69349ab747fSPaolo Bonzini cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
69449ab747fSPaolo Bonzini s->cirrus_blt_dstpitch, s->cirrus_blt_width,
69549ab747fSPaolo Bonzini s->cirrus_blt_height);
69649ab747fSPaolo Bonzini return 1;
69749ab747fSPaolo Bonzini }
69849ab747fSPaolo Bonzini
69949ab747fSPaolo Bonzini /* fill */
70049ab747fSPaolo Bonzini
cirrus_bitblt_solidfill(CirrusVGAState * s,int blt_rop)70149ab747fSPaolo Bonzini static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
70249ab747fSPaolo Bonzini {
70349ab747fSPaolo Bonzini cirrus_fill_t rop_func;
70449ab747fSPaolo Bonzini
70512e97ec3SGerd Hoffmann if (blit_is_unsafe(s, true)) {
70649ab747fSPaolo Bonzini return 0;
707d3532a0dSGerd Hoffmann }
70849ab747fSPaolo Bonzini rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
709026aeffcSGerd Hoffmann rop_func(s, s->cirrus_blt_dstaddr,
71049ab747fSPaolo Bonzini s->cirrus_blt_dstpitch,
71149ab747fSPaolo Bonzini s->cirrus_blt_width, s->cirrus_blt_height);
71249ab747fSPaolo Bonzini cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
71349ab747fSPaolo Bonzini s->cirrus_blt_dstpitch, s->cirrus_blt_width,
71449ab747fSPaolo Bonzini s->cirrus_blt_height);
71549ab747fSPaolo Bonzini cirrus_bitblt_reset(s);
71649ab747fSPaolo Bonzini return 1;
71749ab747fSPaolo Bonzini }
71849ab747fSPaolo Bonzini
71949ab747fSPaolo Bonzini /***************************************
72049ab747fSPaolo Bonzini *
72149ab747fSPaolo Bonzini * bitblt (video-to-video)
72249ab747fSPaolo Bonzini *
72349ab747fSPaolo Bonzini ***************************************/
72449ab747fSPaolo Bonzini
cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)72549ab747fSPaolo Bonzini static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
72649ab747fSPaolo Bonzini {
727ffaf8577SGerd Hoffmann return cirrus_bitblt_common_patterncopy(s);
72849ab747fSPaolo Bonzini }
72949ab747fSPaolo Bonzini
cirrus_do_copy(CirrusVGAState * s,int dst,int src,int w,int h)7304299b90eSPrasad J Pandit static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
73149ab747fSPaolo Bonzini {
73249ab747fSPaolo Bonzini int sx = 0, sy = 0;
73349ab747fSPaolo Bonzini int dx = 0, dy = 0;
73449ab747fSPaolo Bonzini int depth = 0;
73549ab747fSPaolo Bonzini int notify = 0;
73649ab747fSPaolo Bonzini
73749ab747fSPaolo Bonzini /* make sure to only copy if it's a plain copy ROP */
73849ab747fSPaolo Bonzini if (*s->cirrus_rop == cirrus_bitblt_rop_fwd_src ||
73949ab747fSPaolo Bonzini *s->cirrus_rop == cirrus_bitblt_rop_bkwd_src) {
74049ab747fSPaolo Bonzini
74149ab747fSPaolo Bonzini int width, height;
74249ab747fSPaolo Bonzini
74349ab747fSPaolo Bonzini depth = s->vga.get_bpp(&s->vga) / 8;
7444299b90eSPrasad J Pandit if (!depth) {
7454299b90eSPrasad J Pandit return 0;
7464299b90eSPrasad J Pandit }
74749ab747fSPaolo Bonzini s->vga.get_resolution(&s->vga, &width, &height);
74849ab747fSPaolo Bonzini
74949ab747fSPaolo Bonzini /* extra x, y */
75049ab747fSPaolo Bonzini sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;
75149ab747fSPaolo Bonzini sy = (src / ABS(s->cirrus_blt_srcpitch));
75249ab747fSPaolo Bonzini dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;
75349ab747fSPaolo Bonzini dy = (dst / ABS(s->cirrus_blt_dstpitch));
75449ab747fSPaolo Bonzini
75549ab747fSPaolo Bonzini /* normalize width */
75649ab747fSPaolo Bonzini w /= depth;
75749ab747fSPaolo Bonzini
75849ab747fSPaolo Bonzini /* if we're doing a backward copy, we have to adjust
75949ab747fSPaolo Bonzini our x/y to be the upper left corner (instead of the lower
76049ab747fSPaolo Bonzini right corner) */
76149ab747fSPaolo Bonzini if (s->cirrus_blt_dstpitch < 0) {
76249ab747fSPaolo Bonzini sx -= (s->cirrus_blt_width / depth) - 1;
76349ab747fSPaolo Bonzini dx -= (s->cirrus_blt_width / depth) - 1;
76449ab747fSPaolo Bonzini sy -= s->cirrus_blt_height - 1;
76549ab747fSPaolo Bonzini dy -= s->cirrus_blt_height - 1;
76649ab747fSPaolo Bonzini }
76749ab747fSPaolo Bonzini
76849ab747fSPaolo Bonzini /* are we in the visible portion of memory? */
76949ab747fSPaolo Bonzini if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
77049ab747fSPaolo Bonzini (sx + w) <= width && (sy + h) <= height &&
77149ab747fSPaolo Bonzini (dx + w) <= width && (dy + h) <= height) {
77249ab747fSPaolo Bonzini notify = 1;
77349ab747fSPaolo Bonzini }
77449ab747fSPaolo Bonzini }
77549ab747fSPaolo Bonzini
776026aeffcSGerd Hoffmann (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr,
777ffaf8577SGerd Hoffmann s->cirrus_blt_srcaddr,
77849ab747fSPaolo Bonzini s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
77949ab747fSPaolo Bonzini s->cirrus_blt_width, s->cirrus_blt_height);
78049ab747fSPaolo Bonzini
78149ab747fSPaolo Bonzini if (notify) {
78250628d34SGerd Hoffmann dpy_gfx_update(s->vga.con, dx, dy,
78349ab747fSPaolo Bonzini s->cirrus_blt_width / depth,
78449ab747fSPaolo Bonzini s->cirrus_blt_height);
78549ab747fSPaolo Bonzini }
78649ab747fSPaolo Bonzini
78749ab747fSPaolo Bonzini /* we don't have to notify the display that this portion has
78849ab747fSPaolo Bonzini changed since qemu_console_copy implies this */
78949ab747fSPaolo Bonzini
79049ab747fSPaolo Bonzini cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
79149ab747fSPaolo Bonzini s->cirrus_blt_dstpitch, s->cirrus_blt_width,
79249ab747fSPaolo Bonzini s->cirrus_blt_height);
7934299b90eSPrasad J Pandit
7944299b90eSPrasad J Pandit return 1;
79549ab747fSPaolo Bonzini }
79649ab747fSPaolo Bonzini
cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)79749ab747fSPaolo Bonzini static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
79849ab747fSPaolo Bonzini {
79912e97ec3SGerd Hoffmann if (blit_is_unsafe(s, false))
80049ab747fSPaolo Bonzini return 0;
80149ab747fSPaolo Bonzini
802f9b925fdSPaolo Bonzini return cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->vga.params.start_addr,
803f9b925fdSPaolo Bonzini s->cirrus_blt_srcaddr - s->vga.params.start_addr,
80449ab747fSPaolo Bonzini s->cirrus_blt_width, s->cirrus_blt_height);
80549ab747fSPaolo Bonzini }
80649ab747fSPaolo Bonzini
80749ab747fSPaolo Bonzini /***************************************
80849ab747fSPaolo Bonzini *
80949ab747fSPaolo Bonzini * bitblt (cpu-to-video)
81049ab747fSPaolo Bonzini *
81149ab747fSPaolo Bonzini ***************************************/
81249ab747fSPaolo Bonzini
cirrus_bitblt_cputovideo_next(CirrusVGAState * s)81349ab747fSPaolo Bonzini static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
81449ab747fSPaolo Bonzini {
81549ab747fSPaolo Bonzini int copy_count;
81649ab747fSPaolo Bonzini uint8_t *end_ptr;
81749ab747fSPaolo Bonzini
81849ab747fSPaolo Bonzini if (s->cirrus_srccounter > 0) {
81949ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
820ffaf8577SGerd Hoffmann cirrus_bitblt_common_patterncopy(s);
82149ab747fSPaolo Bonzini the_end:
82249ab747fSPaolo Bonzini s->cirrus_srccounter = 0;
82349ab747fSPaolo Bonzini cirrus_bitblt_reset(s);
82449ab747fSPaolo Bonzini } else {
82549ab747fSPaolo Bonzini /* at least one scan line */
82649ab747fSPaolo Bonzini do {
827026aeffcSGerd Hoffmann (*s->cirrus_rop)(s, s->cirrus_blt_dstaddr,
828ffaf8577SGerd Hoffmann 0, 0, 0, s->cirrus_blt_width, 1);
82949ab747fSPaolo Bonzini cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
83049ab747fSPaolo Bonzini s->cirrus_blt_width, 1);
83149ab747fSPaolo Bonzini s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
83249ab747fSPaolo Bonzini s->cirrus_srccounter -= s->cirrus_blt_srcpitch;
83349ab747fSPaolo Bonzini if (s->cirrus_srccounter <= 0)
83449ab747fSPaolo Bonzini goto the_end;
83549ab747fSPaolo Bonzini /* more bytes than needed can be transferred because of
83649ab747fSPaolo Bonzini word alignment, so we keep them for the next line */
83749ab747fSPaolo Bonzini /* XXX: keep alignment to speed up transfer */
83849ab747fSPaolo Bonzini end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
8392fba4e9cSlu zhipeng copy_count = MIN(s->cirrus_srcptr_end - end_ptr, CIRRUS_BLTBUFSIZE);
84049ab747fSPaolo Bonzini memmove(s->cirrus_bltbuf, end_ptr, copy_count);
84149ab747fSPaolo Bonzini s->cirrus_srcptr = s->cirrus_bltbuf + copy_count;
84249ab747fSPaolo Bonzini s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
84349ab747fSPaolo Bonzini } while (s->cirrus_srcptr >= s->cirrus_srcptr_end);
84449ab747fSPaolo Bonzini }
84549ab747fSPaolo Bonzini }
84649ab747fSPaolo Bonzini }
84749ab747fSPaolo Bonzini
84849ab747fSPaolo Bonzini /***************************************
84949ab747fSPaolo Bonzini *
85049ab747fSPaolo Bonzini * bitblt wrapper
85149ab747fSPaolo Bonzini *
85249ab747fSPaolo Bonzini ***************************************/
85349ab747fSPaolo Bonzini
cirrus_bitblt_reset(CirrusVGAState * s)85449ab747fSPaolo Bonzini static void cirrus_bitblt_reset(CirrusVGAState * s)
85549ab747fSPaolo Bonzini {
85649ab747fSPaolo Bonzini int need_update;
85749ab747fSPaolo Bonzini
85849ab747fSPaolo Bonzini s->vga.gr[0x31] &=
85949ab747fSPaolo Bonzini ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED);
86049ab747fSPaolo Bonzini need_update = s->cirrus_srcptr != &s->cirrus_bltbuf[0]
86149ab747fSPaolo Bonzini || s->cirrus_srcptr_end != &s->cirrus_bltbuf[0];
86249ab747fSPaolo Bonzini s->cirrus_srcptr = &s->cirrus_bltbuf[0];
86349ab747fSPaolo Bonzini s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
86449ab747fSPaolo Bonzini s->cirrus_srccounter = 0;
86549ab747fSPaolo Bonzini if (!need_update)
86649ab747fSPaolo Bonzini return;
86749ab747fSPaolo Bonzini cirrus_update_memory_access(s);
86849ab747fSPaolo Bonzini }
86949ab747fSPaolo Bonzini
cirrus_bitblt_cputovideo(CirrusVGAState * s)87049ab747fSPaolo Bonzini static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
87149ab747fSPaolo Bonzini {
87249ab747fSPaolo Bonzini int w;
87349ab747fSPaolo Bonzini
87492f2b88cSGerd Hoffmann if (blit_is_unsafe(s, true)) {
87592f2b88cSGerd Hoffmann return 0;
87692f2b88cSGerd Hoffmann }
87792f2b88cSGerd Hoffmann
87849ab747fSPaolo Bonzini s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
87949ab747fSPaolo Bonzini s->cirrus_srcptr = &s->cirrus_bltbuf[0];
88049ab747fSPaolo Bonzini s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
88149ab747fSPaolo Bonzini
88249ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
88349ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
88449ab747fSPaolo Bonzini s->cirrus_blt_srcpitch = 8;
88549ab747fSPaolo Bonzini } else {
88649ab747fSPaolo Bonzini /* XXX: check for 24 bpp */
88749ab747fSPaolo Bonzini s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth;
88849ab747fSPaolo Bonzini }
88949ab747fSPaolo Bonzini s->cirrus_srccounter = s->cirrus_blt_srcpitch;
89049ab747fSPaolo Bonzini } else {
89149ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
89249ab747fSPaolo Bonzini w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth;
89349ab747fSPaolo Bonzini if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)
89449ab747fSPaolo Bonzini s->cirrus_blt_srcpitch = ((w + 31) >> 5);
89549ab747fSPaolo Bonzini else
89649ab747fSPaolo Bonzini s->cirrus_blt_srcpitch = ((w + 7) >> 3);
89749ab747fSPaolo Bonzini } else {
89849ab747fSPaolo Bonzini /* always align input size to 32 bits */
89949ab747fSPaolo Bonzini s->cirrus_blt_srcpitch = (s->cirrus_blt_width + 3) & ~3;
90049ab747fSPaolo Bonzini }
90149ab747fSPaolo Bonzini s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
90249ab747fSPaolo Bonzini }
90392f2b88cSGerd Hoffmann
90492f2b88cSGerd Hoffmann /* the blit_is_unsafe call above should catch this */
90592f2b88cSGerd Hoffmann assert(s->cirrus_blt_srcpitch <= CIRRUS_BLTBUFSIZE);
90692f2b88cSGerd Hoffmann
90749ab747fSPaolo Bonzini s->cirrus_srcptr = s->cirrus_bltbuf;
90849ab747fSPaolo Bonzini s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
90949ab747fSPaolo Bonzini cirrus_update_memory_access(s);
91049ab747fSPaolo Bonzini return 1;
91149ab747fSPaolo Bonzini }
91249ab747fSPaolo Bonzini
cirrus_bitblt_videotocpu(CirrusVGAState * s)91349ab747fSPaolo Bonzini static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
91449ab747fSPaolo Bonzini {
91549ab747fSPaolo Bonzini /* XXX */
916bb6e9e94SPhilippe Mathieu-Daudé qemu_log_mask(LOG_UNIMP,
917bb6e9e94SPhilippe Mathieu-Daudé "cirrus: bitblt (video to cpu) is not implemented\n");
91849ab747fSPaolo Bonzini return 0;
91949ab747fSPaolo Bonzini }
92049ab747fSPaolo Bonzini
cirrus_bitblt_videotovideo(CirrusVGAState * s)92149ab747fSPaolo Bonzini static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
92249ab747fSPaolo Bonzini {
92349ab747fSPaolo Bonzini int ret;
92449ab747fSPaolo Bonzini
92549ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
92649ab747fSPaolo Bonzini ret = cirrus_bitblt_videotovideo_patterncopy(s);
92749ab747fSPaolo Bonzini } else {
92849ab747fSPaolo Bonzini ret = cirrus_bitblt_videotovideo_copy(s);
92949ab747fSPaolo Bonzini }
93049ab747fSPaolo Bonzini if (ret)
93149ab747fSPaolo Bonzini cirrus_bitblt_reset(s);
93249ab747fSPaolo Bonzini return ret;
93349ab747fSPaolo Bonzini }
93449ab747fSPaolo Bonzini
cirrus_bitblt_start(CirrusVGAState * s)93549ab747fSPaolo Bonzini static void cirrus_bitblt_start(CirrusVGAState * s)
93649ab747fSPaolo Bonzini {
93749ab747fSPaolo Bonzini uint8_t blt_rop;
93849ab747fSPaolo Bonzini
939827bd517SGerd Hoffmann if (!s->enable_blitter) {
940827bd517SGerd Hoffmann goto bitblt_ignore;
941827bd517SGerd Hoffmann }
942827bd517SGerd Hoffmann
94349ab747fSPaolo Bonzini s->vga.gr[0x31] |= CIRRUS_BLT_BUSY;
94449ab747fSPaolo Bonzini
94549ab747fSPaolo Bonzini s->cirrus_blt_width = (s->vga.gr[0x20] | (s->vga.gr[0x21] << 8)) + 1;
94649ab747fSPaolo Bonzini s->cirrus_blt_height = (s->vga.gr[0x22] | (s->vga.gr[0x23] << 8)) + 1;
94749ab747fSPaolo Bonzini s->cirrus_blt_dstpitch = (s->vga.gr[0x24] | (s->vga.gr[0x25] << 8));
94849ab747fSPaolo Bonzini s->cirrus_blt_srcpitch = (s->vga.gr[0x26] | (s->vga.gr[0x27] << 8));
94949ab747fSPaolo Bonzini s->cirrus_blt_dstaddr =
95049ab747fSPaolo Bonzini (s->vga.gr[0x28] | (s->vga.gr[0x29] << 8) | (s->vga.gr[0x2a] << 16));
95149ab747fSPaolo Bonzini s->cirrus_blt_srcaddr =
95249ab747fSPaolo Bonzini (s->vga.gr[0x2c] | (s->vga.gr[0x2d] << 8) | (s->vga.gr[0x2e] << 16));
95349ab747fSPaolo Bonzini s->cirrus_blt_mode = s->vga.gr[0x30];
95449ab747fSPaolo Bonzini s->cirrus_blt_modeext = s->vga.gr[0x33];
95549ab747fSPaolo Bonzini blt_rop = s->vga.gr[0x32];
95649ab747fSPaolo Bonzini
95760cd23e8SGerd Hoffmann s->cirrus_blt_dstaddr &= s->cirrus_addr_mask;
95860cd23e8SGerd Hoffmann s->cirrus_blt_srcaddr &= s->cirrus_addr_mask;
95960cd23e8SGerd Hoffmann
96061527721SPhilippe Mathieu-Daudé trace_vga_cirrus_bitblt_start(blt_rop,
96149ab747fSPaolo Bonzini s->cirrus_blt_mode,
96249ab747fSPaolo Bonzini s->cirrus_blt_modeext,
96349ab747fSPaolo Bonzini s->cirrus_blt_width,
96449ab747fSPaolo Bonzini s->cirrus_blt_height,
96549ab747fSPaolo Bonzini s->cirrus_blt_dstpitch,
96649ab747fSPaolo Bonzini s->cirrus_blt_srcpitch,
96749ab747fSPaolo Bonzini s->cirrus_blt_dstaddr,
96849ab747fSPaolo Bonzini s->cirrus_blt_srcaddr,
96949ab747fSPaolo Bonzini s->vga.gr[0x2f]);
97049ab747fSPaolo Bonzini
97149ab747fSPaolo Bonzini switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
97249ab747fSPaolo Bonzini case CIRRUS_BLTMODE_PIXELWIDTH8:
97349ab747fSPaolo Bonzini s->cirrus_blt_pixelwidth = 1;
97449ab747fSPaolo Bonzini break;
97549ab747fSPaolo Bonzini case CIRRUS_BLTMODE_PIXELWIDTH16:
97649ab747fSPaolo Bonzini s->cirrus_blt_pixelwidth = 2;
97749ab747fSPaolo Bonzini break;
97849ab747fSPaolo Bonzini case CIRRUS_BLTMODE_PIXELWIDTH24:
97949ab747fSPaolo Bonzini s->cirrus_blt_pixelwidth = 3;
98049ab747fSPaolo Bonzini break;
98149ab747fSPaolo Bonzini case CIRRUS_BLTMODE_PIXELWIDTH32:
98249ab747fSPaolo Bonzini s->cirrus_blt_pixelwidth = 4;
98349ab747fSPaolo Bonzini break;
98449ab747fSPaolo Bonzini default:
9852b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
9862b55f4d3SPhilippe Mathieu-Daudé "cirrus: bitblt - pixel width is unknown\n");
98749ab747fSPaolo Bonzini goto bitblt_ignore;
98849ab747fSPaolo Bonzini }
98949ab747fSPaolo Bonzini s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
99049ab747fSPaolo Bonzini
99149ab747fSPaolo Bonzini if ((s->
99249ab747fSPaolo Bonzini cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
99349ab747fSPaolo Bonzini CIRRUS_BLTMODE_MEMSYSDEST))
99449ab747fSPaolo Bonzini == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
995bb6e9e94SPhilippe Mathieu-Daudé qemu_log_mask(LOG_UNIMP,
996bb6e9e94SPhilippe Mathieu-Daudé "cirrus: bitblt - memory-to-memory copy requested\n");
99749ab747fSPaolo Bonzini goto bitblt_ignore;
99849ab747fSPaolo Bonzini }
99949ab747fSPaolo Bonzini
100049ab747fSPaolo Bonzini if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
100149ab747fSPaolo Bonzini (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST |
100249ab747fSPaolo Bonzini CIRRUS_BLTMODE_TRANSPARENTCOMP |
100349ab747fSPaolo Bonzini CIRRUS_BLTMODE_PATTERNCOPY |
100449ab747fSPaolo Bonzini CIRRUS_BLTMODE_COLOREXPAND)) ==
100549ab747fSPaolo Bonzini (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
100649ab747fSPaolo Bonzini cirrus_bitblt_fgcol(s);
100749ab747fSPaolo Bonzini cirrus_bitblt_solidfill(s, blt_rop);
100849ab747fSPaolo Bonzini } else {
100949ab747fSPaolo Bonzini if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND |
101049ab747fSPaolo Bonzini CIRRUS_BLTMODE_PATTERNCOPY)) ==
101149ab747fSPaolo Bonzini CIRRUS_BLTMODE_COLOREXPAND) {
101249ab747fSPaolo Bonzini
101349ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
101449ab747fSPaolo Bonzini if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
101549ab747fSPaolo Bonzini cirrus_bitblt_bgcol(s);
101649ab747fSPaolo Bonzini else
101749ab747fSPaolo Bonzini cirrus_bitblt_fgcol(s);
101849ab747fSPaolo Bonzini s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
101949ab747fSPaolo Bonzini } else {
102049ab747fSPaolo Bonzini cirrus_bitblt_fgcol(s);
102149ab747fSPaolo Bonzini cirrus_bitblt_bgcol(s);
102249ab747fSPaolo Bonzini s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
102349ab747fSPaolo Bonzini }
102449ab747fSPaolo Bonzini } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
102549ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
102649ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
102749ab747fSPaolo Bonzini if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
102849ab747fSPaolo Bonzini cirrus_bitblt_bgcol(s);
102949ab747fSPaolo Bonzini else
103049ab747fSPaolo Bonzini cirrus_bitblt_fgcol(s);
103149ab747fSPaolo Bonzini s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
103249ab747fSPaolo Bonzini } else {
103349ab747fSPaolo Bonzini cirrus_bitblt_fgcol(s);
103449ab747fSPaolo Bonzini cirrus_bitblt_bgcol(s);
103549ab747fSPaolo Bonzini s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
103649ab747fSPaolo Bonzini }
103749ab747fSPaolo Bonzini } else {
103849ab747fSPaolo Bonzini s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
103949ab747fSPaolo Bonzini }
104049ab747fSPaolo Bonzini } else {
104149ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
104249ab747fSPaolo Bonzini if (s->cirrus_blt_pixelwidth > 2) {
10432b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
10442b55f4d3SPhilippe Mathieu-Daudé "cirrus: src transparent without colorexpand "
10452b55f4d3SPhilippe Mathieu-Daudé "must be 8bpp or 16bpp\n");
104649ab747fSPaolo Bonzini goto bitblt_ignore;
104749ab747fSPaolo Bonzini }
104849ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
104949ab747fSPaolo Bonzini s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
105049ab747fSPaolo Bonzini s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
105149ab747fSPaolo Bonzini s->cirrus_rop = cirrus_bkwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
105249ab747fSPaolo Bonzini } else {
105349ab747fSPaolo Bonzini s->cirrus_rop = cirrus_fwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
105449ab747fSPaolo Bonzini }
105549ab747fSPaolo Bonzini } else {
105649ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
105749ab747fSPaolo Bonzini s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
105849ab747fSPaolo Bonzini s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
105949ab747fSPaolo Bonzini s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]];
106049ab747fSPaolo Bonzini } else {
106149ab747fSPaolo Bonzini s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]];
106249ab747fSPaolo Bonzini }
106349ab747fSPaolo Bonzini }
106449ab747fSPaolo Bonzini }
106549ab747fSPaolo Bonzini // setup bitblt engine.
106649ab747fSPaolo Bonzini if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
106749ab747fSPaolo Bonzini if (!cirrus_bitblt_cputovideo(s))
106849ab747fSPaolo Bonzini goto bitblt_ignore;
106949ab747fSPaolo Bonzini } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
107049ab747fSPaolo Bonzini if (!cirrus_bitblt_videotocpu(s))
107149ab747fSPaolo Bonzini goto bitblt_ignore;
107249ab747fSPaolo Bonzini } else {
107349ab747fSPaolo Bonzini if (!cirrus_bitblt_videotovideo(s))
107449ab747fSPaolo Bonzini goto bitblt_ignore;
107549ab747fSPaolo Bonzini }
107649ab747fSPaolo Bonzini }
107749ab747fSPaolo Bonzini return;
107849ab747fSPaolo Bonzini bitblt_ignore:;
107949ab747fSPaolo Bonzini cirrus_bitblt_reset(s);
108049ab747fSPaolo Bonzini }
108149ab747fSPaolo Bonzini
cirrus_write_bitblt(CirrusVGAState * s,unsigned reg_value)108249ab747fSPaolo Bonzini static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
108349ab747fSPaolo Bonzini {
108449ab747fSPaolo Bonzini unsigned old_value;
108549ab747fSPaolo Bonzini
108649ab747fSPaolo Bonzini old_value = s->vga.gr[0x31];
108749ab747fSPaolo Bonzini s->vga.gr[0x31] = reg_value;
108849ab747fSPaolo Bonzini
108949ab747fSPaolo Bonzini if (((old_value & CIRRUS_BLT_RESET) != 0) &&
109049ab747fSPaolo Bonzini ((reg_value & CIRRUS_BLT_RESET) == 0)) {
109149ab747fSPaolo Bonzini cirrus_bitblt_reset(s);
109249ab747fSPaolo Bonzini } else if (((old_value & CIRRUS_BLT_START) == 0) &&
109349ab747fSPaolo Bonzini ((reg_value & CIRRUS_BLT_START) != 0)) {
109449ab747fSPaolo Bonzini cirrus_bitblt_start(s);
109549ab747fSPaolo Bonzini }
109649ab747fSPaolo Bonzini }
109749ab747fSPaolo Bonzini
109849ab747fSPaolo Bonzini
109949ab747fSPaolo Bonzini /***************************************
110049ab747fSPaolo Bonzini *
110149ab747fSPaolo Bonzini * basic parameters
110249ab747fSPaolo Bonzini *
110349ab747fSPaolo Bonzini ***************************************/
110449ab747fSPaolo Bonzini
cirrus_get_params(VGACommonState * s1,VGADisplayParams * params)1105f9b925fdSPaolo Bonzini static void cirrus_get_params(VGACommonState *s1,
1106f9b925fdSPaolo Bonzini VGADisplayParams *params)
110749ab747fSPaolo Bonzini {
110849ab747fSPaolo Bonzini CirrusVGAState * s = container_of(s1, CirrusVGAState, vga);
1109f9b925fdSPaolo Bonzini uint32_t line_offset;
111049ab747fSPaolo Bonzini
111149ab747fSPaolo Bonzini line_offset = s->vga.cr[0x13]
111249ab747fSPaolo Bonzini | ((s->vga.cr[0x1b] & 0x10) << 4);
111349ab747fSPaolo Bonzini line_offset <<= 3;
1114f9b925fdSPaolo Bonzini params->line_offset = line_offset;
111549ab747fSPaolo Bonzini
1116f9b925fdSPaolo Bonzini params->start_addr = (s->vga.cr[0x0c] << 8)
111749ab747fSPaolo Bonzini | s->vga.cr[0x0d]
111849ab747fSPaolo Bonzini | ((s->vga.cr[0x1b] & 0x01) << 16)
111949ab747fSPaolo Bonzini | ((s->vga.cr[0x1b] & 0x0c) << 15)
112049ab747fSPaolo Bonzini | ((s->vga.cr[0x1d] & 0x80) << 12);
112149ab747fSPaolo Bonzini
1122f9b925fdSPaolo Bonzini params->line_compare = s->vga.cr[0x18] |
112349ab747fSPaolo Bonzini ((s->vga.cr[0x07] & 0x10) << 4) |
112449ab747fSPaolo Bonzini ((s->vga.cr[0x09] & 0x40) << 3);
1125*973a724eSPaolo Bonzini
1126*973a724eSPaolo Bonzini params->hpel = s->vga.ar[VGA_ATC_PEL];
1127*973a724eSPaolo Bonzini params->hpel_split = s->vga.ar[VGA_ATC_MODE] & 0x20;
112849ab747fSPaolo Bonzini }
112949ab747fSPaolo Bonzini
cirrus_get_bpp16_depth(CirrusVGAState * s)113049ab747fSPaolo Bonzini static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
113149ab747fSPaolo Bonzini {
113249ab747fSPaolo Bonzini uint32_t ret = 16;
113349ab747fSPaolo Bonzini
113449ab747fSPaolo Bonzini switch (s->cirrus_hidden_dac_data & 0xf) {
113549ab747fSPaolo Bonzini case 0:
113649ab747fSPaolo Bonzini ret = 15;
113749ab747fSPaolo Bonzini break; /* Sierra HiColor */
113849ab747fSPaolo Bonzini case 1:
113949ab747fSPaolo Bonzini ret = 16;
114049ab747fSPaolo Bonzini break; /* XGA HiColor */
114149ab747fSPaolo Bonzini default:
11422b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
11432b55f4d3SPhilippe Mathieu-Daudé "cirrus: invalid DAC value 0x%x in 16bpp\n",
114449ab747fSPaolo Bonzini (s->cirrus_hidden_dac_data & 0xf));
114549ab747fSPaolo Bonzini ret = 15; /* XXX */
114649ab747fSPaolo Bonzini break;
114749ab747fSPaolo Bonzini }
114849ab747fSPaolo Bonzini return ret;
114949ab747fSPaolo Bonzini }
115049ab747fSPaolo Bonzini
cirrus_get_bpp(VGACommonState * s1)115149ab747fSPaolo Bonzini static int cirrus_get_bpp(VGACommonState *s1)
115249ab747fSPaolo Bonzini {
115349ab747fSPaolo Bonzini CirrusVGAState * s = container_of(s1, CirrusVGAState, vga);
115449ab747fSPaolo Bonzini uint32_t ret = 8;
115549ab747fSPaolo Bonzini
115649ab747fSPaolo Bonzini if ((s->vga.sr[0x07] & 0x01) != 0) {
115749ab747fSPaolo Bonzini /* Cirrus SVGA */
115849ab747fSPaolo Bonzini switch (s->vga.sr[0x07] & CIRRUS_SR7_BPP_MASK) {
115949ab747fSPaolo Bonzini case CIRRUS_SR7_BPP_8:
116049ab747fSPaolo Bonzini ret = 8;
116149ab747fSPaolo Bonzini break;
116249ab747fSPaolo Bonzini case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
116349ab747fSPaolo Bonzini ret = cirrus_get_bpp16_depth(s);
116449ab747fSPaolo Bonzini break;
116549ab747fSPaolo Bonzini case CIRRUS_SR7_BPP_24:
116649ab747fSPaolo Bonzini ret = 24;
116749ab747fSPaolo Bonzini break;
116849ab747fSPaolo Bonzini case CIRRUS_SR7_BPP_16:
116949ab747fSPaolo Bonzini ret = cirrus_get_bpp16_depth(s);
117049ab747fSPaolo Bonzini break;
117149ab747fSPaolo Bonzini case CIRRUS_SR7_BPP_32:
117249ab747fSPaolo Bonzini ret = 32;
117349ab747fSPaolo Bonzini break;
117449ab747fSPaolo Bonzini default:
117549ab747fSPaolo Bonzini #ifdef DEBUG_CIRRUS
117649ab747fSPaolo Bonzini printf("cirrus: unknown bpp - sr7=%x\n", s->vga.sr[0x7]);
117749ab747fSPaolo Bonzini #endif
117849ab747fSPaolo Bonzini ret = 8;
117949ab747fSPaolo Bonzini break;
118049ab747fSPaolo Bonzini }
118149ab747fSPaolo Bonzini } else {
118249ab747fSPaolo Bonzini /* VGA */
118349ab747fSPaolo Bonzini ret = 0;
118449ab747fSPaolo Bonzini }
118549ab747fSPaolo Bonzini
118649ab747fSPaolo Bonzini return ret;
118749ab747fSPaolo Bonzini }
118849ab747fSPaolo Bonzini
cirrus_get_resolution(VGACommonState * s,int * pwidth,int * pheight)118949ab747fSPaolo Bonzini static void cirrus_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
119049ab747fSPaolo Bonzini {
119149ab747fSPaolo Bonzini int width, height;
119249ab747fSPaolo Bonzini
119349ab747fSPaolo Bonzini width = (s->cr[0x01] + 1) * 8;
119449ab747fSPaolo Bonzini height = s->cr[0x12] |
119549ab747fSPaolo Bonzini ((s->cr[0x07] & 0x02) << 7) |
119649ab747fSPaolo Bonzini ((s->cr[0x07] & 0x40) << 3);
119749ab747fSPaolo Bonzini height = (height + 1);
119849ab747fSPaolo Bonzini /* interlace support */
119949ab747fSPaolo Bonzini if (s->cr[0x1a] & 0x01)
120049ab747fSPaolo Bonzini height = height * 2;
120149ab747fSPaolo Bonzini *pwidth = width;
120249ab747fSPaolo Bonzini *pheight = height;
120349ab747fSPaolo Bonzini }
120449ab747fSPaolo Bonzini
120549ab747fSPaolo Bonzini /***************************************
120649ab747fSPaolo Bonzini *
120749ab747fSPaolo Bonzini * bank memory
120849ab747fSPaolo Bonzini *
120949ab747fSPaolo Bonzini ***************************************/
121049ab747fSPaolo Bonzini
cirrus_update_bank_ptr(CirrusVGAState * s,unsigned bank_index)121149ab747fSPaolo Bonzini static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
121249ab747fSPaolo Bonzini {
121349ab747fSPaolo Bonzini unsigned offset;
121449ab747fSPaolo Bonzini unsigned limit;
121549ab747fSPaolo Bonzini
121649ab747fSPaolo Bonzini if ((s->vga.gr[0x0b] & 0x01) != 0) /* dual bank */
121749ab747fSPaolo Bonzini offset = s->vga.gr[0x09 + bank_index];
121849ab747fSPaolo Bonzini else /* single bank */
121949ab747fSPaolo Bonzini offset = s->vga.gr[0x09];
122049ab747fSPaolo Bonzini
122149ab747fSPaolo Bonzini if ((s->vga.gr[0x0b] & 0x20) != 0)
122249ab747fSPaolo Bonzini offset <<= 14;
122349ab747fSPaolo Bonzini else
122449ab747fSPaolo Bonzini offset <<= 12;
122549ab747fSPaolo Bonzini
122649ab747fSPaolo Bonzini if (s->real_vram_size <= offset)
122749ab747fSPaolo Bonzini limit = 0;
122849ab747fSPaolo Bonzini else
122949ab747fSPaolo Bonzini limit = s->real_vram_size - offset;
123049ab747fSPaolo Bonzini
123149ab747fSPaolo Bonzini if (((s->vga.gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
123249ab747fSPaolo Bonzini if (limit > 0x8000) {
123349ab747fSPaolo Bonzini offset += 0x8000;
123449ab747fSPaolo Bonzini limit -= 0x8000;
123549ab747fSPaolo Bonzini } else {
123649ab747fSPaolo Bonzini limit = 0;
123749ab747fSPaolo Bonzini }
123849ab747fSPaolo Bonzini }
123949ab747fSPaolo Bonzini
124049ab747fSPaolo Bonzini if (limit > 0) {
124149ab747fSPaolo Bonzini s->cirrus_bank_base[bank_index] = offset;
124249ab747fSPaolo Bonzini s->cirrus_bank_limit[bank_index] = limit;
124349ab747fSPaolo Bonzini } else {
124449ab747fSPaolo Bonzini s->cirrus_bank_base[bank_index] = 0;
124549ab747fSPaolo Bonzini s->cirrus_bank_limit[bank_index] = 0;
124649ab747fSPaolo Bonzini }
124749ab747fSPaolo Bonzini }
124849ab747fSPaolo Bonzini
124949ab747fSPaolo Bonzini /***************************************
125049ab747fSPaolo Bonzini *
125149ab747fSPaolo Bonzini * I/O access between 0x3c4-0x3c5
125249ab747fSPaolo Bonzini *
125349ab747fSPaolo Bonzini ***************************************/
125449ab747fSPaolo Bonzini
cirrus_vga_read_sr(CirrusVGAState * s)125549ab747fSPaolo Bonzini static int cirrus_vga_read_sr(CirrusVGAState * s)
125649ab747fSPaolo Bonzini {
125749ab747fSPaolo Bonzini switch (s->vga.sr_index) {
125849ab747fSPaolo Bonzini case 0x00: // Standard VGA
125949ab747fSPaolo Bonzini case 0x01: // Standard VGA
126049ab747fSPaolo Bonzini case 0x02: // Standard VGA
126149ab747fSPaolo Bonzini case 0x03: // Standard VGA
126249ab747fSPaolo Bonzini case 0x04: // Standard VGA
126349ab747fSPaolo Bonzini return s->vga.sr[s->vga.sr_index];
126449ab747fSPaolo Bonzini case 0x06: // Unlock Cirrus extensions
126549ab747fSPaolo Bonzini return s->vga.sr[s->vga.sr_index];
126649ab747fSPaolo Bonzini case 0x10:
126749ab747fSPaolo Bonzini case 0x30:
126849ab747fSPaolo Bonzini case 0x50:
126949ab747fSPaolo Bonzini case 0x70: // Graphics Cursor X
127049ab747fSPaolo Bonzini case 0x90:
127149ab747fSPaolo Bonzini case 0xb0:
127249ab747fSPaolo Bonzini case 0xd0:
127349ab747fSPaolo Bonzini case 0xf0: // Graphics Cursor X
127449ab747fSPaolo Bonzini return s->vga.sr[0x10];
127549ab747fSPaolo Bonzini case 0x11:
127649ab747fSPaolo Bonzini case 0x31:
127749ab747fSPaolo Bonzini case 0x51:
127849ab747fSPaolo Bonzini case 0x71: // Graphics Cursor Y
127949ab747fSPaolo Bonzini case 0x91:
128049ab747fSPaolo Bonzini case 0xb1:
128149ab747fSPaolo Bonzini case 0xd1:
128249ab747fSPaolo Bonzini case 0xf1: // Graphics Cursor Y
128349ab747fSPaolo Bonzini return s->vga.sr[0x11];
128449ab747fSPaolo Bonzini case 0x05: // ???
128549ab747fSPaolo Bonzini case 0x07: // Extended Sequencer Mode
128649ab747fSPaolo Bonzini case 0x08: // EEPROM Control
128749ab747fSPaolo Bonzini case 0x09: // Scratch Register 0
128849ab747fSPaolo Bonzini case 0x0a: // Scratch Register 1
128949ab747fSPaolo Bonzini case 0x0b: // VCLK 0
129049ab747fSPaolo Bonzini case 0x0c: // VCLK 1
129149ab747fSPaolo Bonzini case 0x0d: // VCLK 2
129249ab747fSPaolo Bonzini case 0x0e: // VCLK 3
129349ab747fSPaolo Bonzini case 0x0f: // DRAM Control
129449ab747fSPaolo Bonzini case 0x12: // Graphics Cursor Attribute
129549ab747fSPaolo Bonzini case 0x13: // Graphics Cursor Pattern Address
129649ab747fSPaolo Bonzini case 0x14: // Scratch Register 2
129749ab747fSPaolo Bonzini case 0x15: // Scratch Register 3
129849ab747fSPaolo Bonzini case 0x16: // Performance Tuning Register
129949ab747fSPaolo Bonzini case 0x17: // Configuration Readback and Extended Control
130049ab747fSPaolo Bonzini case 0x18: // Signature Generator Control
130149ab747fSPaolo Bonzini case 0x19: // Signal Generator Result
130249ab747fSPaolo Bonzini case 0x1a: // Signal Generator Result
130349ab747fSPaolo Bonzini case 0x1b: // VCLK 0 Denominator & Post
130449ab747fSPaolo Bonzini case 0x1c: // VCLK 1 Denominator & Post
130549ab747fSPaolo Bonzini case 0x1d: // VCLK 2 Denominator & Post
130649ab747fSPaolo Bonzini case 0x1e: // VCLK 3 Denominator & Post
130749ab747fSPaolo Bonzini case 0x1f: // BIOS Write Enable and MCLK select
130849ab747fSPaolo Bonzini #ifdef DEBUG_CIRRUS
130949ab747fSPaolo Bonzini printf("cirrus: handled inport sr_index %02x\n", s->vga.sr_index);
131049ab747fSPaolo Bonzini #endif
131149ab747fSPaolo Bonzini return s->vga.sr[s->vga.sr_index];
131249ab747fSPaolo Bonzini default:
13132b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
13142b55f4d3SPhilippe Mathieu-Daudé "cirrus: inport sr_index 0x%02x\n", s->vga.sr_index);
131549ab747fSPaolo Bonzini return 0xff;
131649ab747fSPaolo Bonzini }
131749ab747fSPaolo Bonzini }
131849ab747fSPaolo Bonzini
cirrus_vga_write_sr(CirrusVGAState * s,uint32_t val)131949ab747fSPaolo Bonzini static void cirrus_vga_write_sr(CirrusVGAState * s, uint32_t val)
132049ab747fSPaolo Bonzini {
132149ab747fSPaolo Bonzini switch (s->vga.sr_index) {
132249ab747fSPaolo Bonzini case 0x00: // Standard VGA
132349ab747fSPaolo Bonzini case 0x01: // Standard VGA
132449ab747fSPaolo Bonzini case 0x02: // Standard VGA
132549ab747fSPaolo Bonzini case 0x03: // Standard VGA
132649ab747fSPaolo Bonzini case 0x04: // Standard VGA
132749ab747fSPaolo Bonzini s->vga.sr[s->vga.sr_index] = val & sr_mask[s->vga.sr_index];
132849ab747fSPaolo Bonzini if (s->vga.sr_index == 1)
132949ab747fSPaolo Bonzini s->vga.update_retrace_info(&s->vga);
133049ab747fSPaolo Bonzini break;
133149ab747fSPaolo Bonzini case 0x06: // Unlock Cirrus extensions
133249ab747fSPaolo Bonzini val &= 0x17;
133349ab747fSPaolo Bonzini if (val == 0x12) {
133449ab747fSPaolo Bonzini s->vga.sr[s->vga.sr_index] = 0x12;
133549ab747fSPaolo Bonzini } else {
133649ab747fSPaolo Bonzini s->vga.sr[s->vga.sr_index] = 0x0f;
133749ab747fSPaolo Bonzini }
133849ab747fSPaolo Bonzini break;
133949ab747fSPaolo Bonzini case 0x10:
134049ab747fSPaolo Bonzini case 0x30:
134149ab747fSPaolo Bonzini case 0x50:
134249ab747fSPaolo Bonzini case 0x70: // Graphics Cursor X
134349ab747fSPaolo Bonzini case 0x90:
134449ab747fSPaolo Bonzini case 0xb0:
134549ab747fSPaolo Bonzini case 0xd0:
134649ab747fSPaolo Bonzini case 0xf0: // Graphics Cursor X
134749ab747fSPaolo Bonzini s->vga.sr[0x10] = val;
134822382bb9SGerd Hoffmann s->vga.hw_cursor_x = (val << 3) | (s->vga.sr_index >> 5);
134949ab747fSPaolo Bonzini break;
135049ab747fSPaolo Bonzini case 0x11:
135149ab747fSPaolo Bonzini case 0x31:
135249ab747fSPaolo Bonzini case 0x51:
135349ab747fSPaolo Bonzini case 0x71: // Graphics Cursor Y
135449ab747fSPaolo Bonzini case 0x91:
135549ab747fSPaolo Bonzini case 0xb1:
135649ab747fSPaolo Bonzini case 0xd1:
135749ab747fSPaolo Bonzini case 0xf1: // Graphics Cursor Y
135849ab747fSPaolo Bonzini s->vga.sr[0x11] = val;
135922382bb9SGerd Hoffmann s->vga.hw_cursor_y = (val << 3) | (s->vga.sr_index >> 5);
136049ab747fSPaolo Bonzini break;
136149ab747fSPaolo Bonzini case 0x07: // Extended Sequencer Mode
136249ab747fSPaolo Bonzini cirrus_update_memory_access(s);
1363edd7541bSPaolo Bonzini /* fall through */
136449ab747fSPaolo Bonzini case 0x08: // EEPROM Control
136549ab747fSPaolo Bonzini case 0x09: // Scratch Register 0
136649ab747fSPaolo Bonzini case 0x0a: // Scratch Register 1
136749ab747fSPaolo Bonzini case 0x0b: // VCLK 0
136849ab747fSPaolo Bonzini case 0x0c: // VCLK 1
136949ab747fSPaolo Bonzini case 0x0d: // VCLK 2
137049ab747fSPaolo Bonzini case 0x0e: // VCLK 3
137149ab747fSPaolo Bonzini case 0x0f: // DRAM Control
137249ab747fSPaolo Bonzini case 0x13: // Graphics Cursor Pattern Address
137349ab747fSPaolo Bonzini case 0x14: // Scratch Register 2
137449ab747fSPaolo Bonzini case 0x15: // Scratch Register 3
137549ab747fSPaolo Bonzini case 0x16: // Performance Tuning Register
137649ab747fSPaolo Bonzini case 0x18: // Signature Generator Control
137749ab747fSPaolo Bonzini case 0x19: // Signature Generator Result
137849ab747fSPaolo Bonzini case 0x1a: // Signature Generator Result
137949ab747fSPaolo Bonzini case 0x1b: // VCLK 0 Denominator & Post
138049ab747fSPaolo Bonzini case 0x1c: // VCLK 1 Denominator & Post
138149ab747fSPaolo Bonzini case 0x1d: // VCLK 2 Denominator & Post
138249ab747fSPaolo Bonzini case 0x1e: // VCLK 3 Denominator & Post
138349ab747fSPaolo Bonzini case 0x1f: // BIOS Write Enable and MCLK select
138449ab747fSPaolo Bonzini s->vga.sr[s->vga.sr_index] = val;
138549ab747fSPaolo Bonzini #ifdef DEBUG_CIRRUS
138649ab747fSPaolo Bonzini printf("cirrus: handled outport sr_index %02x, sr_value %02x\n",
138749ab747fSPaolo Bonzini s->vga.sr_index, val);
138849ab747fSPaolo Bonzini #endif
138949ab747fSPaolo Bonzini break;
1390b9fd11b8SBenjamin Herrenschmidt case 0x12: // Graphics Cursor Attribute
1391b9fd11b8SBenjamin Herrenschmidt s->vga.sr[0x12] = val;
1392b9fd11b8SBenjamin Herrenschmidt s->vga.force_shadow = !!(val & CIRRUS_CURSOR_SHOW);
1393b9fd11b8SBenjamin Herrenschmidt #ifdef DEBUG_CIRRUS
1394b9fd11b8SBenjamin Herrenschmidt printf("cirrus: cursor ctl SR12=%02x (force shadow: %d)\n",
1395b9fd11b8SBenjamin Herrenschmidt val, s->vga.force_shadow);
1396b9fd11b8SBenjamin Herrenschmidt #endif
1397b9fd11b8SBenjamin Herrenschmidt break;
139849ab747fSPaolo Bonzini case 0x17: // Configuration Readback and Extended Control
139949ab747fSPaolo Bonzini s->vga.sr[s->vga.sr_index] = (s->vga.sr[s->vga.sr_index] & 0x38)
140049ab747fSPaolo Bonzini | (val & 0xc7);
140149ab747fSPaolo Bonzini cirrus_update_memory_access(s);
140249ab747fSPaolo Bonzini break;
140349ab747fSPaolo Bonzini default:
14042b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
14052b55f4d3SPhilippe Mathieu-Daudé "cirrus: outport sr_index 0x%02x, sr_value 0x%02x\n",
140649ab747fSPaolo Bonzini s->vga.sr_index, val);
140749ab747fSPaolo Bonzini break;
140849ab747fSPaolo Bonzini }
140949ab747fSPaolo Bonzini }
141049ab747fSPaolo Bonzini
141149ab747fSPaolo Bonzini /***************************************
141249ab747fSPaolo Bonzini *
141349ab747fSPaolo Bonzini * I/O access at 0x3c6
141449ab747fSPaolo Bonzini *
141549ab747fSPaolo Bonzini ***************************************/
141649ab747fSPaolo Bonzini
cirrus_read_hidden_dac(CirrusVGAState * s)141749ab747fSPaolo Bonzini static int cirrus_read_hidden_dac(CirrusVGAState * s)
141849ab747fSPaolo Bonzini {
141949ab747fSPaolo Bonzini if (++s->cirrus_hidden_dac_lockindex == 5) {
142049ab747fSPaolo Bonzini s->cirrus_hidden_dac_lockindex = 0;
142149ab747fSPaolo Bonzini return s->cirrus_hidden_dac_data;
142249ab747fSPaolo Bonzini }
142349ab747fSPaolo Bonzini return 0xff;
142449ab747fSPaolo Bonzini }
142549ab747fSPaolo Bonzini
cirrus_write_hidden_dac(CirrusVGAState * s,int reg_value)142649ab747fSPaolo Bonzini static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
142749ab747fSPaolo Bonzini {
142849ab747fSPaolo Bonzini if (s->cirrus_hidden_dac_lockindex == 4) {
142949ab747fSPaolo Bonzini s->cirrus_hidden_dac_data = reg_value;
143049ab747fSPaolo Bonzini #if defined(DEBUG_CIRRUS)
143149ab747fSPaolo Bonzini printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
143249ab747fSPaolo Bonzini #endif
143349ab747fSPaolo Bonzini }
143449ab747fSPaolo Bonzini s->cirrus_hidden_dac_lockindex = 0;
143549ab747fSPaolo Bonzini }
143649ab747fSPaolo Bonzini
143749ab747fSPaolo Bonzini /***************************************
143849ab747fSPaolo Bonzini *
143949ab747fSPaolo Bonzini * I/O access at 0x3c9
144049ab747fSPaolo Bonzini *
144149ab747fSPaolo Bonzini ***************************************/
144249ab747fSPaolo Bonzini
cirrus_vga_read_palette(CirrusVGAState * s)144349ab747fSPaolo Bonzini static int cirrus_vga_read_palette(CirrusVGAState * s)
144449ab747fSPaolo Bonzini {
144549ab747fSPaolo Bonzini int val;
144649ab747fSPaolo Bonzini
144749ab747fSPaolo Bonzini if ((s->vga.sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) {
144849ab747fSPaolo Bonzini val = s->cirrus_hidden_palette[(s->vga.dac_read_index & 0x0f) * 3 +
144949ab747fSPaolo Bonzini s->vga.dac_sub_index];
145049ab747fSPaolo Bonzini } else {
145149ab747fSPaolo Bonzini val = s->vga.palette[s->vga.dac_read_index * 3 + s->vga.dac_sub_index];
145249ab747fSPaolo Bonzini }
145349ab747fSPaolo Bonzini if (++s->vga.dac_sub_index == 3) {
145449ab747fSPaolo Bonzini s->vga.dac_sub_index = 0;
145549ab747fSPaolo Bonzini s->vga.dac_read_index++;
145649ab747fSPaolo Bonzini }
145749ab747fSPaolo Bonzini return val;
145849ab747fSPaolo Bonzini }
145949ab747fSPaolo Bonzini
cirrus_vga_write_palette(CirrusVGAState * s,int reg_value)146049ab747fSPaolo Bonzini static void cirrus_vga_write_palette(CirrusVGAState * s, int reg_value)
146149ab747fSPaolo Bonzini {
146249ab747fSPaolo Bonzini s->vga.dac_cache[s->vga.dac_sub_index] = reg_value;
146349ab747fSPaolo Bonzini if (++s->vga.dac_sub_index == 3) {
146449ab747fSPaolo Bonzini if ((s->vga.sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) {
146549ab747fSPaolo Bonzini memcpy(&s->cirrus_hidden_palette[(s->vga.dac_write_index & 0x0f) * 3],
146649ab747fSPaolo Bonzini s->vga.dac_cache, 3);
146749ab747fSPaolo Bonzini } else {
146849ab747fSPaolo Bonzini memcpy(&s->vga.palette[s->vga.dac_write_index * 3], s->vga.dac_cache, 3);
146949ab747fSPaolo Bonzini }
147049ab747fSPaolo Bonzini /* XXX update cursor */
147149ab747fSPaolo Bonzini s->vga.dac_sub_index = 0;
147249ab747fSPaolo Bonzini s->vga.dac_write_index++;
147349ab747fSPaolo Bonzini }
147449ab747fSPaolo Bonzini }
147549ab747fSPaolo Bonzini
147649ab747fSPaolo Bonzini /***************************************
147749ab747fSPaolo Bonzini *
147849ab747fSPaolo Bonzini * I/O access between 0x3ce-0x3cf
147949ab747fSPaolo Bonzini *
148049ab747fSPaolo Bonzini ***************************************/
148149ab747fSPaolo Bonzini
cirrus_vga_read_gr(CirrusVGAState * s,unsigned reg_index)148249ab747fSPaolo Bonzini static int cirrus_vga_read_gr(CirrusVGAState * s, unsigned reg_index)
148349ab747fSPaolo Bonzini {
148449ab747fSPaolo Bonzini switch (reg_index) {
148549ab747fSPaolo Bonzini case 0x00: // Standard VGA, BGCOLOR 0x000000ff
148649ab747fSPaolo Bonzini return s->cirrus_shadow_gr0;
148749ab747fSPaolo Bonzini case 0x01: // Standard VGA, FGCOLOR 0x000000ff
148849ab747fSPaolo Bonzini return s->cirrus_shadow_gr1;
148949ab747fSPaolo Bonzini case 0x02: // Standard VGA
149049ab747fSPaolo Bonzini case 0x03: // Standard VGA
149149ab747fSPaolo Bonzini case 0x04: // Standard VGA
149249ab747fSPaolo Bonzini case 0x06: // Standard VGA
149349ab747fSPaolo Bonzini case 0x07: // Standard VGA
149449ab747fSPaolo Bonzini case 0x08: // Standard VGA
149549ab747fSPaolo Bonzini return s->vga.gr[s->vga.gr_index];
149649ab747fSPaolo Bonzini case 0x05: // Standard VGA, Cirrus extended mode
149749ab747fSPaolo Bonzini default:
149849ab747fSPaolo Bonzini break;
149949ab747fSPaolo Bonzini }
150049ab747fSPaolo Bonzini
150149ab747fSPaolo Bonzini if (reg_index < 0x3a) {
150249ab747fSPaolo Bonzini return s->vga.gr[reg_index];
150349ab747fSPaolo Bonzini } else {
15042b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
15052b55f4d3SPhilippe Mathieu-Daudé "cirrus: inport gr_index 0x%02x\n", reg_index);
150649ab747fSPaolo Bonzini return 0xff;
150749ab747fSPaolo Bonzini }
150849ab747fSPaolo Bonzini }
150949ab747fSPaolo Bonzini
151049ab747fSPaolo Bonzini static void
cirrus_vga_write_gr(CirrusVGAState * s,unsigned reg_index,int reg_value)151149ab747fSPaolo Bonzini cirrus_vga_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
151249ab747fSPaolo Bonzini {
1513bee61ca2SPhilippe Mathieu-Daudé trace_vga_cirrus_write_gr(reg_index, reg_value);
151449ab747fSPaolo Bonzini switch (reg_index) {
151549ab747fSPaolo Bonzini case 0x00: // Standard VGA, BGCOLOR 0x000000ff
151649ab747fSPaolo Bonzini s->vga.gr[reg_index] = reg_value & gr_mask[reg_index];
151749ab747fSPaolo Bonzini s->cirrus_shadow_gr0 = reg_value;
151849ab747fSPaolo Bonzini break;
151949ab747fSPaolo Bonzini case 0x01: // Standard VGA, FGCOLOR 0x000000ff
152049ab747fSPaolo Bonzini s->vga.gr[reg_index] = reg_value & gr_mask[reg_index];
152149ab747fSPaolo Bonzini s->cirrus_shadow_gr1 = reg_value;
152249ab747fSPaolo Bonzini break;
152349ab747fSPaolo Bonzini case 0x02: // Standard VGA
152449ab747fSPaolo Bonzini case 0x03: // Standard VGA
152549ab747fSPaolo Bonzini case 0x04: // Standard VGA
152649ab747fSPaolo Bonzini case 0x06: // Standard VGA
152749ab747fSPaolo Bonzini case 0x07: // Standard VGA
152849ab747fSPaolo Bonzini case 0x08: // Standard VGA
152949ab747fSPaolo Bonzini s->vga.gr[reg_index] = reg_value & gr_mask[reg_index];
153049ab747fSPaolo Bonzini break;
153149ab747fSPaolo Bonzini case 0x05: // Standard VGA, Cirrus extended mode
153249ab747fSPaolo Bonzini s->vga.gr[reg_index] = reg_value & 0x7f;
153349ab747fSPaolo Bonzini cirrus_update_memory_access(s);
153449ab747fSPaolo Bonzini break;
153549ab747fSPaolo Bonzini case 0x09: // bank offset #0
153649ab747fSPaolo Bonzini case 0x0A: // bank offset #1
153749ab747fSPaolo Bonzini s->vga.gr[reg_index] = reg_value;
153849ab747fSPaolo Bonzini cirrus_update_bank_ptr(s, 0);
153949ab747fSPaolo Bonzini cirrus_update_bank_ptr(s, 1);
154049ab747fSPaolo Bonzini cirrus_update_memory_access(s);
154149ab747fSPaolo Bonzini break;
154249ab747fSPaolo Bonzini case 0x0B:
154349ab747fSPaolo Bonzini s->vga.gr[reg_index] = reg_value;
154449ab747fSPaolo Bonzini cirrus_update_bank_ptr(s, 0);
154549ab747fSPaolo Bonzini cirrus_update_bank_ptr(s, 1);
154649ab747fSPaolo Bonzini cirrus_update_memory_access(s);
154749ab747fSPaolo Bonzini break;
154849ab747fSPaolo Bonzini case 0x10: // BGCOLOR 0x0000ff00
154949ab747fSPaolo Bonzini case 0x11: // FGCOLOR 0x0000ff00
155049ab747fSPaolo Bonzini case 0x12: // BGCOLOR 0x00ff0000
155149ab747fSPaolo Bonzini case 0x13: // FGCOLOR 0x00ff0000
155249ab747fSPaolo Bonzini case 0x14: // BGCOLOR 0xff000000
155349ab747fSPaolo Bonzini case 0x15: // FGCOLOR 0xff000000
155449ab747fSPaolo Bonzini case 0x20: // BLT WIDTH 0x0000ff
155549ab747fSPaolo Bonzini case 0x22: // BLT HEIGHT 0x0000ff
155649ab747fSPaolo Bonzini case 0x24: // BLT DEST PITCH 0x0000ff
155749ab747fSPaolo Bonzini case 0x26: // BLT SRC PITCH 0x0000ff
155849ab747fSPaolo Bonzini case 0x28: // BLT DEST ADDR 0x0000ff
155949ab747fSPaolo Bonzini case 0x29: // BLT DEST ADDR 0x00ff00
156049ab747fSPaolo Bonzini case 0x2c: // BLT SRC ADDR 0x0000ff
156149ab747fSPaolo Bonzini case 0x2d: // BLT SRC ADDR 0x00ff00
156249ab747fSPaolo Bonzini case 0x2f: // BLT WRITEMASK
156349ab747fSPaolo Bonzini case 0x30: // BLT MODE
156449ab747fSPaolo Bonzini case 0x32: // RASTER OP
156549ab747fSPaolo Bonzini case 0x33: // BLT MODEEXT
156649ab747fSPaolo Bonzini case 0x34: // BLT TRANSPARENT COLOR 0x00ff
156749ab747fSPaolo Bonzini case 0x35: // BLT TRANSPARENT COLOR 0xff00
156849ab747fSPaolo Bonzini case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff
156949ab747fSPaolo Bonzini case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00
157049ab747fSPaolo Bonzini s->vga.gr[reg_index] = reg_value;
157149ab747fSPaolo Bonzini break;
157249ab747fSPaolo Bonzini case 0x21: // BLT WIDTH 0x001f00
157349ab747fSPaolo Bonzini case 0x23: // BLT HEIGHT 0x001f00
157449ab747fSPaolo Bonzini case 0x25: // BLT DEST PITCH 0x001f00
157549ab747fSPaolo Bonzini case 0x27: // BLT SRC PITCH 0x001f00
157649ab747fSPaolo Bonzini s->vga.gr[reg_index] = reg_value & 0x1f;
157749ab747fSPaolo Bonzini break;
157849ab747fSPaolo Bonzini case 0x2a: // BLT DEST ADDR 0x3f0000
157949ab747fSPaolo Bonzini s->vga.gr[reg_index] = reg_value & 0x3f;
158049ab747fSPaolo Bonzini /* if auto start mode, starts bit blt now */
158149ab747fSPaolo Bonzini if (s->vga.gr[0x31] & CIRRUS_BLT_AUTOSTART) {
158249ab747fSPaolo Bonzini cirrus_bitblt_start(s);
158349ab747fSPaolo Bonzini }
158449ab747fSPaolo Bonzini break;
158549ab747fSPaolo Bonzini case 0x2e: // BLT SRC ADDR 0x3f0000
158649ab747fSPaolo Bonzini s->vga.gr[reg_index] = reg_value & 0x3f;
158749ab747fSPaolo Bonzini break;
158849ab747fSPaolo Bonzini case 0x31: // BLT STATUS/START
158949ab747fSPaolo Bonzini cirrus_write_bitblt(s, reg_value);
159049ab747fSPaolo Bonzini break;
159149ab747fSPaolo Bonzini default:
15922b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
15932b55f4d3SPhilippe Mathieu-Daudé "cirrus: outport gr_index 0x%02x, gr_value 0x%02x\n",
15942b55f4d3SPhilippe Mathieu-Daudé reg_index, reg_value);
159549ab747fSPaolo Bonzini break;
159649ab747fSPaolo Bonzini }
159749ab747fSPaolo Bonzini }
159849ab747fSPaolo Bonzini
159949ab747fSPaolo Bonzini /***************************************
160049ab747fSPaolo Bonzini *
160149ab747fSPaolo Bonzini * I/O access between 0x3d4-0x3d5
160249ab747fSPaolo Bonzini *
160349ab747fSPaolo Bonzini ***************************************/
160449ab747fSPaolo Bonzini
cirrus_vga_read_cr(CirrusVGAState * s,unsigned reg_index)160549ab747fSPaolo Bonzini static int cirrus_vga_read_cr(CirrusVGAState * s, unsigned reg_index)
160649ab747fSPaolo Bonzini {
160749ab747fSPaolo Bonzini switch (reg_index) {
160849ab747fSPaolo Bonzini case 0x00: // Standard VGA
160949ab747fSPaolo Bonzini case 0x01: // Standard VGA
161049ab747fSPaolo Bonzini case 0x02: // Standard VGA
161149ab747fSPaolo Bonzini case 0x03: // Standard VGA
161249ab747fSPaolo Bonzini case 0x04: // Standard VGA
161349ab747fSPaolo Bonzini case 0x05: // Standard VGA
161449ab747fSPaolo Bonzini case 0x06: // Standard VGA
161549ab747fSPaolo Bonzini case 0x07: // Standard VGA
161649ab747fSPaolo Bonzini case 0x08: // Standard VGA
161749ab747fSPaolo Bonzini case 0x09: // Standard VGA
161849ab747fSPaolo Bonzini case 0x0a: // Standard VGA
161949ab747fSPaolo Bonzini case 0x0b: // Standard VGA
162049ab747fSPaolo Bonzini case 0x0c: // Standard VGA
162149ab747fSPaolo Bonzini case 0x0d: // Standard VGA
162249ab747fSPaolo Bonzini case 0x0e: // Standard VGA
162349ab747fSPaolo Bonzini case 0x0f: // Standard VGA
162449ab747fSPaolo Bonzini case 0x10: // Standard VGA
162549ab747fSPaolo Bonzini case 0x11: // Standard VGA
162649ab747fSPaolo Bonzini case 0x12: // Standard VGA
162749ab747fSPaolo Bonzini case 0x13: // Standard VGA
162849ab747fSPaolo Bonzini case 0x14: // Standard VGA
162949ab747fSPaolo Bonzini case 0x15: // Standard VGA
163049ab747fSPaolo Bonzini case 0x16: // Standard VGA
163149ab747fSPaolo Bonzini case 0x17: // Standard VGA
163249ab747fSPaolo Bonzini case 0x18: // Standard VGA
163349ab747fSPaolo Bonzini return s->vga.cr[s->vga.cr_index];
163449ab747fSPaolo Bonzini case 0x24: // Attribute Controller Toggle Readback (R)
163549ab747fSPaolo Bonzini return (s->vga.ar_flip_flop << 7);
163649ab747fSPaolo Bonzini case 0x19: // Interlace End
163749ab747fSPaolo Bonzini case 0x1a: // Miscellaneous Control
163849ab747fSPaolo Bonzini case 0x1b: // Extended Display Control
163949ab747fSPaolo Bonzini case 0x1c: // Sync Adjust and Genlock
164049ab747fSPaolo Bonzini case 0x1d: // Overlay Extended Control
164149ab747fSPaolo Bonzini case 0x22: // Graphics Data Latches Readback (R)
164249ab747fSPaolo Bonzini case 0x25: // Part Status
164349ab747fSPaolo Bonzini case 0x27: // Part ID (R)
164449ab747fSPaolo Bonzini return s->vga.cr[s->vga.cr_index];
164549ab747fSPaolo Bonzini case 0x26: // Attribute Controller Index Readback (R)
164649ab747fSPaolo Bonzini return s->vga.ar_index & 0x3f;
164749ab747fSPaolo Bonzini default:
16482b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
16492b55f4d3SPhilippe Mathieu-Daudé "cirrus: inport cr_index 0x%02x\n", reg_index);
165049ab747fSPaolo Bonzini return 0xff;
165149ab747fSPaolo Bonzini }
165249ab747fSPaolo Bonzini }
165349ab747fSPaolo Bonzini
cirrus_vga_write_cr(CirrusVGAState * s,int reg_value)165449ab747fSPaolo Bonzini static void cirrus_vga_write_cr(CirrusVGAState * s, int reg_value)
165549ab747fSPaolo Bonzini {
165649ab747fSPaolo Bonzini switch (s->vga.cr_index) {
165749ab747fSPaolo Bonzini case 0x00: // Standard VGA
165849ab747fSPaolo Bonzini case 0x01: // Standard VGA
165949ab747fSPaolo Bonzini case 0x02: // Standard VGA
166049ab747fSPaolo Bonzini case 0x03: // Standard VGA
166149ab747fSPaolo Bonzini case 0x04: // Standard VGA
166249ab747fSPaolo Bonzini case 0x05: // Standard VGA
166349ab747fSPaolo Bonzini case 0x06: // Standard VGA
166449ab747fSPaolo Bonzini case 0x07: // Standard VGA
166549ab747fSPaolo Bonzini case 0x08: // Standard VGA
166649ab747fSPaolo Bonzini case 0x09: // Standard VGA
166749ab747fSPaolo Bonzini case 0x0a: // Standard VGA
166849ab747fSPaolo Bonzini case 0x0b: // Standard VGA
166949ab747fSPaolo Bonzini case 0x0c: // Standard VGA
167049ab747fSPaolo Bonzini case 0x0d: // Standard VGA
167149ab747fSPaolo Bonzini case 0x0e: // Standard VGA
167249ab747fSPaolo Bonzini case 0x0f: // Standard VGA
167349ab747fSPaolo Bonzini case 0x10: // Standard VGA
167449ab747fSPaolo Bonzini case 0x11: // Standard VGA
167549ab747fSPaolo Bonzini case 0x12: // Standard VGA
167649ab747fSPaolo Bonzini case 0x13: // Standard VGA
167749ab747fSPaolo Bonzini case 0x14: // Standard VGA
167849ab747fSPaolo Bonzini case 0x15: // Standard VGA
167949ab747fSPaolo Bonzini case 0x16: // Standard VGA
168049ab747fSPaolo Bonzini case 0x17: // Standard VGA
168149ab747fSPaolo Bonzini case 0x18: // Standard VGA
168249ab747fSPaolo Bonzini /* handle CR0-7 protection */
168349ab747fSPaolo Bonzini if ((s->vga.cr[0x11] & 0x80) && s->vga.cr_index <= 7) {
168449ab747fSPaolo Bonzini /* can always write bit 4 of CR7 */
168549ab747fSPaolo Bonzini if (s->vga.cr_index == 7)
168649ab747fSPaolo Bonzini s->vga.cr[7] = (s->vga.cr[7] & ~0x10) | (reg_value & 0x10);
168749ab747fSPaolo Bonzini return;
168849ab747fSPaolo Bonzini }
168949ab747fSPaolo Bonzini s->vga.cr[s->vga.cr_index] = reg_value;
169049ab747fSPaolo Bonzini switch(s->vga.cr_index) {
169149ab747fSPaolo Bonzini case 0x00:
169249ab747fSPaolo Bonzini case 0x04:
169349ab747fSPaolo Bonzini case 0x05:
169449ab747fSPaolo Bonzini case 0x06:
169549ab747fSPaolo Bonzini case 0x07:
169649ab747fSPaolo Bonzini case 0x11:
169749ab747fSPaolo Bonzini case 0x17:
169849ab747fSPaolo Bonzini s->vga.update_retrace_info(&s->vga);
169949ab747fSPaolo Bonzini break;
170049ab747fSPaolo Bonzini }
170149ab747fSPaolo Bonzini break;
170249ab747fSPaolo Bonzini case 0x19: // Interlace End
170349ab747fSPaolo Bonzini case 0x1a: // Miscellaneous Control
170449ab747fSPaolo Bonzini case 0x1b: // Extended Display Control
170549ab747fSPaolo Bonzini case 0x1c: // Sync Adjust and Genlock
170649ab747fSPaolo Bonzini case 0x1d: // Overlay Extended Control
170749ab747fSPaolo Bonzini s->vga.cr[s->vga.cr_index] = reg_value;
170849ab747fSPaolo Bonzini #ifdef DEBUG_CIRRUS
170949ab747fSPaolo Bonzini printf("cirrus: handled outport cr_index %02x, cr_value %02x\n",
171049ab747fSPaolo Bonzini s->vga.cr_index, reg_value);
171149ab747fSPaolo Bonzini #endif
171249ab747fSPaolo Bonzini break;
171349ab747fSPaolo Bonzini case 0x22: // Graphics Data Latches Readback (R)
171449ab747fSPaolo Bonzini case 0x24: // Attribute Controller Toggle Readback (R)
171549ab747fSPaolo Bonzini case 0x26: // Attribute Controller Index Readback (R)
171649ab747fSPaolo Bonzini case 0x27: // Part ID (R)
171749ab747fSPaolo Bonzini break;
171849ab747fSPaolo Bonzini case 0x25: // Part Status
171949ab747fSPaolo Bonzini default:
17202b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
17212b55f4d3SPhilippe Mathieu-Daudé "cirrus: outport cr_index 0x%02x, cr_value 0x%02x\n",
172249ab747fSPaolo Bonzini s->vga.cr_index, reg_value);
172349ab747fSPaolo Bonzini break;
172449ab747fSPaolo Bonzini }
172549ab747fSPaolo Bonzini }
172649ab747fSPaolo Bonzini
172749ab747fSPaolo Bonzini /***************************************
172849ab747fSPaolo Bonzini *
172949ab747fSPaolo Bonzini * memory-mapped I/O (bitblt)
173049ab747fSPaolo Bonzini *
173149ab747fSPaolo Bonzini ***************************************/
173249ab747fSPaolo Bonzini
cirrus_mmio_blt_read(CirrusVGAState * s,unsigned address)173349ab747fSPaolo Bonzini static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
173449ab747fSPaolo Bonzini {
173549ab747fSPaolo Bonzini int value = 0xff;
173649ab747fSPaolo Bonzini
173749ab747fSPaolo Bonzini switch (address) {
173849ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTBGCOLOR + 0):
173949ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x00);
174049ab747fSPaolo Bonzini break;
174149ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTBGCOLOR + 1):
174249ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x10);
174349ab747fSPaolo Bonzini break;
174449ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTBGCOLOR + 2):
174549ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x12);
174649ab747fSPaolo Bonzini break;
174749ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTBGCOLOR + 3):
174849ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x14);
174949ab747fSPaolo Bonzini break;
175049ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTFGCOLOR + 0):
175149ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x01);
175249ab747fSPaolo Bonzini break;
175349ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTFGCOLOR + 1):
175449ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x11);
175549ab747fSPaolo Bonzini break;
175649ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTFGCOLOR + 2):
175749ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x13);
175849ab747fSPaolo Bonzini break;
175949ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTFGCOLOR + 3):
176049ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x15);
176149ab747fSPaolo Bonzini break;
176249ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTWIDTH + 0):
176349ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x20);
176449ab747fSPaolo Bonzini break;
176549ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTWIDTH + 1):
176649ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x21);
176749ab747fSPaolo Bonzini break;
176849ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTHEIGHT + 0):
176949ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x22);
177049ab747fSPaolo Bonzini break;
177149ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTHEIGHT + 1):
177249ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x23);
177349ab747fSPaolo Bonzini break;
177449ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTDESTPITCH + 0):
177549ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x24);
177649ab747fSPaolo Bonzini break;
177749ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTDESTPITCH + 1):
177849ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x25);
177949ab747fSPaolo Bonzini break;
178049ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTSRCPITCH + 0):
178149ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x26);
178249ab747fSPaolo Bonzini break;
178349ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTSRCPITCH + 1):
178449ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x27);
178549ab747fSPaolo Bonzini break;
178649ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTDESTADDR + 0):
178749ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x28);
178849ab747fSPaolo Bonzini break;
178949ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTDESTADDR + 1):
179049ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x29);
179149ab747fSPaolo Bonzini break;
179249ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTDESTADDR + 2):
179349ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x2a);
179449ab747fSPaolo Bonzini break;
179549ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTSRCADDR + 0):
179649ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x2c);
179749ab747fSPaolo Bonzini break;
179849ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTSRCADDR + 1):
179949ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x2d);
180049ab747fSPaolo Bonzini break;
180149ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTSRCADDR + 2):
180249ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x2e);
180349ab747fSPaolo Bonzini break;
180449ab747fSPaolo Bonzini case CIRRUS_MMIO_BLTWRITEMASK:
180549ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x2f);
180649ab747fSPaolo Bonzini break;
180749ab747fSPaolo Bonzini case CIRRUS_MMIO_BLTMODE:
180849ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x30);
180949ab747fSPaolo Bonzini break;
181049ab747fSPaolo Bonzini case CIRRUS_MMIO_BLTROP:
181149ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x32);
181249ab747fSPaolo Bonzini break;
181349ab747fSPaolo Bonzini case CIRRUS_MMIO_BLTMODEEXT:
181449ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x33);
181549ab747fSPaolo Bonzini break;
181649ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
181749ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x34);
181849ab747fSPaolo Bonzini break;
181949ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
182049ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x35);
182149ab747fSPaolo Bonzini break;
182249ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
182349ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x38);
182449ab747fSPaolo Bonzini break;
182549ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
182649ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x39);
182749ab747fSPaolo Bonzini break;
182849ab747fSPaolo Bonzini case CIRRUS_MMIO_BLTSTATUS:
182949ab747fSPaolo Bonzini value = cirrus_vga_read_gr(s, 0x31);
183049ab747fSPaolo Bonzini break;
183149ab747fSPaolo Bonzini default:
18322b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
18332b55f4d3SPhilippe Mathieu-Daudé "cirrus: mmio read - address 0x%04x\n", address);
183449ab747fSPaolo Bonzini break;
183549ab747fSPaolo Bonzini }
183649ab747fSPaolo Bonzini
1837ec87f206SGerd Hoffmann trace_vga_cirrus_write_blt(address, value);
183849ab747fSPaolo Bonzini return (uint8_t) value;
183949ab747fSPaolo Bonzini }
184049ab747fSPaolo Bonzini
cirrus_mmio_blt_write(CirrusVGAState * s,unsigned address,uint8_t value)184149ab747fSPaolo Bonzini static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address,
184249ab747fSPaolo Bonzini uint8_t value)
184349ab747fSPaolo Bonzini {
1844ec87f206SGerd Hoffmann trace_vga_cirrus_write_blt(address, value);
184549ab747fSPaolo Bonzini switch (address) {
184649ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTBGCOLOR + 0):
184749ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x00, value);
184849ab747fSPaolo Bonzini break;
184949ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTBGCOLOR + 1):
185049ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x10, value);
185149ab747fSPaolo Bonzini break;
185249ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTBGCOLOR + 2):
185349ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x12, value);
185449ab747fSPaolo Bonzini break;
185549ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTBGCOLOR + 3):
185649ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x14, value);
185749ab747fSPaolo Bonzini break;
185849ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTFGCOLOR + 0):
185949ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x01, value);
186049ab747fSPaolo Bonzini break;
186149ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTFGCOLOR + 1):
186249ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x11, value);
186349ab747fSPaolo Bonzini break;
186449ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTFGCOLOR + 2):
186549ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x13, value);
186649ab747fSPaolo Bonzini break;
186749ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTFGCOLOR + 3):
186849ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x15, value);
186949ab747fSPaolo Bonzini break;
187049ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTWIDTH + 0):
187149ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x20, value);
187249ab747fSPaolo Bonzini break;
187349ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTWIDTH + 1):
187449ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x21, value);
187549ab747fSPaolo Bonzini break;
187649ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTHEIGHT + 0):
187749ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x22, value);
187849ab747fSPaolo Bonzini break;
187949ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTHEIGHT + 1):
188049ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x23, value);
188149ab747fSPaolo Bonzini break;
188249ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTDESTPITCH + 0):
188349ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x24, value);
188449ab747fSPaolo Bonzini break;
188549ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTDESTPITCH + 1):
188649ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x25, value);
188749ab747fSPaolo Bonzini break;
188849ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTSRCPITCH + 0):
188949ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x26, value);
189049ab747fSPaolo Bonzini break;
189149ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTSRCPITCH + 1):
189249ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x27, value);
189349ab747fSPaolo Bonzini break;
189449ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTDESTADDR + 0):
189549ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x28, value);
189649ab747fSPaolo Bonzini break;
189749ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTDESTADDR + 1):
189849ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x29, value);
189949ab747fSPaolo Bonzini break;
190049ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTDESTADDR + 2):
190149ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x2a, value);
190249ab747fSPaolo Bonzini break;
190349ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTDESTADDR + 3):
190449ab747fSPaolo Bonzini /* ignored */
190549ab747fSPaolo Bonzini break;
190649ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTSRCADDR + 0):
190749ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x2c, value);
190849ab747fSPaolo Bonzini break;
190949ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTSRCADDR + 1):
191049ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x2d, value);
191149ab747fSPaolo Bonzini break;
191249ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTSRCADDR + 2):
191349ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x2e, value);
191449ab747fSPaolo Bonzini break;
191549ab747fSPaolo Bonzini case CIRRUS_MMIO_BLTWRITEMASK:
191649ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x2f, value);
191749ab747fSPaolo Bonzini break;
191849ab747fSPaolo Bonzini case CIRRUS_MMIO_BLTMODE:
191949ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x30, value);
192049ab747fSPaolo Bonzini break;
192149ab747fSPaolo Bonzini case CIRRUS_MMIO_BLTROP:
192249ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x32, value);
192349ab747fSPaolo Bonzini break;
192449ab747fSPaolo Bonzini case CIRRUS_MMIO_BLTMODEEXT:
192549ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x33, value);
192649ab747fSPaolo Bonzini break;
192749ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
192849ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x34, value);
192949ab747fSPaolo Bonzini break;
193049ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
193149ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x35, value);
193249ab747fSPaolo Bonzini break;
193349ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
193449ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x38, value);
193549ab747fSPaolo Bonzini break;
193649ab747fSPaolo Bonzini case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
193749ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x39, value);
193849ab747fSPaolo Bonzini break;
193949ab747fSPaolo Bonzini case CIRRUS_MMIO_BLTSTATUS:
194049ab747fSPaolo Bonzini cirrus_vga_write_gr(s, 0x31, value);
194149ab747fSPaolo Bonzini break;
194249ab747fSPaolo Bonzini default:
19432b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
19442b55f4d3SPhilippe Mathieu-Daudé "cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n",
194549ab747fSPaolo Bonzini address, value);
194649ab747fSPaolo Bonzini break;
194749ab747fSPaolo Bonzini }
194849ab747fSPaolo Bonzini }
194949ab747fSPaolo Bonzini
195049ab747fSPaolo Bonzini /***************************************
195149ab747fSPaolo Bonzini *
195249ab747fSPaolo Bonzini * write mode 4/5
195349ab747fSPaolo Bonzini *
195449ab747fSPaolo Bonzini ***************************************/
195549ab747fSPaolo Bonzini
cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,unsigned mode,unsigned offset,uint32_t mem_value)195649ab747fSPaolo Bonzini static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
195749ab747fSPaolo Bonzini unsigned mode,
195849ab747fSPaolo Bonzini unsigned offset,
195949ab747fSPaolo Bonzini uint32_t mem_value)
196049ab747fSPaolo Bonzini {
196149ab747fSPaolo Bonzini int x;
196249ab747fSPaolo Bonzini unsigned val = mem_value;
196349ab747fSPaolo Bonzini uint8_t *dst;
196449ab747fSPaolo Bonzini
196549ab747fSPaolo Bonzini for (x = 0; x < 8; x++) {
1966eb38e1bcSGerd Hoffmann dst = s->vga.vram_ptr + ((offset + x) & s->cirrus_addr_mask);
196749ab747fSPaolo Bonzini if (val & 0x80) {
196849ab747fSPaolo Bonzini *dst = s->cirrus_shadow_gr1;
196949ab747fSPaolo Bonzini } else if (mode == 5) {
197049ab747fSPaolo Bonzini *dst = s->cirrus_shadow_gr0;
197149ab747fSPaolo Bonzini }
197249ab747fSPaolo Bonzini val <<= 1;
197349ab747fSPaolo Bonzini }
197449ab747fSPaolo Bonzini memory_region_set_dirty(&s->vga.vram, offset, 8);
197549ab747fSPaolo Bonzini }
197649ab747fSPaolo Bonzini
cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,unsigned mode,unsigned offset,uint32_t mem_value)197749ab747fSPaolo Bonzini static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
197849ab747fSPaolo Bonzini unsigned mode,
197949ab747fSPaolo Bonzini unsigned offset,
198049ab747fSPaolo Bonzini uint32_t mem_value)
198149ab747fSPaolo Bonzini {
198249ab747fSPaolo Bonzini int x;
198349ab747fSPaolo Bonzini unsigned val = mem_value;
198449ab747fSPaolo Bonzini uint8_t *dst;
198549ab747fSPaolo Bonzini
198649ab747fSPaolo Bonzini for (x = 0; x < 8; x++) {
1987eb38e1bcSGerd Hoffmann dst = s->vga.vram_ptr + ((offset + 2 * x) & s->cirrus_addr_mask & ~1);
198849ab747fSPaolo Bonzini if (val & 0x80) {
198949ab747fSPaolo Bonzini *dst = s->cirrus_shadow_gr1;
199049ab747fSPaolo Bonzini *(dst + 1) = s->vga.gr[0x11];
199149ab747fSPaolo Bonzini } else if (mode == 5) {
199249ab747fSPaolo Bonzini *dst = s->cirrus_shadow_gr0;
199349ab747fSPaolo Bonzini *(dst + 1) = s->vga.gr[0x10];
199449ab747fSPaolo Bonzini }
199549ab747fSPaolo Bonzini val <<= 1;
199649ab747fSPaolo Bonzini }
199749ab747fSPaolo Bonzini memory_region_set_dirty(&s->vga.vram, offset, 16);
199849ab747fSPaolo Bonzini }
199949ab747fSPaolo Bonzini
200049ab747fSPaolo Bonzini /***************************************
200149ab747fSPaolo Bonzini *
200249ab747fSPaolo Bonzini * memory access between 0xa0000-0xbffff
200349ab747fSPaolo Bonzini *
200449ab747fSPaolo Bonzini ***************************************/
200549ab747fSPaolo Bonzini
cirrus_vga_mem_read(void * opaque,hwaddr addr,uint32_t size)200649ab747fSPaolo Bonzini static uint64_t cirrus_vga_mem_read(void *opaque,
200749ab747fSPaolo Bonzini hwaddr addr,
200849ab747fSPaolo Bonzini uint32_t size)
200949ab747fSPaolo Bonzini {
201049ab747fSPaolo Bonzini CirrusVGAState *s = opaque;
201149ab747fSPaolo Bonzini unsigned bank_index;
201249ab747fSPaolo Bonzini unsigned bank_offset;
201349ab747fSPaolo Bonzini uint32_t val;
201449ab747fSPaolo Bonzini
201549ab747fSPaolo Bonzini if ((s->vga.sr[0x07] & 0x01) == 0) {
201649ab747fSPaolo Bonzini return vga_mem_readb(&s->vga, addr);
201749ab747fSPaolo Bonzini }
201849ab747fSPaolo Bonzini
201949ab747fSPaolo Bonzini if (addr < 0x10000) {
202049ab747fSPaolo Bonzini /* XXX handle bitblt */
202149ab747fSPaolo Bonzini /* video memory */
202249ab747fSPaolo Bonzini bank_index = addr >> 15;
202349ab747fSPaolo Bonzini bank_offset = addr & 0x7fff;
202449ab747fSPaolo Bonzini if (bank_offset < s->cirrus_bank_limit[bank_index]) {
202549ab747fSPaolo Bonzini bank_offset += s->cirrus_bank_base[bank_index];
202649ab747fSPaolo Bonzini if ((s->vga.gr[0x0B] & 0x14) == 0x14) {
202749ab747fSPaolo Bonzini bank_offset <<= 4;
202849ab747fSPaolo Bonzini } else if (s->vga.gr[0x0B] & 0x02) {
202949ab747fSPaolo Bonzini bank_offset <<= 3;
203049ab747fSPaolo Bonzini }
203149ab747fSPaolo Bonzini bank_offset &= s->cirrus_addr_mask;
203249ab747fSPaolo Bonzini val = *(s->vga.vram_ptr + bank_offset);
203349ab747fSPaolo Bonzini } else
203449ab747fSPaolo Bonzini val = 0xff;
203549ab747fSPaolo Bonzini } else if (addr >= 0x18000 && addr < 0x18100) {
203649ab747fSPaolo Bonzini /* memory-mapped I/O */
203749ab747fSPaolo Bonzini val = 0xff;
203849ab747fSPaolo Bonzini if ((s->vga.sr[0x17] & 0x44) == 0x04) {
203949ab747fSPaolo Bonzini val = cirrus_mmio_blt_read(s, addr & 0xff);
204049ab747fSPaolo Bonzini }
204149ab747fSPaolo Bonzini } else {
204249ab747fSPaolo Bonzini val = 0xff;
20432b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
2044883f2c59SPhilippe Mathieu-Daudé "cirrus: mem_readb 0x" HWADDR_FMT_plx "\n", addr);
204549ab747fSPaolo Bonzini }
204649ab747fSPaolo Bonzini return val;
204749ab747fSPaolo Bonzini }
204849ab747fSPaolo Bonzini
cirrus_vga_mem_write(void * opaque,hwaddr addr,uint64_t mem_value,uint32_t size)204949ab747fSPaolo Bonzini static void cirrus_vga_mem_write(void *opaque,
205049ab747fSPaolo Bonzini hwaddr addr,
205149ab747fSPaolo Bonzini uint64_t mem_value,
205249ab747fSPaolo Bonzini uint32_t size)
205349ab747fSPaolo Bonzini {
205449ab747fSPaolo Bonzini CirrusVGAState *s = opaque;
205549ab747fSPaolo Bonzini unsigned bank_index;
205649ab747fSPaolo Bonzini unsigned bank_offset;
205749ab747fSPaolo Bonzini unsigned mode;
205849ab747fSPaolo Bonzini
205949ab747fSPaolo Bonzini if ((s->vga.sr[0x07] & 0x01) == 0) {
206049ab747fSPaolo Bonzini vga_mem_writeb(&s->vga, addr, mem_value);
206149ab747fSPaolo Bonzini return;
206249ab747fSPaolo Bonzini }
206349ab747fSPaolo Bonzini
206449ab747fSPaolo Bonzini if (addr < 0x10000) {
206549ab747fSPaolo Bonzini if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
206649ab747fSPaolo Bonzini /* bitblt */
206749ab747fSPaolo Bonzini *s->cirrus_srcptr++ = (uint8_t) mem_value;
206849ab747fSPaolo Bonzini if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
206949ab747fSPaolo Bonzini cirrus_bitblt_cputovideo_next(s);
207049ab747fSPaolo Bonzini }
207149ab747fSPaolo Bonzini } else {
207249ab747fSPaolo Bonzini /* video memory */
207349ab747fSPaolo Bonzini bank_index = addr >> 15;
207449ab747fSPaolo Bonzini bank_offset = addr & 0x7fff;
207549ab747fSPaolo Bonzini if (bank_offset < s->cirrus_bank_limit[bank_index]) {
207649ab747fSPaolo Bonzini bank_offset += s->cirrus_bank_base[bank_index];
207749ab747fSPaolo Bonzini if ((s->vga.gr[0x0B] & 0x14) == 0x14) {
207849ab747fSPaolo Bonzini bank_offset <<= 4;
207949ab747fSPaolo Bonzini } else if (s->vga.gr[0x0B] & 0x02) {
208049ab747fSPaolo Bonzini bank_offset <<= 3;
208149ab747fSPaolo Bonzini }
208249ab747fSPaolo Bonzini bank_offset &= s->cirrus_addr_mask;
208349ab747fSPaolo Bonzini mode = s->vga.gr[0x05] & 0x7;
208449ab747fSPaolo Bonzini if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
208549ab747fSPaolo Bonzini *(s->vga.vram_ptr + bank_offset) = mem_value;
208649ab747fSPaolo Bonzini memory_region_set_dirty(&s->vga.vram, bank_offset,
208749ab747fSPaolo Bonzini sizeof(mem_value));
208849ab747fSPaolo Bonzini } else {
208949ab747fSPaolo Bonzini if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
209049ab747fSPaolo Bonzini cirrus_mem_writeb_mode4and5_8bpp(s, mode,
209149ab747fSPaolo Bonzini bank_offset,
209249ab747fSPaolo Bonzini mem_value);
209349ab747fSPaolo Bonzini } else {
209449ab747fSPaolo Bonzini cirrus_mem_writeb_mode4and5_16bpp(s, mode,
209549ab747fSPaolo Bonzini bank_offset,
209649ab747fSPaolo Bonzini mem_value);
209749ab747fSPaolo Bonzini }
209849ab747fSPaolo Bonzini }
209949ab747fSPaolo Bonzini }
210049ab747fSPaolo Bonzini }
210149ab747fSPaolo Bonzini } else if (addr >= 0x18000 && addr < 0x18100) {
210249ab747fSPaolo Bonzini /* memory-mapped I/O */
210349ab747fSPaolo Bonzini if ((s->vga.sr[0x17] & 0x44) == 0x04) {
210449ab747fSPaolo Bonzini cirrus_mmio_blt_write(s, addr & 0xff, mem_value);
210549ab747fSPaolo Bonzini }
210649ab747fSPaolo Bonzini } else {
21072b55f4d3SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR,
2108883f2c59SPhilippe Mathieu-Daudé "cirrus: mem_writeb 0x" HWADDR_FMT_plx " "
2109e016a844SPhilippe Mathieu-Daudé "value 0x%02" PRIx64 "\n", addr, mem_value);
211049ab747fSPaolo Bonzini }
211149ab747fSPaolo Bonzini }
211249ab747fSPaolo Bonzini
211349ab747fSPaolo Bonzini static const MemoryRegionOps cirrus_vga_mem_ops = {
211449ab747fSPaolo Bonzini .read = cirrus_vga_mem_read,
211549ab747fSPaolo Bonzini .write = cirrus_vga_mem_write,
211649ab747fSPaolo Bonzini .endianness = DEVICE_LITTLE_ENDIAN,
211749ab747fSPaolo Bonzini .impl = {
211849ab747fSPaolo Bonzini .min_access_size = 1,
211949ab747fSPaolo Bonzini .max_access_size = 1,
212049ab747fSPaolo Bonzini },
212149ab747fSPaolo Bonzini };
212249ab747fSPaolo Bonzini
212349ab747fSPaolo Bonzini /***************************************
212449ab747fSPaolo Bonzini *
212549ab747fSPaolo Bonzini * hardware cursor
212649ab747fSPaolo Bonzini *
212749ab747fSPaolo Bonzini ***************************************/
212849ab747fSPaolo Bonzini
invalidate_cursor1(CirrusVGAState * s)212949ab747fSPaolo Bonzini static inline void invalidate_cursor1(CirrusVGAState *s)
213049ab747fSPaolo Bonzini {
213149ab747fSPaolo Bonzini if (s->last_hw_cursor_size) {
213249ab747fSPaolo Bonzini vga_invalidate_scanlines(&s->vga,
213349ab747fSPaolo Bonzini s->last_hw_cursor_y + s->last_hw_cursor_y_start,
213449ab747fSPaolo Bonzini s->last_hw_cursor_y + s->last_hw_cursor_y_end);
213549ab747fSPaolo Bonzini }
213649ab747fSPaolo Bonzini }
213749ab747fSPaolo Bonzini
cirrus_cursor_compute_yrange(CirrusVGAState * s)213849ab747fSPaolo Bonzini static inline void cirrus_cursor_compute_yrange(CirrusVGAState *s)
213949ab747fSPaolo Bonzini {
214049ab747fSPaolo Bonzini const uint8_t *src;
214149ab747fSPaolo Bonzini uint32_t content;
214249ab747fSPaolo Bonzini int y, y_min, y_max;
214349ab747fSPaolo Bonzini
2144f0353b0dSPhilippe Mathieu-Daudé src = s->vga.vram_ptr + s->real_vram_size - 16 * KiB;
214549ab747fSPaolo Bonzini if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) {
214649ab747fSPaolo Bonzini src += (s->vga.sr[0x13] & 0x3c) * 256;
214749ab747fSPaolo Bonzini y_min = 64;
214849ab747fSPaolo Bonzini y_max = -1;
214949ab747fSPaolo Bonzini for(y = 0; y < 64; y++) {
215049ab747fSPaolo Bonzini content = ((uint32_t *)src)[0] |
215149ab747fSPaolo Bonzini ((uint32_t *)src)[1] |
215249ab747fSPaolo Bonzini ((uint32_t *)src)[2] |
215349ab747fSPaolo Bonzini ((uint32_t *)src)[3];
215449ab747fSPaolo Bonzini if (content) {
215549ab747fSPaolo Bonzini if (y < y_min)
215649ab747fSPaolo Bonzini y_min = y;
215749ab747fSPaolo Bonzini if (y > y_max)
215849ab747fSPaolo Bonzini y_max = y;
215949ab747fSPaolo Bonzini }
216049ab747fSPaolo Bonzini src += 16;
216149ab747fSPaolo Bonzini }
216249ab747fSPaolo Bonzini } else {
216349ab747fSPaolo Bonzini src += (s->vga.sr[0x13] & 0x3f) * 256;
216449ab747fSPaolo Bonzini y_min = 32;
216549ab747fSPaolo Bonzini y_max = -1;
216649ab747fSPaolo Bonzini for(y = 0; y < 32; y++) {
216749ab747fSPaolo Bonzini content = ((uint32_t *)src)[0] |
216849ab747fSPaolo Bonzini ((uint32_t *)(src + 128))[0];
216949ab747fSPaolo Bonzini if (content) {
217049ab747fSPaolo Bonzini if (y < y_min)
217149ab747fSPaolo Bonzini y_min = y;
217249ab747fSPaolo Bonzini if (y > y_max)
217349ab747fSPaolo Bonzini y_max = y;
217449ab747fSPaolo Bonzini }
217549ab747fSPaolo Bonzini src += 4;
217649ab747fSPaolo Bonzini }
217749ab747fSPaolo Bonzini }
217849ab747fSPaolo Bonzini if (y_min > y_max) {
217949ab747fSPaolo Bonzini s->last_hw_cursor_y_start = 0;
218049ab747fSPaolo Bonzini s->last_hw_cursor_y_end = 0;
218149ab747fSPaolo Bonzini } else {
218249ab747fSPaolo Bonzini s->last_hw_cursor_y_start = y_min;
218349ab747fSPaolo Bonzini s->last_hw_cursor_y_end = y_max + 1;
218449ab747fSPaolo Bonzini }
218549ab747fSPaolo Bonzini }
218649ab747fSPaolo Bonzini
218749ab747fSPaolo Bonzini /* NOTE: we do not currently handle the cursor bitmap change, so we
218849ab747fSPaolo Bonzini update the cursor only if it moves. */
cirrus_cursor_invalidate(VGACommonState * s1)218949ab747fSPaolo Bonzini static void cirrus_cursor_invalidate(VGACommonState *s1)
219049ab747fSPaolo Bonzini {
219149ab747fSPaolo Bonzini CirrusVGAState *s = container_of(s1, CirrusVGAState, vga);
219249ab747fSPaolo Bonzini int size;
219349ab747fSPaolo Bonzini
219449ab747fSPaolo Bonzini if (!(s->vga.sr[0x12] & CIRRUS_CURSOR_SHOW)) {
219549ab747fSPaolo Bonzini size = 0;
219649ab747fSPaolo Bonzini } else {
219749ab747fSPaolo Bonzini if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE)
219849ab747fSPaolo Bonzini size = 64;
219949ab747fSPaolo Bonzini else
220049ab747fSPaolo Bonzini size = 32;
220149ab747fSPaolo Bonzini }
220249ab747fSPaolo Bonzini /* invalidate last cursor and new cursor if any change */
220349ab747fSPaolo Bonzini if (s->last_hw_cursor_size != size ||
220422382bb9SGerd Hoffmann s->last_hw_cursor_x != s->vga.hw_cursor_x ||
220522382bb9SGerd Hoffmann s->last_hw_cursor_y != s->vga.hw_cursor_y) {
220649ab747fSPaolo Bonzini
220749ab747fSPaolo Bonzini invalidate_cursor1(s);
220849ab747fSPaolo Bonzini
220949ab747fSPaolo Bonzini s->last_hw_cursor_size = size;
221022382bb9SGerd Hoffmann s->last_hw_cursor_x = s->vga.hw_cursor_x;
221122382bb9SGerd Hoffmann s->last_hw_cursor_y = s->vga.hw_cursor_y;
221249ab747fSPaolo Bonzini /* compute the real cursor min and max y */
221349ab747fSPaolo Bonzini cirrus_cursor_compute_yrange(s);
221449ab747fSPaolo Bonzini invalidate_cursor1(s);
221549ab747fSPaolo Bonzini }
221649ab747fSPaolo Bonzini }
221749ab747fSPaolo Bonzini
vga_draw_cursor_line(uint8_t * d1,const uint8_t * src1,int poffset,int w,unsigned int color0,unsigned int color1,unsigned int color_xor)221870a041feSBenjamin Herrenschmidt static void vga_draw_cursor_line(uint8_t *d1,
221970a041feSBenjamin Herrenschmidt const uint8_t *src1,
222070a041feSBenjamin Herrenschmidt int poffset, int w,
222170a041feSBenjamin Herrenschmidt unsigned int color0,
222270a041feSBenjamin Herrenschmidt unsigned int color1,
222370a041feSBenjamin Herrenschmidt unsigned int color_xor)
222470a041feSBenjamin Herrenschmidt {
222570a041feSBenjamin Herrenschmidt const uint8_t *plane0, *plane1;
222670a041feSBenjamin Herrenschmidt int x, b0, b1;
222770a041feSBenjamin Herrenschmidt uint8_t *d;
222849ab747fSPaolo Bonzini
222970a041feSBenjamin Herrenschmidt d = d1;
223070a041feSBenjamin Herrenschmidt plane0 = src1;
223170a041feSBenjamin Herrenschmidt plane1 = src1 + poffset;
223270a041feSBenjamin Herrenschmidt for (x = 0; x < w; x++) {
223370a041feSBenjamin Herrenschmidt b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
223470a041feSBenjamin Herrenschmidt b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
223570a041feSBenjamin Herrenschmidt switch (b0 | (b1 << 1)) {
223670a041feSBenjamin Herrenschmidt case 0:
223770a041feSBenjamin Herrenschmidt break;
223870a041feSBenjamin Herrenschmidt case 1:
223970a041feSBenjamin Herrenschmidt ((uint32_t *)d)[0] ^= color_xor;
224070a041feSBenjamin Herrenschmidt break;
224170a041feSBenjamin Herrenschmidt case 2:
224270a041feSBenjamin Herrenschmidt ((uint32_t *)d)[0] = color0;
224370a041feSBenjamin Herrenschmidt break;
224470a041feSBenjamin Herrenschmidt case 3:
224570a041feSBenjamin Herrenschmidt ((uint32_t *)d)[0] = color1;
224670a041feSBenjamin Herrenschmidt break;
224770a041feSBenjamin Herrenschmidt }
224870a041feSBenjamin Herrenschmidt d += 4;
224970a041feSBenjamin Herrenschmidt }
225070a041feSBenjamin Herrenschmidt }
225149ab747fSPaolo Bonzini
cirrus_cursor_draw_line(VGACommonState * s1,uint8_t * d1,int scr_y)225249ab747fSPaolo Bonzini static void cirrus_cursor_draw_line(VGACommonState *s1, uint8_t *d1, int scr_y)
225349ab747fSPaolo Bonzini {
225449ab747fSPaolo Bonzini CirrusVGAState *s = container_of(s1, CirrusVGAState, vga);
225570a041feSBenjamin Herrenschmidt int w, h, x1, x2, poffset;
225649ab747fSPaolo Bonzini unsigned int color0, color1;
225749ab747fSPaolo Bonzini const uint8_t *palette, *src;
225849ab747fSPaolo Bonzini uint32_t content;
225949ab747fSPaolo Bonzini
226049ab747fSPaolo Bonzini if (!(s->vga.sr[0x12] & CIRRUS_CURSOR_SHOW))
226149ab747fSPaolo Bonzini return;
226249ab747fSPaolo Bonzini /* fast test to see if the cursor intersects with the scan line */
226349ab747fSPaolo Bonzini if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) {
226449ab747fSPaolo Bonzini h = 64;
226549ab747fSPaolo Bonzini } else {
226649ab747fSPaolo Bonzini h = 32;
226749ab747fSPaolo Bonzini }
226822382bb9SGerd Hoffmann if (scr_y < s->vga.hw_cursor_y ||
226922382bb9SGerd Hoffmann scr_y >= (s->vga.hw_cursor_y + h)) {
227049ab747fSPaolo Bonzini return;
227122382bb9SGerd Hoffmann }
227249ab747fSPaolo Bonzini
2273f0353b0dSPhilippe Mathieu-Daudé src = s->vga.vram_ptr + s->real_vram_size - 16 * KiB;
227449ab747fSPaolo Bonzini if (s->vga.sr[0x12] & CIRRUS_CURSOR_LARGE) {
227549ab747fSPaolo Bonzini src += (s->vga.sr[0x13] & 0x3c) * 256;
227622382bb9SGerd Hoffmann src += (scr_y - s->vga.hw_cursor_y) * 16;
227749ab747fSPaolo Bonzini poffset = 8;
227849ab747fSPaolo Bonzini content = ((uint32_t *)src)[0] |
227949ab747fSPaolo Bonzini ((uint32_t *)src)[1] |
228049ab747fSPaolo Bonzini ((uint32_t *)src)[2] |
228149ab747fSPaolo Bonzini ((uint32_t *)src)[3];
228249ab747fSPaolo Bonzini } else {
228349ab747fSPaolo Bonzini src += (s->vga.sr[0x13] & 0x3f) * 256;
228422382bb9SGerd Hoffmann src += (scr_y - s->vga.hw_cursor_y) * 4;
2285d3c2343aSBenjamin Herrenschmidt
2286d3c2343aSBenjamin Herrenschmidt
228749ab747fSPaolo Bonzini poffset = 128;
228849ab747fSPaolo Bonzini content = ((uint32_t *)src)[0] |
228949ab747fSPaolo Bonzini ((uint32_t *)(src + 128))[0];
229049ab747fSPaolo Bonzini }
229149ab747fSPaolo Bonzini /* if nothing to draw, no need to continue */
229249ab747fSPaolo Bonzini if (!content)
229349ab747fSPaolo Bonzini return;
229449ab747fSPaolo Bonzini w = h;
229549ab747fSPaolo Bonzini
229622382bb9SGerd Hoffmann x1 = s->vga.hw_cursor_x;
229749ab747fSPaolo Bonzini if (x1 >= s->vga.last_scr_width)
229849ab747fSPaolo Bonzini return;
229922382bb9SGerd Hoffmann x2 = s->vga.hw_cursor_x + w;
230049ab747fSPaolo Bonzini if (x2 > s->vga.last_scr_width)
230149ab747fSPaolo Bonzini x2 = s->vga.last_scr_width;
230249ab747fSPaolo Bonzini w = x2 - x1;
230349ab747fSPaolo Bonzini palette = s->cirrus_hidden_palette;
2304d3c2343aSBenjamin Herrenschmidt color0 = rgb_to_pixel32(c6_to_8(palette[0x0 * 3]),
230549ab747fSPaolo Bonzini c6_to_8(palette[0x0 * 3 + 1]),
230649ab747fSPaolo Bonzini c6_to_8(palette[0x0 * 3 + 2]));
2307d3c2343aSBenjamin Herrenschmidt color1 = rgb_to_pixel32(c6_to_8(palette[0xf * 3]),
230849ab747fSPaolo Bonzini c6_to_8(palette[0xf * 3 + 1]),
230949ab747fSPaolo Bonzini c6_to_8(palette[0xf * 3 + 2]));
231070a041feSBenjamin Herrenschmidt d1 += x1 * 4;
231170a041feSBenjamin Herrenschmidt vga_draw_cursor_line(d1, src, poffset, w, color0, color1, 0xffffff);
231249ab747fSPaolo Bonzini }
231349ab747fSPaolo Bonzini
231449ab747fSPaolo Bonzini /***************************************
231549ab747fSPaolo Bonzini *
231649ab747fSPaolo Bonzini * LFB memory access
231749ab747fSPaolo Bonzini *
231849ab747fSPaolo Bonzini ***************************************/
231949ab747fSPaolo Bonzini
cirrus_linear_read(void * opaque,hwaddr addr,unsigned size)232049ab747fSPaolo Bonzini static uint64_t cirrus_linear_read(void *opaque, hwaddr addr,
232149ab747fSPaolo Bonzini unsigned size)
232249ab747fSPaolo Bonzini {
232349ab747fSPaolo Bonzini CirrusVGAState *s = opaque;
232449ab747fSPaolo Bonzini uint32_t ret;
232549ab747fSPaolo Bonzini
232649ab747fSPaolo Bonzini addr &= s->cirrus_addr_mask;
232749ab747fSPaolo Bonzini
232849ab747fSPaolo Bonzini if (((s->vga.sr[0x17] & 0x44) == 0x44) &&
232949ab747fSPaolo Bonzini ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
233049ab747fSPaolo Bonzini /* memory-mapped I/O */
233149ab747fSPaolo Bonzini ret = cirrus_mmio_blt_read(s, addr & 0xff);
233249ab747fSPaolo Bonzini } else if (0) {
233349ab747fSPaolo Bonzini /* XXX handle bitblt */
233449ab747fSPaolo Bonzini ret = 0xff;
233549ab747fSPaolo Bonzini } else {
233649ab747fSPaolo Bonzini /* video memory */
233749ab747fSPaolo Bonzini if ((s->vga.gr[0x0B] & 0x14) == 0x14) {
233849ab747fSPaolo Bonzini addr <<= 4;
233949ab747fSPaolo Bonzini } else if (s->vga.gr[0x0B] & 0x02) {
234049ab747fSPaolo Bonzini addr <<= 3;
234149ab747fSPaolo Bonzini }
234249ab747fSPaolo Bonzini addr &= s->cirrus_addr_mask;
234349ab747fSPaolo Bonzini ret = *(s->vga.vram_ptr + addr);
234449ab747fSPaolo Bonzini }
234549ab747fSPaolo Bonzini
234649ab747fSPaolo Bonzini return ret;
234749ab747fSPaolo Bonzini }
234849ab747fSPaolo Bonzini
cirrus_linear_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)234949ab747fSPaolo Bonzini static void cirrus_linear_write(void *opaque, hwaddr addr,
235049ab747fSPaolo Bonzini uint64_t val, unsigned size)
235149ab747fSPaolo Bonzini {
235249ab747fSPaolo Bonzini CirrusVGAState *s = opaque;
235349ab747fSPaolo Bonzini unsigned mode;
235449ab747fSPaolo Bonzini
235549ab747fSPaolo Bonzini addr &= s->cirrus_addr_mask;
235649ab747fSPaolo Bonzini
235749ab747fSPaolo Bonzini if (((s->vga.sr[0x17] & 0x44) == 0x44) &&
235849ab747fSPaolo Bonzini ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
235949ab747fSPaolo Bonzini /* memory-mapped I/O */
236049ab747fSPaolo Bonzini cirrus_mmio_blt_write(s, addr & 0xff, val);
236149ab747fSPaolo Bonzini } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
236249ab747fSPaolo Bonzini /* bitblt */
236349ab747fSPaolo Bonzini *s->cirrus_srcptr++ = (uint8_t) val;
236449ab747fSPaolo Bonzini if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
236549ab747fSPaolo Bonzini cirrus_bitblt_cputovideo_next(s);
236649ab747fSPaolo Bonzini }
236749ab747fSPaolo Bonzini } else {
236849ab747fSPaolo Bonzini /* video memory */
236949ab747fSPaolo Bonzini if ((s->vga.gr[0x0B] & 0x14) == 0x14) {
237049ab747fSPaolo Bonzini addr <<= 4;
237149ab747fSPaolo Bonzini } else if (s->vga.gr[0x0B] & 0x02) {
237249ab747fSPaolo Bonzini addr <<= 3;
237349ab747fSPaolo Bonzini }
237449ab747fSPaolo Bonzini addr &= s->cirrus_addr_mask;
237549ab747fSPaolo Bonzini
237649ab747fSPaolo Bonzini mode = s->vga.gr[0x05] & 0x7;
237749ab747fSPaolo Bonzini if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
237849ab747fSPaolo Bonzini *(s->vga.vram_ptr + addr) = (uint8_t) val;
237949ab747fSPaolo Bonzini memory_region_set_dirty(&s->vga.vram, addr, 1);
238049ab747fSPaolo Bonzini } else {
238149ab747fSPaolo Bonzini if ((s->vga.gr[0x0B] & 0x14) != 0x14) {
238249ab747fSPaolo Bonzini cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
238349ab747fSPaolo Bonzini } else {
238449ab747fSPaolo Bonzini cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val);
238549ab747fSPaolo Bonzini }
238649ab747fSPaolo Bonzini }
238749ab747fSPaolo Bonzini }
238849ab747fSPaolo Bonzini }
238949ab747fSPaolo Bonzini
239049ab747fSPaolo Bonzini /***************************************
239149ab747fSPaolo Bonzini *
239249ab747fSPaolo Bonzini * system to screen memory access
239349ab747fSPaolo Bonzini *
239449ab747fSPaolo Bonzini ***************************************/
239549ab747fSPaolo Bonzini
239649ab747fSPaolo Bonzini
cirrus_linear_bitblt_read(void * opaque,hwaddr addr,unsigned size)239749ab747fSPaolo Bonzini static uint64_t cirrus_linear_bitblt_read(void *opaque,
239849ab747fSPaolo Bonzini hwaddr addr,
239949ab747fSPaolo Bonzini unsigned size)
240049ab747fSPaolo Bonzini {
240149ab747fSPaolo Bonzini CirrusVGAState *s = opaque;
240249ab747fSPaolo Bonzini
240349ab747fSPaolo Bonzini /* XXX handle bitblt */
240449ab747fSPaolo Bonzini (void)s;
2405bb6e9e94SPhilippe Mathieu-Daudé qemu_log_mask(LOG_UNIMP,
2406bb6e9e94SPhilippe Mathieu-Daudé "cirrus: linear bitblt is not implemented\n");
2407bb6e9e94SPhilippe Mathieu-Daudé
2408b3ac2b94SSimran Singhal return 0xff;
240949ab747fSPaolo Bonzini }
241049ab747fSPaolo Bonzini
cirrus_linear_bitblt_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)241149ab747fSPaolo Bonzini static void cirrus_linear_bitblt_write(void *opaque,
241249ab747fSPaolo Bonzini hwaddr addr,
241349ab747fSPaolo Bonzini uint64_t val,
241449ab747fSPaolo Bonzini unsigned size)
241549ab747fSPaolo Bonzini {
241649ab747fSPaolo Bonzini CirrusVGAState *s = opaque;
241749ab747fSPaolo Bonzini
241849ab747fSPaolo Bonzini if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
241949ab747fSPaolo Bonzini /* bitblt */
242049ab747fSPaolo Bonzini *s->cirrus_srcptr++ = (uint8_t) val;
242149ab747fSPaolo Bonzini if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
242249ab747fSPaolo Bonzini cirrus_bitblt_cputovideo_next(s);
242349ab747fSPaolo Bonzini }
242449ab747fSPaolo Bonzini }
242549ab747fSPaolo Bonzini }
242649ab747fSPaolo Bonzini
242749ab747fSPaolo Bonzini static const MemoryRegionOps cirrus_linear_bitblt_io_ops = {
242849ab747fSPaolo Bonzini .read = cirrus_linear_bitblt_read,
242949ab747fSPaolo Bonzini .write = cirrus_linear_bitblt_write,
243049ab747fSPaolo Bonzini .endianness = DEVICE_LITTLE_ENDIAN,
243149ab747fSPaolo Bonzini .impl = {
243249ab747fSPaolo Bonzini .min_access_size = 1,
243349ab747fSPaolo Bonzini .max_access_size = 1,
243449ab747fSPaolo Bonzini },
243549ab747fSPaolo Bonzini };
243649ab747fSPaolo Bonzini
map_linear_vram_bank(CirrusVGAState * s,unsigned bank)243749ab747fSPaolo Bonzini static void map_linear_vram_bank(CirrusVGAState *s, unsigned bank)
243849ab747fSPaolo Bonzini {
243949ab747fSPaolo Bonzini MemoryRegion *mr = &s->cirrus_bank[bank];
244049ab747fSPaolo Bonzini bool enabled = !(s->cirrus_srcptr != s->cirrus_srcptr_end)
244149ab747fSPaolo Bonzini && !((s->vga.sr[0x07] & 0x01) == 0)
244249ab747fSPaolo Bonzini && !((s->vga.gr[0x0B] & 0x14) == 0x14)
244349ab747fSPaolo Bonzini && !(s->vga.gr[0x0B] & 0x02);
244449ab747fSPaolo Bonzini
244549ab747fSPaolo Bonzini memory_region_set_enabled(mr, enabled);
244649ab747fSPaolo Bonzini memory_region_set_alias_offset(mr, s->cirrus_bank_base[bank]);
244749ab747fSPaolo Bonzini }
244849ab747fSPaolo Bonzini
map_linear_vram(CirrusVGAState * s)244949ab747fSPaolo Bonzini static void map_linear_vram(CirrusVGAState *s)
245049ab747fSPaolo Bonzini {
245149ab747fSPaolo Bonzini if (s->bustype == CIRRUS_BUSTYPE_PCI && !s->linear_vram) {
245249ab747fSPaolo Bonzini s->linear_vram = true;
245349ab747fSPaolo Bonzini memory_region_add_subregion_overlap(&s->pci_bar, 0, &s->vga.vram, 1);
245449ab747fSPaolo Bonzini }
245549ab747fSPaolo Bonzini map_linear_vram_bank(s, 0);
245649ab747fSPaolo Bonzini map_linear_vram_bank(s, 1);
245749ab747fSPaolo Bonzini }
245849ab747fSPaolo Bonzini
unmap_linear_vram(CirrusVGAState * s)245949ab747fSPaolo Bonzini static void unmap_linear_vram(CirrusVGAState *s)
246049ab747fSPaolo Bonzini {
246149ab747fSPaolo Bonzini if (s->bustype == CIRRUS_BUSTYPE_PCI && s->linear_vram) {
246249ab747fSPaolo Bonzini s->linear_vram = false;
246349ab747fSPaolo Bonzini memory_region_del_subregion(&s->pci_bar, &s->vga.vram);
246449ab747fSPaolo Bonzini }
246549ab747fSPaolo Bonzini memory_region_set_enabled(&s->cirrus_bank[0], false);
246649ab747fSPaolo Bonzini memory_region_set_enabled(&s->cirrus_bank[1], false);
246749ab747fSPaolo Bonzini }
246849ab747fSPaolo Bonzini
246949ab747fSPaolo Bonzini /* Compute the memory access functions */
cirrus_update_memory_access(CirrusVGAState * s)247049ab747fSPaolo Bonzini static void cirrus_update_memory_access(CirrusVGAState *s)
247149ab747fSPaolo Bonzini {
247249ab747fSPaolo Bonzini unsigned mode;
247349ab747fSPaolo Bonzini
247449ab747fSPaolo Bonzini memory_region_transaction_begin();
247549ab747fSPaolo Bonzini if ((s->vga.sr[0x17] & 0x44) == 0x44) {
247649ab747fSPaolo Bonzini goto generic_io;
247749ab747fSPaolo Bonzini } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
247849ab747fSPaolo Bonzini goto generic_io;
247949ab747fSPaolo Bonzini } else {
248049ab747fSPaolo Bonzini if ((s->vga.gr[0x0B] & 0x14) == 0x14) {
248149ab747fSPaolo Bonzini goto generic_io;
248249ab747fSPaolo Bonzini } else if (s->vga.gr[0x0B] & 0x02) {
248349ab747fSPaolo Bonzini goto generic_io;
248449ab747fSPaolo Bonzini }
248549ab747fSPaolo Bonzini
248649ab747fSPaolo Bonzini mode = s->vga.gr[0x05] & 0x7;
248749ab747fSPaolo Bonzini if (mode < 4 || mode > 5 || ((s->vga.gr[0x0B] & 0x4) == 0)) {
248849ab747fSPaolo Bonzini map_linear_vram(s);
248949ab747fSPaolo Bonzini } else {
249049ab747fSPaolo Bonzini generic_io:
249149ab747fSPaolo Bonzini unmap_linear_vram(s);
249249ab747fSPaolo Bonzini }
249349ab747fSPaolo Bonzini }
249449ab747fSPaolo Bonzini memory_region_transaction_commit();
249549ab747fSPaolo Bonzini }
249649ab747fSPaolo Bonzini
249749ab747fSPaolo Bonzini
249849ab747fSPaolo Bonzini /* I/O ports */
249949ab747fSPaolo Bonzini
cirrus_vga_ioport_read(void * opaque,hwaddr addr,unsigned size)250049ab747fSPaolo Bonzini static uint64_t cirrus_vga_ioport_read(void *opaque, hwaddr addr,
250149ab747fSPaolo Bonzini unsigned size)
250249ab747fSPaolo Bonzini {
250349ab747fSPaolo Bonzini CirrusVGAState *c = opaque;
250449ab747fSPaolo Bonzini VGACommonState *s = &c->vga;
250549ab747fSPaolo Bonzini int val, index;
250649ab747fSPaolo Bonzini
250749ab747fSPaolo Bonzini addr += 0x3b0;
250849ab747fSPaolo Bonzini
250949ab747fSPaolo Bonzini if (vga_ioport_invalid(s, addr)) {
251049ab747fSPaolo Bonzini val = 0xff;
251149ab747fSPaolo Bonzini } else {
251249ab747fSPaolo Bonzini switch (addr) {
251349ab747fSPaolo Bonzini case 0x3c0:
251449ab747fSPaolo Bonzini if (s->ar_flip_flop == 0) {
251549ab747fSPaolo Bonzini val = s->ar_index;
251649ab747fSPaolo Bonzini } else {
251749ab747fSPaolo Bonzini val = 0;
251849ab747fSPaolo Bonzini }
251949ab747fSPaolo Bonzini break;
252049ab747fSPaolo Bonzini case 0x3c1:
252149ab747fSPaolo Bonzini index = s->ar_index & 0x1f;
252249ab747fSPaolo Bonzini if (index < 21)
252349ab747fSPaolo Bonzini val = s->ar[index];
252449ab747fSPaolo Bonzini else
252549ab747fSPaolo Bonzini val = 0;
252649ab747fSPaolo Bonzini break;
252749ab747fSPaolo Bonzini case 0x3c2:
252849ab747fSPaolo Bonzini val = s->st00;
252949ab747fSPaolo Bonzini break;
253049ab747fSPaolo Bonzini case 0x3c4:
253149ab747fSPaolo Bonzini val = s->sr_index;
253249ab747fSPaolo Bonzini break;
253349ab747fSPaolo Bonzini case 0x3c5:
253449ab747fSPaolo Bonzini val = cirrus_vga_read_sr(c);
253549ab747fSPaolo Bonzini break;
253649ab747fSPaolo Bonzini break;
253749ab747fSPaolo Bonzini case 0x3c6:
253849ab747fSPaolo Bonzini val = cirrus_read_hidden_dac(c);
253949ab747fSPaolo Bonzini break;
254049ab747fSPaolo Bonzini case 0x3c7:
254149ab747fSPaolo Bonzini val = s->dac_state;
254249ab747fSPaolo Bonzini break;
254349ab747fSPaolo Bonzini case 0x3c8:
254449ab747fSPaolo Bonzini val = s->dac_write_index;
254549ab747fSPaolo Bonzini c->cirrus_hidden_dac_lockindex = 0;
254649ab747fSPaolo Bonzini break;
254749ab747fSPaolo Bonzini case 0x3c9:
254849ab747fSPaolo Bonzini val = cirrus_vga_read_palette(c);
254949ab747fSPaolo Bonzini break;
255049ab747fSPaolo Bonzini case 0x3ca:
255149ab747fSPaolo Bonzini val = s->fcr;
255249ab747fSPaolo Bonzini break;
255349ab747fSPaolo Bonzini case 0x3cc:
255449ab747fSPaolo Bonzini val = s->msr;
255549ab747fSPaolo Bonzini break;
255649ab747fSPaolo Bonzini case 0x3ce:
255749ab747fSPaolo Bonzini val = s->gr_index;
255849ab747fSPaolo Bonzini break;
255949ab747fSPaolo Bonzini case 0x3cf:
256049ab747fSPaolo Bonzini val = cirrus_vga_read_gr(c, s->gr_index);
256149ab747fSPaolo Bonzini break;
256249ab747fSPaolo Bonzini case 0x3b4:
256349ab747fSPaolo Bonzini case 0x3d4:
256449ab747fSPaolo Bonzini val = s->cr_index;
256549ab747fSPaolo Bonzini break;
256649ab747fSPaolo Bonzini case 0x3b5:
256749ab747fSPaolo Bonzini case 0x3d5:
256849ab747fSPaolo Bonzini val = cirrus_vga_read_cr(c, s->cr_index);
256949ab747fSPaolo Bonzini break;
257049ab747fSPaolo Bonzini case 0x3ba:
257149ab747fSPaolo Bonzini case 0x3da:
257249ab747fSPaolo Bonzini /* just toggle to fool polling */
257349ab747fSPaolo Bonzini val = s->st01 = s->retrace(s);
257449ab747fSPaolo Bonzini s->ar_flip_flop = 0;
257549ab747fSPaolo Bonzini break;
257649ab747fSPaolo Bonzini default:
257749ab747fSPaolo Bonzini val = 0x00;
257849ab747fSPaolo Bonzini break;
257949ab747fSPaolo Bonzini }
258049ab747fSPaolo Bonzini }
2581ec87f206SGerd Hoffmann trace_vga_cirrus_read_io(addr, val);
258249ab747fSPaolo Bonzini return val;
258349ab747fSPaolo Bonzini }
258449ab747fSPaolo Bonzini
cirrus_vga_ioport_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)258549ab747fSPaolo Bonzini static void cirrus_vga_ioport_write(void *opaque, hwaddr addr, uint64_t val,
258649ab747fSPaolo Bonzini unsigned size)
258749ab747fSPaolo Bonzini {
258849ab747fSPaolo Bonzini CirrusVGAState *c = opaque;
258949ab747fSPaolo Bonzini VGACommonState *s = &c->vga;
259049ab747fSPaolo Bonzini int index;
259149ab747fSPaolo Bonzini
259249ab747fSPaolo Bonzini addr += 0x3b0;
259349ab747fSPaolo Bonzini
259449ab747fSPaolo Bonzini /* check port range access depending on color/monochrome mode */
259549ab747fSPaolo Bonzini if (vga_ioport_invalid(s, addr)) {
259649ab747fSPaolo Bonzini return;
259749ab747fSPaolo Bonzini }
2598ec87f206SGerd Hoffmann trace_vga_cirrus_write_io(addr, val);
259949ab747fSPaolo Bonzini
260049ab747fSPaolo Bonzini switch (addr) {
260149ab747fSPaolo Bonzini case 0x3c0:
260249ab747fSPaolo Bonzini if (s->ar_flip_flop == 0) {
260349ab747fSPaolo Bonzini val &= 0x3f;
260449ab747fSPaolo Bonzini s->ar_index = val;
260549ab747fSPaolo Bonzini } else {
260649ab747fSPaolo Bonzini index = s->ar_index & 0x1f;
260749ab747fSPaolo Bonzini switch (index) {
260849ab747fSPaolo Bonzini case 0x00 ... 0x0f:
260949ab747fSPaolo Bonzini s->ar[index] = val & 0x3f;
261049ab747fSPaolo Bonzini break;
261149ab747fSPaolo Bonzini case 0x10:
261249ab747fSPaolo Bonzini s->ar[index] = val & ~0x10;
261349ab747fSPaolo Bonzini break;
261449ab747fSPaolo Bonzini case 0x11:
261549ab747fSPaolo Bonzini s->ar[index] = val;
261649ab747fSPaolo Bonzini break;
261749ab747fSPaolo Bonzini case 0x12:
261849ab747fSPaolo Bonzini s->ar[index] = val & ~0xc0;
261949ab747fSPaolo Bonzini break;
262049ab747fSPaolo Bonzini case 0x13:
262149ab747fSPaolo Bonzini s->ar[index] = val & ~0xf0;
262249ab747fSPaolo Bonzini break;
262349ab747fSPaolo Bonzini case 0x14:
262449ab747fSPaolo Bonzini s->ar[index] = val & ~0xf0;
262549ab747fSPaolo Bonzini break;
262649ab747fSPaolo Bonzini default:
262749ab747fSPaolo Bonzini break;
262849ab747fSPaolo Bonzini }
262949ab747fSPaolo Bonzini }
263049ab747fSPaolo Bonzini s->ar_flip_flop ^= 1;
263149ab747fSPaolo Bonzini break;
263249ab747fSPaolo Bonzini case 0x3c2:
263349ab747fSPaolo Bonzini s->msr = val & ~0x10;
263449ab747fSPaolo Bonzini s->update_retrace_info(s);
263549ab747fSPaolo Bonzini break;
263649ab747fSPaolo Bonzini case 0x3c4:
263749ab747fSPaolo Bonzini s->sr_index = val;
263849ab747fSPaolo Bonzini break;
263949ab747fSPaolo Bonzini case 0x3c5:
264049ab747fSPaolo Bonzini cirrus_vga_write_sr(c, val);
264149ab747fSPaolo Bonzini break;
264249ab747fSPaolo Bonzini case 0x3c6:
264349ab747fSPaolo Bonzini cirrus_write_hidden_dac(c, val);
264449ab747fSPaolo Bonzini break;
264549ab747fSPaolo Bonzini case 0x3c7:
264649ab747fSPaolo Bonzini s->dac_read_index = val;
264749ab747fSPaolo Bonzini s->dac_sub_index = 0;
264849ab747fSPaolo Bonzini s->dac_state = 3;
264949ab747fSPaolo Bonzini break;
265049ab747fSPaolo Bonzini case 0x3c8:
265149ab747fSPaolo Bonzini s->dac_write_index = val;
265249ab747fSPaolo Bonzini s->dac_sub_index = 0;
265349ab747fSPaolo Bonzini s->dac_state = 0;
265449ab747fSPaolo Bonzini break;
265549ab747fSPaolo Bonzini case 0x3c9:
265649ab747fSPaolo Bonzini cirrus_vga_write_palette(c, val);
265749ab747fSPaolo Bonzini break;
265849ab747fSPaolo Bonzini case 0x3ce:
265949ab747fSPaolo Bonzini s->gr_index = val;
266049ab747fSPaolo Bonzini break;
266149ab747fSPaolo Bonzini case 0x3cf:
266249ab747fSPaolo Bonzini cirrus_vga_write_gr(c, s->gr_index, val);
266349ab747fSPaolo Bonzini break;
266449ab747fSPaolo Bonzini case 0x3b4:
266549ab747fSPaolo Bonzini case 0x3d4:
266649ab747fSPaolo Bonzini s->cr_index = val;
266749ab747fSPaolo Bonzini break;
266849ab747fSPaolo Bonzini case 0x3b5:
266949ab747fSPaolo Bonzini case 0x3d5:
267049ab747fSPaolo Bonzini cirrus_vga_write_cr(c, val);
267149ab747fSPaolo Bonzini break;
267249ab747fSPaolo Bonzini case 0x3ba:
267349ab747fSPaolo Bonzini case 0x3da:
267449ab747fSPaolo Bonzini s->fcr = val & 0x10;
267549ab747fSPaolo Bonzini break;
267649ab747fSPaolo Bonzini }
267749ab747fSPaolo Bonzini }
267849ab747fSPaolo Bonzini
267949ab747fSPaolo Bonzini /***************************************
268049ab747fSPaolo Bonzini *
268149ab747fSPaolo Bonzini * memory-mapped I/O access
268249ab747fSPaolo Bonzini *
268349ab747fSPaolo Bonzini ***************************************/
268449ab747fSPaolo Bonzini
cirrus_mmio_read(void * opaque,hwaddr addr,unsigned size)268549ab747fSPaolo Bonzini static uint64_t cirrus_mmio_read(void *opaque, hwaddr addr,
268649ab747fSPaolo Bonzini unsigned size)
268749ab747fSPaolo Bonzini {
268849ab747fSPaolo Bonzini CirrusVGAState *s = opaque;
268949ab747fSPaolo Bonzini
269049ab747fSPaolo Bonzini if (addr >= 0x100) {
269149ab747fSPaolo Bonzini return cirrus_mmio_blt_read(s, addr - 0x100);
269249ab747fSPaolo Bonzini } else {
269349ab747fSPaolo Bonzini return cirrus_vga_ioport_read(s, addr + 0x10, size);
269449ab747fSPaolo Bonzini }
269549ab747fSPaolo Bonzini }
269649ab747fSPaolo Bonzini
cirrus_mmio_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)269749ab747fSPaolo Bonzini static void cirrus_mmio_write(void *opaque, hwaddr addr,
269849ab747fSPaolo Bonzini uint64_t val, unsigned size)
269949ab747fSPaolo Bonzini {
270049ab747fSPaolo Bonzini CirrusVGAState *s = opaque;
270149ab747fSPaolo Bonzini
270249ab747fSPaolo Bonzini if (addr >= 0x100) {
270349ab747fSPaolo Bonzini cirrus_mmio_blt_write(s, addr - 0x100, val);
270449ab747fSPaolo Bonzini } else {
270549ab747fSPaolo Bonzini cirrus_vga_ioport_write(s, addr + 0x10, val, size);
270649ab747fSPaolo Bonzini }
270749ab747fSPaolo Bonzini }
270849ab747fSPaolo Bonzini
270949ab747fSPaolo Bonzini static const MemoryRegionOps cirrus_mmio_io_ops = {
271049ab747fSPaolo Bonzini .read = cirrus_mmio_read,
271149ab747fSPaolo Bonzini .write = cirrus_mmio_write,
271249ab747fSPaolo Bonzini .endianness = DEVICE_LITTLE_ENDIAN,
271349ab747fSPaolo Bonzini .impl = {
271449ab747fSPaolo Bonzini .min_access_size = 1,
271549ab747fSPaolo Bonzini .max_access_size = 1,
271649ab747fSPaolo Bonzini },
271749ab747fSPaolo Bonzini };
271849ab747fSPaolo Bonzini
271949ab747fSPaolo Bonzini /* load/save state */
272049ab747fSPaolo Bonzini
cirrus_post_load(void * opaque,int version_id)272149ab747fSPaolo Bonzini static int cirrus_post_load(void *opaque, int version_id)
272249ab747fSPaolo Bonzini {
272349ab747fSPaolo Bonzini CirrusVGAState *s = opaque;
272449ab747fSPaolo Bonzini
272549ab747fSPaolo Bonzini s->vga.gr[0x00] = s->cirrus_shadow_gr0 & 0x0f;
272649ab747fSPaolo Bonzini s->vga.gr[0x01] = s->cirrus_shadow_gr1 & 0x0f;
272749ab747fSPaolo Bonzini
2728b7ee9e49SWang Xin cirrus_update_bank_ptr(s, 0);
2729b7ee9e49SWang Xin cirrus_update_bank_ptr(s, 1);
273049ab747fSPaolo Bonzini cirrus_update_memory_access(s);
273149ab747fSPaolo Bonzini /* force refresh */
273249ab747fSPaolo Bonzini s->vga.graphic_mode = -1;
2733b7ee9e49SWang Xin
273449ab747fSPaolo Bonzini return 0;
273549ab747fSPaolo Bonzini }
273649ab747fSPaolo Bonzini
2737ce3cf70eSThomas Huth const VMStateDescription vmstate_cirrus_vga = {
273849ab747fSPaolo Bonzini .name = "cirrus_vga",
273949ab747fSPaolo Bonzini .version_id = 2,
274049ab747fSPaolo Bonzini .minimum_version_id = 1,
274149ab747fSPaolo Bonzini .post_load = cirrus_post_load,
2742f0613160SRichard Henderson .fields = (const VMStateField[]) {
274349ab747fSPaolo Bonzini VMSTATE_UINT32(vga.latch, CirrusVGAState),
274449ab747fSPaolo Bonzini VMSTATE_UINT8(vga.sr_index, CirrusVGAState),
274549ab747fSPaolo Bonzini VMSTATE_BUFFER(vga.sr, CirrusVGAState),
274649ab747fSPaolo Bonzini VMSTATE_UINT8(vga.gr_index, CirrusVGAState),
274749ab747fSPaolo Bonzini VMSTATE_UINT8(cirrus_shadow_gr0, CirrusVGAState),
274849ab747fSPaolo Bonzini VMSTATE_UINT8(cirrus_shadow_gr1, CirrusVGAState),
274949ab747fSPaolo Bonzini VMSTATE_BUFFER_START_MIDDLE(vga.gr, CirrusVGAState, 2),
275049ab747fSPaolo Bonzini VMSTATE_UINT8(vga.ar_index, CirrusVGAState),
275149ab747fSPaolo Bonzini VMSTATE_BUFFER(vga.ar, CirrusVGAState),
275249ab747fSPaolo Bonzini VMSTATE_INT32(vga.ar_flip_flop, CirrusVGAState),
275349ab747fSPaolo Bonzini VMSTATE_UINT8(vga.cr_index, CirrusVGAState),
275449ab747fSPaolo Bonzini VMSTATE_BUFFER(vga.cr, CirrusVGAState),
275549ab747fSPaolo Bonzini VMSTATE_UINT8(vga.msr, CirrusVGAState),
275649ab747fSPaolo Bonzini VMSTATE_UINT8(vga.fcr, CirrusVGAState),
275749ab747fSPaolo Bonzini VMSTATE_UINT8(vga.st00, CirrusVGAState),
275849ab747fSPaolo Bonzini VMSTATE_UINT8(vga.st01, CirrusVGAState),
275949ab747fSPaolo Bonzini VMSTATE_UINT8(vga.dac_state, CirrusVGAState),
276049ab747fSPaolo Bonzini VMSTATE_UINT8(vga.dac_sub_index, CirrusVGAState),
276149ab747fSPaolo Bonzini VMSTATE_UINT8(vga.dac_read_index, CirrusVGAState),
276249ab747fSPaolo Bonzini VMSTATE_UINT8(vga.dac_write_index, CirrusVGAState),
276349ab747fSPaolo Bonzini VMSTATE_BUFFER(vga.dac_cache, CirrusVGAState),
276449ab747fSPaolo Bonzini VMSTATE_BUFFER(vga.palette, CirrusVGAState),
276549ab747fSPaolo Bonzini VMSTATE_INT32(vga.bank_offset, CirrusVGAState),
276649ab747fSPaolo Bonzini VMSTATE_UINT8(cirrus_hidden_dac_lockindex, CirrusVGAState),
276749ab747fSPaolo Bonzini VMSTATE_UINT8(cirrus_hidden_dac_data, CirrusVGAState),
276822382bb9SGerd Hoffmann VMSTATE_UINT32(vga.hw_cursor_x, CirrusVGAState),
276922382bb9SGerd Hoffmann VMSTATE_UINT32(vga.hw_cursor_y, CirrusVGAState),
277049ab747fSPaolo Bonzini /* XXX: we do not save the bitblt state - we assume we do not save
277149ab747fSPaolo Bonzini the state when the blitter is active */
277249ab747fSPaolo Bonzini VMSTATE_END_OF_LIST()
277349ab747fSPaolo Bonzini }
277449ab747fSPaolo Bonzini };
277549ab747fSPaolo Bonzini
277649ab747fSPaolo Bonzini static const VMStateDescription vmstate_pci_cirrus_vga = {
277749ab747fSPaolo Bonzini .name = "cirrus_vga",
277849ab747fSPaolo Bonzini .version_id = 2,
277949ab747fSPaolo Bonzini .minimum_version_id = 2,
2780f0613160SRichard Henderson .fields = (const VMStateField[]) {
278149ab747fSPaolo Bonzini VMSTATE_PCI_DEVICE(dev, PCICirrusVGAState),
278249ab747fSPaolo Bonzini VMSTATE_STRUCT(cirrus_vga, PCICirrusVGAState, 0,
278349ab747fSPaolo Bonzini vmstate_cirrus_vga, CirrusVGAState),
278449ab747fSPaolo Bonzini VMSTATE_END_OF_LIST()
278549ab747fSPaolo Bonzini }
278649ab747fSPaolo Bonzini };
278749ab747fSPaolo Bonzini
278849ab747fSPaolo Bonzini /***************************************
278949ab747fSPaolo Bonzini *
279049ab747fSPaolo Bonzini * initialize
279149ab747fSPaolo Bonzini *
279249ab747fSPaolo Bonzini ***************************************/
279349ab747fSPaolo Bonzini
cirrus_reset(void * opaque)279449ab747fSPaolo Bonzini static void cirrus_reset(void *opaque)
279549ab747fSPaolo Bonzini {
279649ab747fSPaolo Bonzini CirrusVGAState *s = opaque;
279749ab747fSPaolo Bonzini
279849ab747fSPaolo Bonzini vga_common_reset(&s->vga);
279949ab747fSPaolo Bonzini unmap_linear_vram(s);
280049ab747fSPaolo Bonzini s->vga.sr[0x06] = 0x0f;
280149ab747fSPaolo Bonzini if (s->device_id == CIRRUS_ID_CLGD5446) {
280249ab747fSPaolo Bonzini /* 4MB 64 bit memory config, always PCI */
280349ab747fSPaolo Bonzini s->vga.sr[0x1F] = 0x2d; // MemClock
280449ab747fSPaolo Bonzini s->vga.gr[0x18] = 0x0f; // fastest memory configuration
280549ab747fSPaolo Bonzini s->vga.sr[0x0f] = 0x98;
280649ab747fSPaolo Bonzini s->vga.sr[0x17] = 0x20;
280749ab747fSPaolo Bonzini s->vga.sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */
280849ab747fSPaolo Bonzini } else {
280949ab747fSPaolo Bonzini s->vga.sr[0x1F] = 0x22; // MemClock
281049ab747fSPaolo Bonzini s->vga.sr[0x0F] = CIRRUS_MEMSIZE_2M;
281149ab747fSPaolo Bonzini s->vga.sr[0x17] = s->bustype;
281249ab747fSPaolo Bonzini s->vga.sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
281349ab747fSPaolo Bonzini }
281449ab747fSPaolo Bonzini s->vga.cr[0x27] = s->device_id;
281549ab747fSPaolo Bonzini
281649ab747fSPaolo Bonzini s->cirrus_hidden_dac_lockindex = 5;
281749ab747fSPaolo Bonzini s->cirrus_hidden_dac_data = 0;
281849ab747fSPaolo Bonzini }
281949ab747fSPaolo Bonzini
282049ab747fSPaolo Bonzini static const MemoryRegionOps cirrus_linear_io_ops = {
282149ab747fSPaolo Bonzini .read = cirrus_linear_read,
282249ab747fSPaolo Bonzini .write = cirrus_linear_write,
282349ab747fSPaolo Bonzini .endianness = DEVICE_LITTLE_ENDIAN,
282449ab747fSPaolo Bonzini .impl = {
282549ab747fSPaolo Bonzini .min_access_size = 1,
282649ab747fSPaolo Bonzini .max_access_size = 1,
282749ab747fSPaolo Bonzini },
282849ab747fSPaolo Bonzini };
282949ab747fSPaolo Bonzini
283049ab747fSPaolo Bonzini static const MemoryRegionOps cirrus_vga_io_ops = {
283149ab747fSPaolo Bonzini .read = cirrus_vga_ioport_read,
283249ab747fSPaolo Bonzini .write = cirrus_vga_ioport_write,
283349ab747fSPaolo Bonzini .endianness = DEVICE_LITTLE_ENDIAN,
283449ab747fSPaolo Bonzini .impl = {
283549ab747fSPaolo Bonzini .min_access_size = 1,
283649ab747fSPaolo Bonzini .max_access_size = 1,
283749ab747fSPaolo Bonzini },
283849ab747fSPaolo Bonzini };
283949ab747fSPaolo Bonzini
cirrus_init_common(CirrusVGAState * s,Object * owner,int device_id,int is_pci,MemoryRegion * system_memory,MemoryRegion * system_io)2840ce3cf70eSThomas Huth void cirrus_init_common(CirrusVGAState *s, Object *owner,
28419eb58a47SPaolo Bonzini int device_id, int is_pci,
2842ce3cf70eSThomas Huth MemoryRegion *system_memory, MemoryRegion *system_io)
284349ab747fSPaolo Bonzini {
284449ab747fSPaolo Bonzini int i;
284549ab747fSPaolo Bonzini static int inited;
284649ab747fSPaolo Bonzini
284749ab747fSPaolo Bonzini if (!inited) {
284849ab747fSPaolo Bonzini inited = 1;
284949ab747fSPaolo Bonzini for(i = 0;i < 256; i++)
285049ab747fSPaolo Bonzini rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */
285149ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_0] = 0;
285249ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1;
285349ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_NOP] = 2;
285449ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3;
285549ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_NOTDST] = 4;
285649ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_SRC] = 5;
285749ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_1] = 6;
285849ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7;
285949ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8;
286049ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9;
286149ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10;
286249ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11;
286349ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12;
286449ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_NOTSRC] = 13;
286549ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14;
286649ab747fSPaolo Bonzini rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15;
286749ab747fSPaolo Bonzini s->device_id = device_id;
286849ab747fSPaolo Bonzini if (is_pci)
286949ab747fSPaolo Bonzini s->bustype = CIRRUS_BUSTYPE_PCI;
287049ab747fSPaolo Bonzini else
287149ab747fSPaolo Bonzini s->bustype = CIRRUS_BUSTYPE_ISA;
287249ab747fSPaolo Bonzini }
287349ab747fSPaolo Bonzini
287449ab747fSPaolo Bonzini /* Register ioport 0x3b0 - 0x3df */
28759eb58a47SPaolo Bonzini memory_region_init_io(&s->cirrus_vga_io, owner, &cirrus_vga_io_ops, s,
287649ab747fSPaolo Bonzini "cirrus-io", 0x30);
2877eb25a1d9SJan Kiszka memory_region_set_flush_coalesced(&s->cirrus_vga_io);
287849ab747fSPaolo Bonzini memory_region_add_subregion(system_io, 0x3b0, &s->cirrus_vga_io);
287949ab747fSPaolo Bonzini
28809eb58a47SPaolo Bonzini memory_region_init(&s->low_mem_container, owner,
288149ab747fSPaolo Bonzini "cirrus-lowmem-container",
288249ab747fSPaolo Bonzini 0x20000);
288349ab747fSPaolo Bonzini
28849eb58a47SPaolo Bonzini memory_region_init_io(&s->low_mem, owner, &cirrus_vga_mem_ops, s,
288549ab747fSPaolo Bonzini "cirrus-low-memory", 0x20000);
288649ab747fSPaolo Bonzini memory_region_add_subregion(&s->low_mem_container, 0, &s->low_mem);
288749ab747fSPaolo Bonzini for (i = 0; i < 2; ++i) {
288849ab747fSPaolo Bonzini static const char *names[] = { "vga.bank0", "vga.bank1" };
288949ab747fSPaolo Bonzini MemoryRegion *bank = &s->cirrus_bank[i];
28909eb58a47SPaolo Bonzini memory_region_init_alias(bank, owner, names[i], &s->vga.vram,
28919eb58a47SPaolo Bonzini 0, 0x8000);
289249ab747fSPaolo Bonzini memory_region_set_enabled(bank, false);
289349ab747fSPaolo Bonzini memory_region_add_subregion_overlap(&s->low_mem_container, i * 0x8000,
289449ab747fSPaolo Bonzini bank, 1);
289549ab747fSPaolo Bonzini }
289649ab747fSPaolo Bonzini memory_region_add_subregion_overlap(system_memory,
2897b19c1c08SHervé Poussineau 0x000a0000,
289849ab747fSPaolo Bonzini &s->low_mem_container,
289949ab747fSPaolo Bonzini 1);
290049ab747fSPaolo Bonzini memory_region_set_coalescing(&s->low_mem);
290149ab747fSPaolo Bonzini
290249ab747fSPaolo Bonzini /* I/O handler for LFB */
29039eb58a47SPaolo Bonzini memory_region_init_io(&s->cirrus_linear_io, owner, &cirrus_linear_io_ops, s,
2904f0353b0dSPhilippe Mathieu-Daudé "cirrus-linear-io", s->vga.vram_size_mb * MiB);
290549ab747fSPaolo Bonzini memory_region_set_flush_coalesced(&s->cirrus_linear_io);
290649ab747fSPaolo Bonzini
290749ab747fSPaolo Bonzini /* I/O handler for LFB */
29089eb58a47SPaolo Bonzini memory_region_init_io(&s->cirrus_linear_bitblt_io, owner,
290949ab747fSPaolo Bonzini &cirrus_linear_bitblt_io_ops,
291049ab747fSPaolo Bonzini s,
291149ab747fSPaolo Bonzini "cirrus-bitblt-mmio",
291249ab747fSPaolo Bonzini 0x400000);
291349ab747fSPaolo Bonzini memory_region_set_flush_coalesced(&s->cirrus_linear_bitblt_io);
291449ab747fSPaolo Bonzini
291549ab747fSPaolo Bonzini /* I/O handler for memory-mapped I/O */
29169eb58a47SPaolo Bonzini memory_region_init_io(&s->cirrus_mmio_io, owner, &cirrus_mmio_io_ops, s,
291749ab747fSPaolo Bonzini "cirrus-mmio", CIRRUS_PNPMMIO_SIZE);
291849ab747fSPaolo Bonzini memory_region_set_flush_coalesced(&s->cirrus_mmio_io);
291949ab747fSPaolo Bonzini
292049ab747fSPaolo Bonzini s->real_vram_size =
2921f0353b0dSPhilippe Mathieu-Daudé (s->device_id == CIRRUS_ID_CLGD5446) ? 4 * MiB : 2 * MiB;
292249ab747fSPaolo Bonzini
292349ab747fSPaolo Bonzini /* XXX: s->vga.vram_size must be a power of two */
292449ab747fSPaolo Bonzini s->cirrus_addr_mask = s->real_vram_size - 1;
292549ab747fSPaolo Bonzini s->linear_mmio_mask = s->real_vram_size - 256;
292649ab747fSPaolo Bonzini
292749ab747fSPaolo Bonzini s->vga.get_bpp = cirrus_get_bpp;
2928f9b925fdSPaolo Bonzini s->vga.get_params = cirrus_get_params;
292949ab747fSPaolo Bonzini s->vga.get_resolution = cirrus_get_resolution;
293049ab747fSPaolo Bonzini s->vga.cursor_invalidate = cirrus_cursor_invalidate;
293149ab747fSPaolo Bonzini s->vga.cursor_draw_line = cirrus_cursor_draw_line;
293249ab747fSPaolo Bonzini
293349ab747fSPaolo Bonzini qemu_register_reset(cirrus_reset, s);
293449ab747fSPaolo Bonzini }
293549ab747fSPaolo Bonzini
293649ab747fSPaolo Bonzini /***************************************
293749ab747fSPaolo Bonzini *
293849ab747fSPaolo Bonzini * PCI bus support
293949ab747fSPaolo Bonzini *
294049ab747fSPaolo Bonzini ***************************************/
294149ab747fSPaolo Bonzini
pci_cirrus_vga_realize(PCIDevice * dev,Error ** errp)2942f409edf7SMarkus Armbruster static void pci_cirrus_vga_realize(PCIDevice *dev, Error **errp)
294349ab747fSPaolo Bonzini {
2944d338bae3SGonglei PCICirrusVGAState *d = PCI_CIRRUS_VGA(dev);
294549ab747fSPaolo Bonzini CirrusVGAState *s = &d->cirrus_vga;
294649ab747fSPaolo Bonzini PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
294749ab747fSPaolo Bonzini int16_t device_id = pc->device_id;
294849ab747fSPaolo Bonzini
29495f2011beSThomas Huth /*
29505f2011beSThomas Huth * Follow real hardware, cirrus card emulated has 4 MB video memory.
29515f2011beSThomas Huth * Also accept 8 MB/16 MB for backward compatibility.
29525f2011beSThomas Huth */
2953f61d82c2SGonglei if (s->vga.vram_size_mb != 4 && s->vga.vram_size_mb != 8 &&
2954f61d82c2SGonglei s->vga.vram_size_mb != 16) {
2955f409edf7SMarkus Armbruster error_setg(errp, "Invalid cirrus_vga ram size '%u'",
2956f61d82c2SGonglei s->vga.vram_size_mb);
2957f409edf7SMarkus Armbruster return;
2958f61d82c2SGonglei }
295949ab747fSPaolo Bonzini /* setup VGA */
29606832deb8SThomas Huth if (!vga_common_init(&s->vga, OBJECT(dev), errp)) {
29616832deb8SThomas Huth return;
29626832deb8SThomas Huth }
29639eb58a47SPaolo Bonzini cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev),
296449ab747fSPaolo Bonzini pci_address_space_io(dev));
29655643706aSGerd Hoffmann s->vga.con = graphic_console_init(DEVICE(dev), 0, s->vga.hw_ops, &s->vga);
296649ab747fSPaolo Bonzini
296749ab747fSPaolo Bonzini /* setup PCI */
29683eadad55SPaolo Bonzini memory_region_init(&s->pci_bar, OBJECT(dev), "cirrus-pci-bar0", 0x2000000);
296949ab747fSPaolo Bonzini
297049ab747fSPaolo Bonzini /* XXX: add byte swapping apertures */
297149ab747fSPaolo Bonzini memory_region_add_subregion(&s->pci_bar, 0, &s->cirrus_linear_io);
297249ab747fSPaolo Bonzini memory_region_add_subregion(&s->pci_bar, 0x1000000,
297349ab747fSPaolo Bonzini &s->cirrus_linear_bitblt_io);
297449ab747fSPaolo Bonzini
297549ab747fSPaolo Bonzini /* setup memory space */
297649ab747fSPaolo Bonzini /* memory #0 LFB */
297749ab747fSPaolo Bonzini /* memory #1 memory-mapped I/O */
297849ab747fSPaolo Bonzini /* XXX: s->vga.vram_size must be a power of two */
297949ab747fSPaolo Bonzini pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->pci_bar);
298049ab747fSPaolo Bonzini if (device_id == CIRRUS_ID_CLGD5446) {
298149ab747fSPaolo Bonzini pci_register_bar(&d->dev, 1, 0, &s->cirrus_mmio_io);
298249ab747fSPaolo Bonzini }
298349ab747fSPaolo Bonzini }
298449ab747fSPaolo Bonzini
298549ab747fSPaolo Bonzini static Property pci_vga_cirrus_properties[] = {
298649ab747fSPaolo Bonzini DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState,
298773c14813SGerd Hoffmann cirrus_vga.vga.vram_size_mb, 4),
2988827bd517SGerd Hoffmann DEFINE_PROP_BOOL("blitter", struct PCICirrusVGAState,
2989827bd517SGerd Hoffmann cirrus_vga.enable_blitter, true),
29901fcfdc43SGerd Hoffmann DEFINE_PROP_BOOL("global-vmstate", struct PCICirrusVGAState,
29911fcfdc43SGerd Hoffmann cirrus_vga.vga.global_vmstate, false),
299249ab747fSPaolo Bonzini DEFINE_PROP_END_OF_LIST(),
299349ab747fSPaolo Bonzini };
299449ab747fSPaolo Bonzini
cirrus_vga_class_init(ObjectClass * klass,void * data)299549ab747fSPaolo Bonzini static void cirrus_vga_class_init(ObjectClass *klass, void *data)
299649ab747fSPaolo Bonzini {
299749ab747fSPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass);
299849ab747fSPaolo Bonzini PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
299949ab747fSPaolo Bonzini
3000f409edf7SMarkus Armbruster k->realize = pci_cirrus_vga_realize;
300149ab747fSPaolo Bonzini k->romfile = VGABIOS_CIRRUS_FILENAME;
300249ab747fSPaolo Bonzini k->vendor_id = PCI_VENDOR_ID_CIRRUS;
300349ab747fSPaolo Bonzini k->device_id = CIRRUS_ID_CLGD5446;
300449ab747fSPaolo Bonzini k->class_id = PCI_CLASS_DISPLAY_VGA;
3005125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
300649ab747fSPaolo Bonzini dc->desc = "Cirrus CLGD 54xx VGA";
300749ab747fSPaolo Bonzini dc->vmsd = &vmstate_pci_cirrus_vga;
30084f67d30bSMarc-André Lureau device_class_set_props(dc, pci_vga_cirrus_properties);
30092897ae02SIgor Mammedov dc->hotpluggable = false;
301049ab747fSPaolo Bonzini }
301149ab747fSPaolo Bonzini
301249ab747fSPaolo Bonzini static const TypeInfo cirrus_vga_info = {
3013d338bae3SGonglei .name = TYPE_PCI_CIRRUS_VGA,
301449ab747fSPaolo Bonzini .parent = TYPE_PCI_DEVICE,
301549ab747fSPaolo Bonzini .instance_size = sizeof(PCICirrusVGAState),
301649ab747fSPaolo Bonzini .class_init = cirrus_vga_class_init,
3017fd3b02c8SEduardo Habkost .interfaces = (InterfaceInfo[]) {
3018fd3b02c8SEduardo Habkost { INTERFACE_CONVENTIONAL_PCI_DEVICE },
3019fd3b02c8SEduardo Habkost { },
3020fd3b02c8SEduardo Habkost },
302149ab747fSPaolo Bonzini };
302249ab747fSPaolo Bonzini
cirrus_vga_register_types(void)302349ab747fSPaolo Bonzini static void cirrus_vga_register_types(void)
302449ab747fSPaolo Bonzini {
302549ab747fSPaolo Bonzini type_register_static(&cirrus_vga_info);
302649ab747fSPaolo Bonzini }
302749ab747fSPaolo Bonzini
302849ab747fSPaolo Bonzini type_init(cirrus_vga_register_types)
3029