📄 cirrus_vga.c
字号:
/* * QEMU Cirrus CLGD 54xx VGA Emulator. * * Copyright (c) 2004 Fabrice Bellard * Copyright (c) 2004 Makoto Suzuki (suzu) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. *//* * Reference: Finn Thogersons' VGADOC4b * available at http://home.worldonline.dk/~finth/ */#include "vl.h"#include "vga_int.h"/* * TODO: * - destination write mask support not complete (bits 5..7) * - optimize linear mappings * - optimize bitblt functions *///#define DEBUG_CIRRUS//#define DEBUG_BITBLT/*************************************** * * definitions * ***************************************/#define qemu_MIN(a,b) ((a) < (b) ? (a) : (b))// ID#define CIRRUS_ID_CLGD5422 (0x23<<2)#define CIRRUS_ID_CLGD5426 (0x24<<2)#define CIRRUS_ID_CLGD5424 (0x25<<2)#define CIRRUS_ID_CLGD5428 (0x26<<2)#define CIRRUS_ID_CLGD5430 (0x28<<2)#define CIRRUS_ID_CLGD5434 (0x2A<<2)#define CIRRUS_ID_CLGD5436 (0x2B<<2)#define CIRRUS_ID_CLGD5446 (0x2E<<2)// sequencer 0x07#define CIRRUS_SR7_BPP_VGA 0x00#define CIRRUS_SR7_BPP_SVGA 0x01#define CIRRUS_SR7_BPP_MASK 0x0e#define CIRRUS_SR7_BPP_8 0x00#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02#define CIRRUS_SR7_BPP_24 0x04#define CIRRUS_SR7_BPP_16 0x06#define CIRRUS_SR7_BPP_32 0x08#define CIRRUS_SR7_ISAADDR_MASK 0xe0// sequencer 0x0f#define CIRRUS_MEMSIZE_512k 0x08#define CIRRUS_MEMSIZE_1M 0x10#define CIRRUS_MEMSIZE_2M 0x18#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled.// sequencer 0x12#define CIRRUS_CURSOR_SHOW 0x01#define CIRRUS_CURSOR_HIDDENPEL 0x02#define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear// sequencer 0x17#define CIRRUS_BUSTYPE_VLBFAST 0x10#define CIRRUS_BUSTYPE_PCI 0x20#define CIRRUS_BUSTYPE_VLBSLOW 0x30#define CIRRUS_BUSTYPE_ISA 0x38#define CIRRUS_MMIO_ENABLE 0x04#define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared.#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80// control 0x0b#define CIRRUS_BANKING_DUAL 0x01#define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k// control 0x30#define CIRRUS_BLTMODE_BACKWARDS 0x01#define CIRRUS_BLTMODE_MEMSYSDEST 0x02#define CIRRUS_BLTMODE_MEMSYSSRC 0x04#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08#define CIRRUS_BLTMODE_PATTERNCOPY 0x40#define CIRRUS_BLTMODE_COLOREXPAND 0x80#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30// control 0x31#define CIRRUS_BLT_BUSY 0x01#define CIRRUS_BLT_START 0x02#define CIRRUS_BLT_RESET 0x04#define CIRRUS_BLT_FIFOUSED 0x10#define CIRRUS_BLT_AUTOSTART 0x80// control 0x32#define CIRRUS_ROP_0 0x00#define CIRRUS_ROP_SRC_AND_DST 0x05#define CIRRUS_ROP_NOP 0x06#define CIRRUS_ROP_SRC_AND_NOTDST 0x09#define CIRRUS_ROP_NOTDST 0x0b#define CIRRUS_ROP_SRC 0x0d#define CIRRUS_ROP_1 0x0e#define CIRRUS_ROP_NOTSRC_AND_DST 0x50#define CIRRUS_ROP_SRC_XOR_DST 0x59#define CIRRUS_ROP_SRC_OR_DST 0x6d#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95#define CIRRUS_ROP_SRC_OR_NOTDST 0xad#define CIRRUS_ROP_NOTSRC 0xd0#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda#define CIRRUS_ROP_NOP_INDEX 2#define CIRRUS_ROP_SRC_INDEX 5// control 0x33#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04#define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01// memory-mapped IO#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword#define CIRRUS_MMIO_BLTWIDTH 0x08 // word#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte#define CIRRUS_MMIO_BLTMODE 0x18 // byte#define CIRRUS_MMIO_BLTROP 0x1a // byte#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c // word?#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word?#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24 // word#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26 // word#define CIRRUS_MMIO_LINEARDRAW_END_X 0x28 // word#define CIRRUS_MMIO_LINEARDRAW_END_Y 0x2a // word#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c // byte#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d // byte#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e // byte#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f // byte#define CIRRUS_MMIO_BRESENHAM_K1 0x30 // word#define CIRRUS_MMIO_BRESENHAM_K3 0x32 // word#define CIRRUS_MMIO_BRESENHAM_ERROR 0x34 // word#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36 // word#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38 // byte#define CIRRUS_MMIO_LINEDRAW_MODE 0x39 // byte#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte// PCI 0x00: vendor, 0x02: device#define PCI_VENDOR_CIRRUS 0x1013#define PCI_DEVICE_CLGD5462 0x00d0#define PCI_DEVICE_CLGD5465 0x00d6// PCI 0x04: command(word), 0x06(word): status#define PCI_COMMAND_IOACCESS 0x0001#define PCI_COMMAND_MEMACCESS 0x0002#define PCI_COMMAND_BUSMASTER 0x0004#define PCI_COMMAND_SPECIALCYCLE 0x0008#define PCI_COMMAND_MEMWRITEINVALID 0x0010#define PCI_COMMAND_PALETTESNOOPING 0x0020#define PCI_COMMAND_PARITYDETECTION 0x0040#define PCI_COMMAND_ADDRESSDATASTEPPING 0x0080#define PCI_COMMAND_SERR 0x0100#define PCI_COMMAND_BACKTOBACKTRANS 0x0200// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)#define PCI_CLASS_BASE_DISPLAY 0x03// PCI 0x08, 0x00ff0000#define PCI_CLASS_SUB_VGA 0x00// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test)#define PCI_CLASS_HEADERTYPE_00h 0x00// 0x10-0x3f (headertype 00h)// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers// 0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x)#define PCI_MAP_MEM 0x0#define PCI_MAP_IO 0x1#define PCI_MAP_MEM_ADDR_MASK (~0xf)#define PCI_MAP_IO_ADDR_MASK (~0x3)#define PCI_MAP_MEMFLAGS_32BIT 0x0#define PCI_MAP_MEMFLAGS_32BIT_1M 0x1#define PCI_MAP_MEMFLAGS_64BIT 0x4#define PCI_MAP_MEMFLAGS_CACHEABLE 0x8// PCI 0x28: cardbus CIS pointer// PCI 0x2c: subsystem vendor id, 0x2e: subsystem id// PCI 0x30: expansion ROM base address#define PCI_ROMBIOS_ENABLED 0x1// PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer// PCI 0x38: reserved// PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat#define CIRRUS_PNPMMIO_SIZE 0x1000/* I/O and memory hook */#define CIRRUS_HOOK_NOT_HANDLED 0#define CIRRUS_HOOK_HANDLED 1struct CirrusVGAState;typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s, uint8_t * dst, const uint8_t * src, int dstpitch, int srcpitch, int bltwidth, int bltheight);typedef void (*cirrus_fill_t)(struct CirrusVGAState *s, uint8_t *dst, int dst_pitch, int width, int height);typedef struct CirrusVGAState { VGA_STATE_COMMON int cirrus_linear_io_addr; int cirrus_linear_bitblt_io_addr; int cirrus_mmio_io_addr; uint32_t cirrus_addr_mask; uint32_t linear_mmio_mask; uint8_t cirrus_shadow_gr0; uint8_t cirrus_shadow_gr1; uint8_t cirrus_hidden_dac_lockindex; uint8_t cirrus_hidden_dac_data; uint32_t cirrus_bank_base[2]; uint32_t cirrus_bank_limit[2]; uint8_t cirrus_hidden_palette[48]; uint32_t hw_cursor_x; uint32_t hw_cursor_y; int cirrus_blt_pixelwidth; int cirrus_blt_width; int cirrus_blt_height; int cirrus_blt_dstpitch; int cirrus_blt_srcpitch; uint32_t cirrus_blt_fgcol; uint32_t cirrus_blt_bgcol; uint32_t cirrus_blt_dstaddr; uint32_t cirrus_blt_srcaddr; uint8_t cirrus_blt_mode; uint8_t cirrus_blt_modeext; cirrus_bitblt_rop_t cirrus_rop;#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */ uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE]; uint8_t *cirrus_srcptr; uint8_t *cirrus_srcptr_end; uint32_t cirrus_srccounter; /* hwcursor display state */ int last_hw_cursor_size; int last_hw_cursor_x; int last_hw_cursor_y; int last_hw_cursor_y_start; int last_hw_cursor_y_end; int real_vram_size; /* XXX: suppress that */ CPUWriteMemoryFunc **cirrus_linear_write;} CirrusVGAState;typedef struct PCICirrusVGAState { PCIDevice dev; CirrusVGAState cirrus_vga;} PCICirrusVGAState;static uint8_t rop_to_index[256]; /*************************************** * * prototypes. * ***************************************/static void cirrus_bitblt_reset(CirrusVGAState *s);static void cirrus_update_memory_access(CirrusVGAState *s);/*************************************** * * raster operations * ***************************************/static void cirrus_bitblt_rop_nop(CirrusVGAState *s, uint8_t *dst,const uint8_t *src, int dstpitch,int srcpitch, int bltwidth,int bltheight){}static void cirrus_bitblt_fill_nop(CirrusVGAState *s, uint8_t *dst, int dstpitch, int bltwidth,int bltheight){}#define ROP_NAME 0#define ROP_OP(d, s) d = 0#include "cirrus_vga_rop.h"#define ROP_NAME src_and_dst#define ROP_OP(d, s) d = (s) & (d)#include "cirrus_vga_rop.h"#define ROP_NAME src_and_notdst#define ROP_OP(d, s) d = (s) & (~(d))#include "cirrus_vga_rop.h"#define ROP_NAME notdst#define ROP_OP(d, s) d = ~(d)#include "cirrus_vga_rop.h"#define ROP_NAME src#define ROP_OP(d, s) d = s#include "cirrus_vga_rop.h"#define ROP_NAME 1#define ROP_OP(d, s) d = ~0#include "cirrus_vga_rop.h"#define ROP_NAME notsrc_and_dst#define ROP_OP(d, s) d = (~(s)) & (d)#include "cirrus_vga_rop.h"#define ROP_NAME src_xor_dst#define ROP_OP(d, s) d = (s) ^ (d)#include "cirrus_vga_rop.h"#define ROP_NAME src_or_dst#define ROP_OP(d, s) d = (s) | (d)#include "cirrus_vga_rop.h"#define ROP_NAME notsrc_or_notdst#define ROP_OP(d, s) d = (~(s)) | (~(d))#include "cirrus_vga_rop.h"#define ROP_NAME src_notxor_dst#define ROP_OP(d, s) d = ~((s) ^ (d))#include "cirrus_vga_rop.h"#define ROP_NAME src_or_notdst#define ROP_OP(d, s) d = (s) | (~(d))#include "cirrus_vga_rop.h"#define ROP_NAME notsrc#define ROP_OP(d, s) d = (~(s))#include "cirrus_vga_rop.h"#define ROP_NAME notsrc_or_dst#define ROP_OP(d, s) d = (~(s)) | (d)#include "cirrus_vga_rop.h"#define ROP_NAME notsrc_and_notdst#define ROP_OP(d, s) d = (~(s)) & (~(d))#include "cirrus_vga_rop.h"static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = { cirrus_bitblt_rop_fwd_0, cirrus_bitblt_rop_fwd_src_and_dst, cirrus_bitblt_rop_nop, cirrus_bitblt_rop_fwd_src_and_notdst, cirrus_bitblt_rop_fwd_notdst, cirrus_bitblt_rop_fwd_src, cirrus_bitblt_rop_fwd_1, cirrus_bitblt_rop_fwd_notsrc_and_dst, cirrus_bitblt_rop_fwd_src_xor_dst, cirrus_bitblt_rop_fwd_src_or_dst, cirrus_bitblt_rop_fwd_notsrc_or_notdst, cirrus_bitblt_rop_fwd_src_notxor_dst, cirrus_bitblt_rop_fwd_src_or_notdst, cirrus_bitblt_rop_fwd_notsrc, cirrus_bitblt_rop_fwd_notsrc_or_dst, cirrus_bitblt_rop_fwd_notsrc_and_notdst,};static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = { cirrus_bitblt_rop_bkwd_0, cirrus_bitblt_rop_bkwd_src_and_dst, cirrus_bitblt_rop_nop, cirrus_bitblt_rop_bkwd_src_and_notdst, cirrus_bitblt_rop_bkwd_notdst, cirrus_bitblt_rop_bkwd_src, cirrus_bitblt_rop_bkwd_1, cirrus_bitblt_rop_bkwd_notsrc_and_dst, cirrus_bitblt_rop_bkwd_src_xor_dst, cirrus_bitblt_rop_bkwd_src_or_dst, cirrus_bitblt_rop_bkwd_notsrc_or_notdst, cirrus_bitblt_rop_bkwd_src_notxor_dst, cirrus_bitblt_rop_bkwd_src_or_notdst, cirrus_bitblt_rop_bkwd_notsrc, cirrus_bitblt_rop_bkwd_notsrc_or_dst, cirrus_bitblt_rop_bkwd_notsrc_and_notdst,}; #define ROP2(name) {\ name ## _8,\ name ## _16,\ name ## _24,\ name ## _32,\ }#define ROP_NOP2(func) {\ func,\ func,\ func,\ func,\ }static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = { ROP2(cirrus_patternfill_0), ROP2(cirrus_patternfill_src_and_dst), ROP_NOP2(cirrus_bitblt_rop_nop), ROP2(cirrus_patternfill_src_and_notdst), ROP2(cirrus_patternfill_notdst), ROP2(cirrus_patternfill_src), ROP2(cirrus_patternfill_1), ROP2(cirrus_patternfill_notsrc_and_dst), ROP2(cirrus_patternfill_src_xor_dst), ROP2(cirrus_patternfill_src_or_dst), ROP2(cirrus_patternfill_notsrc_or_notdst), ROP2(cirrus_patternfill_src_notxor_dst),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -