///////////////////////////////////////////////////////////////////////// // $Id$ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Makoto Suzuki (suzu) // Volker Ruppert (vruppert) // Robin Kay (komadori) // Copyright (C) 2004-2013 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // limited PCI/ISA CLGD5446 support for Bochs // // there are still many unimplemented features: // // - destination write mask support is not complete (bit 5..6) // - BLT mode extension support is not complete (bit 3..4) // - 4bpp modes // // some codes are copied from vga.cc and modified. // some codes are ported from the cirrus emulation in qemu // (http://savannah.nongnu.org/projects/qemu). #define BX_PLUGGABLE #include "iodev.h" #include "vgacore.h" #include "svga_cirrus.h" #include "virt_timer.h" #if BX_SUPPORT_CLGD54XX // Only reference the array if the tile numbers are within the bounds // of the array. If out of bounds, do nothing. #define SET_TILE_UPDATED(xtile, ytile, value) \ do { \ if (((xtile) < BX_CIRRUS_THIS s.num_x_tiles) && ((ytile) < BX_CIRRUS_THIS s.num_y_tiles)) \ BX_CIRRUS_THIS s.vga_tile_updated[(xtile)+(ytile)*BX_CIRRUS_THIS s.num_x_tiles] = value; \ } while (0) // Only reference the array if the tile numbers are within the bounds // of the array. If out of bounds, return 0. #define GET_TILE_UPDATED(xtile,ytile) \ ((((xtile) < BX_CIRRUS_THIS s.num_x_tiles) && ((ytile) < BX_CIRRUS_THIS s.num_y_tiles))? \ BX_CIRRUS_THIS s.vga_tile_updated[(xtile)+(ytile)*BX_CIRRUS_THIS s.num_x_tiles] \ : 0) #define LOG_THIS BX_CIRRUS_THIS #if BX_USE_CIRRUS_SMF #define VGA_READ(addr,len) bx_vgacore_c::read_handler(theSvga,addr,len) #define VGA_WRITE(addr,val,len) bx_vgacore_c::write_handler(theSvga,addr,val,len) #define SVGA_READ(addr,len) svga_read_handler(theSvga,addr,len) #define SVGA_WRITE(addr,val,len) svga_write_handler(theSvga,addr,val,len) #else #define VGA_READ(addr,len) bx_vgacore_c::read(addr,len) #define VGA_WRITE(addr,val,len) bx_vgacore_c::write(addr,val,len) #define SVGA_READ(addr,len) svga_read(addr,len) #define SVGA_WRITE(addr,val,len) svga_write(addr,val,len) #endif // BX_USE_CIRRUS_SMF #define ID_CLGD5428 (0x26<<2) #define ID_CLGD5430 (0x28<<2) #define ID_CLGD5434 (0x2A<<2) #define 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_AND_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_OR_NOTDST 0xda // control 0x33 #define CIRRUS_BLTMODEEXT_SYNCDISPSWITCH 0x10 // unimplemented #define CIRRUS_BLTMODEEXT_BKGNDONLYCLIP 0x08 // unimplemented #define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 #define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02 #define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 #define CLGD543x_MMIO_BLTBGCOLOR 0x00 // dword #define CLGD543x_MMIO_BLTFGCOLOR 0x04 // dword #define CLGD543x_MMIO_BLTWIDTH 0x08 // word #define CLGD543x_MMIO_BLTHEIGHT 0x0a // word #define CLGD543x_MMIO_BLTDESTPITCH 0x0c // word #define CLGD543x_MMIO_BLTSRCPITCH 0x0e // word #define CLGD543x_MMIO_BLTDESTADDR 0x10 // dword #define CLGD543x_MMIO_BLTSRCADDR 0x14 // dword #define CLGD543x_MMIO_BLTWRITEMASK 0x17 // byte #define CLGD543x_MMIO_BLTMODE 0x18 // byte #define CLGD543x_MMIO_BLTROP 0x1a // byte #define CLGD543x_MMIO_BLTMODEEXT 0x1b // byte #define CLGD543x_MMIO_BLTTRANSPARENTCOLOR 0x1c // word? #define CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word? #define CLGD543x_MMIO_BLTSTATUS 0x40 // byte // PCI 0x00: vendor, 0x02: device #define PCI_VENDOR_CIRRUS 0x1013 #define PCI_DEVICE_CLGD5430 0x00a0 // CLGD5430 or CLGD5440 #define PCI_DEVICE_CLGD5434 0x00a8 #define PCI_DEVICE_CLGD5436 0x00ac #define PCI_DEVICE_CLGD5446 0x00b8 #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 // PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer // PCI 0x38: reserved // PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat // PCI 0x40-0xff: device dependent fields // default PnP memory and memory-mapped I/O sizes #define CIRRUS_PNPMEM_SIZE CIRRUS_VIDEO_MEMORY_BYTES #define CIRRUS_PNPMMIO_SIZE 0x1000 static bx_svga_cirrus_c *theSvga = NULL; int libsvga_cirrus_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { theSvga = new bx_svga_cirrus_c(); bx_devices.pluginVgaDevice = theSvga; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theSvga, BX_PLUGIN_CIRRUS); return 0; // Success } else { return -1; } } void libsvga_cirrus_LTX_plugin_fini(void) { delete theSvga; } bx_svga_cirrus_c::bx_svga_cirrus_c() : bx_vgacore_c() { // nothing else to do } bx_svga_cirrus_c::~bx_svga_cirrus_c() { SIM->get_bochs_root()->remove("svga_cirrus"); BX_DEBUG(("Exit")); } void bx_svga_cirrus_c::init_vga_extension(void) { if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "cirrus")) { BX_CIRRUS_THIS put("CIRRUS"); // initialize SVGA stuffs. BX_CIRRUS_THIS bx_vgacore_c::init_iohandlers(svga_read_handler, svga_write_handler); BX_CIRRUS_THIS bx_vgacore_c::init_systemtimer(svga_timer_handler, svga_param_handler); BX_CIRRUS_THIS pci_enabled = SIM->is_pci_device("cirrus"); BX_CIRRUS_THIS svga_init_members(); #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { BX_CIRRUS_THIS svga_init_pcihandlers(); BX_INFO(("CL-GD5446 PCI initialized")); } else #endif { BX_INFO(("CL-GD5430 ISA initialized")); } BX_CIRRUS_THIS s.max_xres = 1600; BX_CIRRUS_THIS s.max_yres = 1200; BX_CIRRUS_THIS extension_init = 1; } else { BX_CIRRUS_THIS sequencer.reg[0x07] = 0x00; // Cirrus extension disabled // initialize VGA extension, read/write handlers and timer BX_CIRRUS_THIS bx_vgacore_c::init_vga_extension(); } #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("cirrus", this); #endif } void bx_svga_cirrus_c::svga_init_members() { unsigned i; // clear all registers. BX_CIRRUS_THIS sequencer.index = CIRRUS_SEQENCER_MAX + 1; for (i = 0; i <= CIRRUS_SEQENCER_MAX; i++) BX_CIRRUS_THIS sequencer.reg[i] = 0x00; BX_CIRRUS_THIS control.index = CIRRUS_CONTROL_MAX + 1; for (i = 0; i <= CIRRUS_CONTROL_MAX; i++) BX_CIRRUS_THIS control.reg[i] = 0x00; BX_CIRRUS_THIS control.shadow_reg0 = 0x00; BX_CIRRUS_THIS control.shadow_reg1 = 0x00; BX_CIRRUS_THIS crtc.index = CIRRUS_CRTC_MAX + 1; for (i = 0; i <= CIRRUS_CRTC_MAX; i++) BX_CIRRUS_THIS crtc.reg[i] = 0x00; BX_CIRRUS_THIS hidden_dac.lockindex = 0; BX_CIRRUS_THIS hidden_dac.data = 0x00; BX_CIRRUS_THIS svga_unlock_special = 0; BX_CIRRUS_THIS svga_needs_update_tile = 1; BX_CIRRUS_THIS svga_needs_update_dispentire = 1; BX_CIRRUS_THIS svga_needs_update_mode = 0; BX_CIRRUS_THIS svga_xres = 640; BX_CIRRUS_THIS svga_yres = 480; BX_CIRRUS_THIS svga_bpp = 8; BX_CIRRUS_THIS svga_pitch = 640; BX_CIRRUS_THIS bank_base[0] = 0; BX_CIRRUS_THIS bank_base[1] = 0; BX_CIRRUS_THIS bank_limit[0] = 0; BX_CIRRUS_THIS bank_limit[1] = 0; svga_reset_bitblt(); BX_CIRRUS_THIS hw_cursor.x = 0; BX_CIRRUS_THIS hw_cursor.y = 0; BX_CIRRUS_THIS hw_cursor.size = 0; // memory allocation. if (BX_CIRRUS_THIS s.memory == NULL) BX_CIRRUS_THIS s.memory = new Bit8u[CIRRUS_VIDEO_MEMORY_BYTES]; // set some registers. BX_CIRRUS_THIS sequencer.reg[0x06] = 0x0f; BX_CIRRUS_THIS sequencer.reg[0x07] = 0x00; // 0xf0:linearbase(0x00 if disabled) #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { BX_CIRRUS_THIS svga_unlock_special = 1; BX_CIRRUS_THIS crtc.reg[0x27] = ID_CLGD5446; BX_CIRRUS_THIS sequencer.reg[0x1F] = 0x2d; // MemClock BX_CIRRUS_THIS control.reg[0x18] = 0x0f; BX_CIRRUS_THIS sequencer.reg[0x0F] = 0x98; BX_CIRRUS_THIS sequencer.reg[0x17] = CIRRUS_BUSTYPE_PCI; BX_CIRRUS_THIS sequencer.reg[0x15] = 0x04; // memory size 4MB BX_CIRRUS_THIS s.memsize = (4 << 20); } else #endif { BX_CIRRUS_THIS crtc.reg[0x27] = ID_CLGD5430; BX_CIRRUS_THIS sequencer.reg[0x1F] = 0x22; // MemClock BX_CIRRUS_THIS sequencer.reg[0x0F] = CIRRUS_MEMSIZE_2M; BX_CIRRUS_THIS sequencer.reg[0x17] = CIRRUS_BUSTYPE_ISA; BX_CIRRUS_THIS sequencer.reg[0x15] = 0x03; // memory size 2MB BX_CIRRUS_THIS s.memsize = (2 << 20); } BX_CIRRUS_THIS hidden_dac.lockindex = 5; BX_CIRRUS_THIS hidden_dac.data = 0; memset(BX_CIRRUS_THIS s.memory, 0xff, CIRRUS_VIDEO_MEMORY_BYTES); BX_CIRRUS_THIS disp_ptr = BX_CIRRUS_THIS s.memory; BX_CIRRUS_THIS memsize_mask = BX_CIRRUS_THIS s.memsize - 1; } void bx_svga_cirrus_c::reset(unsigned type) { // reset VGA stuffs. BX_CIRRUS_THIS bx_vgacore_c::reset(type); if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "cirrus")) { // reset SVGA stuffs. BX_CIRRUS_THIS svga_init_members(); } } void bx_svga_cirrus_c::register_state(void) { unsigned i; char name[6]; bx_list_c *reg; if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "cirrus")) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "svga_cirrus", "Cirrus SVGA State"); bx_vgacore_c::register_state(list); bx_list_c *crtc = new bx_list_c(list, "crtc"); new bx_shadow_num_c(crtc, "index", &BX_CIRRUS_THIS crtc.index, BASE_HEX); reg = new bx_list_c(crtc, "reg"); for (i=0; i<=CIRRUS_CRTC_MAX; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS crtc.reg[i], BASE_HEX); } bx_list_c *sequ = new bx_list_c(list, "sequencer"); new bx_shadow_num_c(sequ, "index", &BX_CIRRUS_THIS sequencer.index, BASE_HEX); reg = new bx_list_c(sequ, "reg"); for (i=0; i<=CIRRUS_SEQENCER_MAX; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS sequencer.reg[i], BASE_HEX); } bx_list_c *ctrl = new bx_list_c(list, "control"); new bx_shadow_num_c(ctrl, "index", &BX_CIRRUS_THIS control.index, BASE_HEX); reg = new bx_list_c(ctrl, "reg"); for (i=0; i<=CIRRUS_CONTROL_MAX; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS control.reg[i], BASE_HEX); } new bx_shadow_num_c(ctrl, "shadow_reg0", &BX_CIRRUS_THIS control.shadow_reg0, BASE_HEX); new bx_shadow_num_c(ctrl, "shadow_reg1", &BX_CIRRUS_THIS control.shadow_reg1, BASE_HEX); bx_list_c *hdac = new bx_list_c(list, "hidden_dac"); new bx_shadow_num_c(hdac, "lockindex", &BX_CIRRUS_THIS hidden_dac.lockindex, BASE_HEX); new bx_shadow_num_c(hdac, "data", &BX_CIRRUS_THIS hidden_dac.data, BASE_HEX); reg = new bx_list_c(hdac, "palette"); for (i=0; i<48; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS hidden_dac.palette[i], BASE_HEX); } new bx_shadow_bool_c(list, "svga_unlock_special", &BX_CIRRUS_THIS svga_unlock_special); new bx_shadow_num_c(list, "svga_xres", &BX_CIRRUS_THIS svga_xres); new bx_shadow_num_c(list, "svga_yres", &BX_CIRRUS_THIS svga_yres); new bx_shadow_num_c(list, "svga_pitch", &BX_CIRRUS_THIS svga_pitch); new bx_shadow_num_c(list, "svga_bpp", &BX_CIRRUS_THIS svga_bpp); new bx_shadow_num_c(list, "svga_dispbpp", &BX_CIRRUS_THIS svga_dispbpp); new bx_shadow_num_c(list, "bank_base0", &BX_CIRRUS_THIS bank_base[0], BASE_HEX); new bx_shadow_num_c(list, "bank_base1", &BX_CIRRUS_THIS bank_base[1], BASE_HEX); new bx_shadow_num_c(list, "bank_limit0", &BX_CIRRUS_THIS bank_limit[0], BASE_HEX); new bx_shadow_num_c(list, "bank_limit1", &BX_CIRRUS_THIS bank_limit[1], BASE_HEX); bx_list_c *cursor = new bx_list_c(list, "hw_cursor"); new bx_shadow_num_c(cursor, "x", &BX_CIRRUS_THIS hw_cursor.x, BASE_HEX); new bx_shadow_num_c(cursor, "y", &BX_CIRRUS_THIS hw_cursor.y, BASE_HEX); new bx_shadow_num_c(cursor, "size", &BX_CIRRUS_THIS hw_cursor.size, BASE_HEX); #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { register_pci_state(list); } #endif } } void bx_svga_cirrus_c::after_restore_state(void) { if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { BX_CIRRUS_THIS bx_vgacore_c::after_restore_state(); } else { #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_base_address[0], &BX_CIRRUS_THIS pci_conf[0x10], 0x2000000)) { BX_INFO(("new pci_memaddr: 0x%04x", BX_CIRRUS_THIS pci_base_address[0])); } if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_base_address[1], &BX_CIRRUS_THIS pci_conf[0x14], CIRRUS_PNPMMIO_SIZE)) { BX_INFO(("new pci_mmioaddr = 0x%08x", BX_CIRRUS_THIS pci_base_address[1])); } if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_rom_address, &BX_CIRRUS_THIS pci_conf[0x30], BX_CIRRUS_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_CIRRUS_THIS pci_rom_address)); } } #endif for (unsigned i=0; i<256; i++) { bx_gui->palette_change_common(i, BX_CIRRUS_THIS s.pel.data[i].red<<2, BX_CIRRUS_THIS s.pel.data[i].green<<2, BX_CIRRUS_THIS s.pel.data[i].blue<<2); } BX_CIRRUS_THIS svga_needs_update_mode = 1; BX_CIRRUS_THIS svga_update(); } } void bx_svga_cirrus_c::redraw_area(unsigned x0, unsigned y0, unsigned width, unsigned height) { unsigned xti, yti, xt0, xt1, yt0, yt1; if ((width == 0) || (height == 0)) { return; } if (BX_CIRRUS_THIS s.vga_override && (BX_CIRRUS_THIS s.nvgadev != NULL)) { BX_CIRRUS_THIS s.nvgadev->redraw_area(x0, y0, width, height); return; } if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { BX_CIRRUS_THIS bx_vgacore_c::redraw_area(x0,y0,width,height); return; } if (BX_CIRRUS_THIS svga_needs_update_mode) { return; } BX_CIRRUS_THIS svga_needs_update_tile = 1; xt0 = x0 / X_TILESIZE; yt0 = y0 / Y_TILESIZE; if (x0 < BX_CIRRUS_THIS svga_xres) { xt1 = (x0 + width - 1) / X_TILESIZE; } else { xt1 = (BX_CIRRUS_THIS svga_xres - 1) / X_TILESIZE; } if (y0 < BX_CIRRUS_THIS svga_yres) { yt1 = (y0 + height - 1) / Y_TILESIZE; } else { yt1 = (BX_CIRRUS_THIS svga_yres - 1) / Y_TILESIZE; } for (yti=yt0; yti<=yt1; yti++) { for (xti=xt0; xti<=xt1; xti++) { SET_TILE_UPDATED (xti, yti, 1); } } } void bx_svga_cirrus_c::mem_write_mode4and5_8bpp(Bit8u mode, Bit32u offset, Bit8u value) { Bit8u val = value; Bit8u *dst; dst = BX_CIRRUS_THIS s.memory + offset; for (int x = 0; x < 8; x++) { if (val & 0x80) { *dst = BX_CIRRUS_THIS control.shadow_reg1; } else if (mode == 5) { *dst = BX_CIRRUS_THIS control.shadow_reg0; } val <<= 1; dst++; } } void bx_svga_cirrus_c::mem_write_mode4and5_16bpp(Bit8u mode, Bit32u offset, Bit8u value) { Bit8u val = value; Bit8u *dst; dst = BX_CIRRUS_THIS s.memory + offset; for (int x = 0; x < 8; x++) { if (val & 0x80) { *dst = BX_CIRRUS_THIS control.shadow_reg1; *(dst + 1) = BX_CIRRUS_THIS control.reg[0x11]; } else if (mode == 5) { *dst = BX_CIRRUS_THIS control.shadow_reg0; *(dst + 1) = BX_CIRRUS_THIS control.reg[0x10]; } val <<= 1; dst += 2; } } #if BX_SUPPORT_PCI bx_bool bx_svga_cirrus_c::cirrus_mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit8u *data_ptr; #ifdef BX_LITTLE_ENDIAN data_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { *data_ptr = BX_CIRRUS_THIS mem_read(addr); addr++; #ifdef BX_LITTLE_ENDIAN data_ptr++; #else // BX_BIG_ENDIAN data_ptr--; #endif } return 1; } #endif Bit8u bx_svga_cirrus_c::mem_read(bx_phy_address addr) { #if BX_SUPPORT_PCI if ((BX_CIRRUS_THIS pci_enabled) && (BX_CIRRUS_THIS pci_rom_size > 0)) { Bit32u mask = (BX_CIRRUS_THIS pci_rom_size - 1); if ((addr & ~mask) == BX_CIRRUS_THIS pci_rom_address) { if (BX_CIRRUS_THIS pci_conf[0x30] & 0x01) { return BX_CIRRUS_THIS pci_rom[addr & mask]; } else { return 0xff; } } } #endif if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { return BX_CIRRUS_THIS bx_vgacore_c::mem_read(addr); } #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { if ((addr >= BX_CIRRUS_THIS pci_base_address[0]) && (addr < (BX_CIRRUS_THIS pci_base_address[0] + CIRRUS_PNPMEM_SIZE))) { Bit8u *ptr; Bit32u offset = addr & BX_CIRRUS_THIS memsize_mask; if ((offset >= (BX_CIRRUS_THIS s.memsize - 256)) && ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x44)) { return svga_mmio_blt_read(offset & 0xff); } // video-to-cpu BLT if (BX_CIRRUS_THIS bitblt.memdst_needed != 0) { ptr = BX_CIRRUS_THIS bitblt.memdst_ptr; if (ptr != BX_CIRRUS_THIS bitblt.memdst_endptr) { BX_CIRRUS_THIS bitblt.memdst_ptr ++; return *ptr; } if (!svga_asyncbitblt_next()) { ptr = BX_CIRRUS_THIS bitblt.memdst_ptr; BX_CIRRUS_THIS bitblt.memdst_ptr ++; return *ptr; } } ptr = BX_CIRRUS_THIS s.memory; if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) { offset <<= 4; } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) { offset <<= 3; } offset &= BX_CIRRUS_THIS memsize_mask; return *(ptr + offset); } else if ((addr >= BX_CIRRUS_THIS pci_base_address[1]) && (addr < (BX_CIRRUS_THIS pci_base_address[1] + CIRRUS_PNPMMIO_SIZE))) { Bit32u offset = addr & (CIRRUS_PNPMMIO_SIZE - 1); if (offset >= 0x100) { return svga_mmio_blt_read(offset - 0x100); } else { return svga_mmio_vga_read(offset); } } } #endif // BX_SUPPORT_PCI if (addr >= 0xA0000 && addr <= 0xAFFFF) { Bit32u bank; Bit32u offset; Bit8u *ptr; // video-to-cpu BLT if (BX_CIRRUS_THIS bitblt.memdst_needed != 0) { ptr = BX_CIRRUS_THIS bitblt.memdst_ptr; if (ptr != BX_CIRRUS_THIS bitblt.memdst_endptr) { BX_CIRRUS_THIS bitblt.memdst_ptr ++; return *ptr; } if (!svga_asyncbitblt_next()) { ptr = BX_CIRRUS_THIS bitblt.memdst_ptr; BX_CIRRUS_THIS bitblt.memdst_ptr ++; return *ptr; } } offset = addr & 0xffff; bank = (offset >> 15); offset &= 0x7fff; if (offset < bank_limit[bank]) { offset += bank_base[bank]; if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) { offset <<= 4; } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) { offset <<= 3; } offset &= BX_CIRRUS_THIS memsize_mask; return *(BX_CIRRUS_THIS s.memory + offset); } else { return 0xff; } } else if (addr >= 0xB8000 && addr <= 0xB8100) { // memory-mapped I/O. Bit32u offset = (Bit32u) (addr - 0xb8000); if ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x04) return svga_mmio_blt_read(offset); } else { BX_DEBUG(("mem_read 0x%08x", (Bit32u)addr)); } return 0xff; } #if BX_SUPPORT_PCI bx_bool bx_svga_cirrus_c::cirrus_mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit8u *data_ptr; #ifdef BX_LITTLE_ENDIAN data_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { BX_CIRRUS_THIS mem_write(addr, *data_ptr); addr++; #ifdef BX_LITTLE_ENDIAN data_ptr++; #else // BX_BIG_ENDIAN data_ptr--; #endif } return 1; } #endif void bx_svga_cirrus_c::mem_write(bx_phy_address addr, Bit8u value) { if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { BX_CIRRUS_THIS bx_vgacore_c::mem_write(addr,value); return; } #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { if ((addr >= BX_CIRRUS_THIS pci_base_address[0]) && (addr < (BX_CIRRUS_THIS pci_base_address[0] + CIRRUS_PNPMEM_SIZE))) { Bit32u offset = addr & BX_CIRRUS_THIS memsize_mask; if ((offset >= (BX_CIRRUS_THIS s.memsize - 256)) && ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x44)) { svga_mmio_blt_write(addr & 0xff, value); return; } // cpu-to-video BLT if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) { *(BX_CIRRUS_THIS bitblt.memsrc_ptr)++ = (value); if (BX_CIRRUS_THIS bitblt.memsrc_ptr >= BX_CIRRUS_THIS bitblt.memsrc_endptr) { svga_asyncbitblt_next(); } return; } // BX_DEBUG(("write offset 0x%08x,value 0x%02x",offset,value)); if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) { offset <<= 4; } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) { offset <<= 3; } offset &= BX_CIRRUS_THIS memsize_mask; Bit8u mode = BX_CIRRUS_THIS control.reg[0x05] & 0x07; if ((mode < 4) || (mode > 5) || ((BX_CIRRUS_THIS control.reg[0x0b] & 0x4) == 0)) { *(BX_CIRRUS_THIS s.memory + offset) = value; } else { if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) != 0x14) { mem_write_mode4and5_8bpp(mode, offset, value); } else { mem_write_mode4and5_16bpp(mode, offset, value); } } BX_CIRRUS_THIS svga_needs_update_tile = 1; SET_TILE_UPDATED(((offset % BX_CIRRUS_THIS svga_pitch) / (BX_CIRRUS_THIS svga_bpp / 8)) / X_TILESIZE, (offset / BX_CIRRUS_THIS svga_pitch) / Y_TILESIZE, 1); return; } else if ((addr >= BX_CIRRUS_THIS pci_base_address[1]) && (addr < (BX_CIRRUS_THIS pci_base_address[1] + CIRRUS_PNPMMIO_SIZE))) { // memory-mapped I/O. // BX_DEBUG(("write mmio 0x%08x",addr)); Bit32u offset = addr & (CIRRUS_PNPMMIO_SIZE - 1); if (offset >= 0x100) { svga_mmio_blt_write(offset - 0x100, value); } else { svga_mmio_vga_write(offset,value); } return; } } #endif // BX_SUPPORT_PCI if (addr >= 0xA0000 && addr <= 0xAFFFF) { Bit32u bank, offset; Bit8u mode; // cpu-to-video BLT if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) { *(BX_CIRRUS_THIS bitblt.memsrc_ptr)++ = (value); if (BX_CIRRUS_THIS bitblt.memsrc_ptr >= BX_CIRRUS_THIS bitblt.memsrc_endptr) { svga_asyncbitblt_next(); } return; } offset = addr & 0xffff; bank = (offset >> 15); offset &= 0x7fff; if (offset < bank_limit[bank]) { offset += bank_base[bank]; if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) { offset <<= 4; } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) { offset <<= 3; } offset &= BX_CIRRUS_THIS memsize_mask; mode = BX_CIRRUS_THIS control.reg[0x05] & 0x07; if ((mode < 4) || (mode > 5) || ((BX_CIRRUS_THIS control.reg[0x0b] & 0x4) == 0)) { *(BX_CIRRUS_THIS s.memory + offset) = value; } else { if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) != 0x14) { mem_write_mode4and5_8bpp(mode, offset, value); } else { mem_write_mode4and5_16bpp(mode, offset, value); } } BX_CIRRUS_THIS svga_needs_update_tile = 1; SET_TILE_UPDATED(((offset % BX_CIRRUS_THIS svga_pitch) / (BX_CIRRUS_THIS svga_bpp / 8)) / X_TILESIZE, (offset / BX_CIRRUS_THIS svga_pitch) / Y_TILESIZE, 1); } } else if (addr >= 0xB8000 && addr < 0xB8100) { // memory-mapped I/O. Bit32u offset = (Bit32u) (addr - 0xb8000); if ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x04) { svga_mmio_blt_write(offset & 0xff, value); } } else { BX_DEBUG(("mem_write 0x%08x, value 0x%02x", (Bit32u)addr, value)); } } void bx_svga_cirrus_c::get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight, unsigned *txWidth) { BX_CIRRUS_THIS bx_vgacore_c::get_text_snapshot(text_snapshot,txHeight,txWidth); } Bit64s bx_svga_cirrus_c::svga_param_handler(bx_param_c *param, int set, Bit64s val) { if (set) { BX_CIRRUS_THIS update_interval = (Bit32u)(1000000 / val); BX_INFO(("Changing timer interval to %d", BX_CIRRUS_THIS update_interval)); BX_CIRRUS_THIS svga_timer_handler(theSvga); bx_virt_timer.activate_timer(BX_CIRRUS_THIS timer_id, BX_CIRRUS_THIS update_interval, 1); if (BX_CIRRUS_THIS update_interval < 300000) { BX_CIRRUS_THIS s.blink_counter = 300000 / (unsigned)BX_CIRRUS_THIS update_interval; } else { BX_CIRRUS_THIS s.blink_counter = 1; } } return val; } Bit32u bx_svga_cirrus_c::svga_read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_CIRRUS_SMF bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr; return class_ptr->svga_read(address, io_len); } Bit32u bx_svga_cirrus_c::svga_read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_CIRRUS_SMF if ((io_len == 2) && ((address & 1) == 0)) { Bit32u value; value = (Bit32u)SVGA_READ(address,1); value |= (Bit32u)SVGA_READ(address+1,1) << 8; return value; } if (io_len != 1) { BX_PANIC(("SVGA read: io_len != 1")); } switch (address) { case 0x03b4: /* VGA: CRTC Index Register (monochrome emulation modes) */ case 0x03d4: /* VGA: CRTC Index Register (color emulation modes) */ return BX_CIRRUS_THIS crtc.index; case 0x03b5: /* VGA: CRTC Registers (monochrome emulation modes) */ case 0x03d5: /* VGA: CRTC Registers (color emulation modes) */ if (BX_CIRRUS_THIS is_unlocked()) return BX_CIRRUS_THIS svga_read_crtc(address,BX_CIRRUS_THIS crtc.index); break; case 0x03c4: /* VGA: Sequencer Index Register */ if (BX_CIRRUS_THIS is_unlocked()) { Bit32u value = BX_CIRRUS_THIS sequencer.index; if ((value & 0x1e) == 0x10) { /* SR10-F0, SR11-F1 */ if (value & 1) value = ((BX_CIRRUS_THIS hw_cursor.y & 7) << 5) | 0x11; else value = ((BX_CIRRUS_THIS hw_cursor.x & 7) << 5) | 0x10; } return value; } return BX_CIRRUS_THIS sequencer.index; case 0x03c5: /* VGA: Sequencer Registers */ if ((BX_CIRRUS_THIS sequencer.index == 0x06) || (BX_CIRRUS_THIS is_unlocked())) { return BX_CIRRUS_THIS svga_read_sequencer(address,BX_CIRRUS_THIS sequencer.index); } break; case 0x03c6: /* Hidden DAC */ if (BX_CIRRUS_THIS is_unlocked()) { if ((++BX_CIRRUS_THIS hidden_dac.lockindex) == 5) { BX_CIRRUS_THIS hidden_dac.lockindex = 0; return BX_CIRRUS_THIS hidden_dac.data; } } break; case 0x03c8: /* PEL write address */ BX_CIRRUS_THIS hidden_dac.lockindex = 0; break; case 0x03c9: /* PEL Data Register, hiddem pel colors 00..0F */ if (BX_CIRRUS_THIS sequencer.reg[0x12] & CIRRUS_CURSOR_HIDDENPEL) { Bit8u index = (BX_CIRRUS_THIS s.pel.read_data_register & 0x0f) * 3 + BX_CIRRUS_THIS s.pel.read_data_cycle; Bit8u retval = BX_CIRRUS_THIS hidden_dac.palette[index]; BX_CIRRUS_THIS s.pel.read_data_cycle ++; if (BX_CIRRUS_THIS s.pel.read_data_cycle >= 3) { BX_CIRRUS_THIS s.pel.read_data_cycle = 0; BX_CIRRUS_THIS s.pel.read_data_register++; } return retval; } break; case 0x03ce: /* VGA: Graphics Controller Index Register */ return BX_CIRRUS_THIS control.index; case 0x03cf: /* VGA: Graphics Controller Registers */ if (BX_CIRRUS_THIS is_unlocked()) return BX_CIRRUS_THIS svga_read_control(address,BX_CIRRUS_THIS control.index); break; default: break; } return VGA_READ(address,io_len); } void bx_svga_cirrus_c::svga_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_CIRRUS_SMF bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr; class_ptr->svga_write(address, value, io_len); } void bx_svga_cirrus_c::svga_write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_CIRRUS_SMF if ((io_len == 2) && ((address & 1) == 0)) { SVGA_WRITE(address,value & 0xff,1); SVGA_WRITE(address+1,value >> 8,1); return; } if (io_len != 1) { BX_PANIC(("SVGA write: io_len != 1")); } switch (address) { case 0x03b4: /* VGA: CRTC Index Register (monochrome emulation modes) */ case 0x03d4: /* VGA: CRTC Index Register (color emulation modes) */ BX_CIRRUS_THIS crtc.index = value & 0x7f; break; case 0x03b5: /* VGA: CRTC Registers (monochrome emulation modes) */ case 0x03d5: /* VGA: CRTC Registers (color emulation modes) */ if (BX_CIRRUS_THIS is_unlocked()) { BX_CIRRUS_THIS svga_write_crtc(address,BX_CIRRUS_THIS crtc.index,value); return; } break; case 0x03c4: /* VGA: Sequencer Index Register */ BX_CIRRUS_THIS sequencer.index = value; break; case 0x03c5: /* VGA: Sequencer Registers */ if ((BX_CIRRUS_THIS sequencer.index == 0x06) || (BX_CIRRUS_THIS is_unlocked())) { BX_CIRRUS_THIS svga_write_sequencer(address,BX_CIRRUS_THIS sequencer.index,value); return; } break; case 0x03c6: /* Hidden DAC */ if (BX_CIRRUS_THIS is_unlocked()) { if (BX_CIRRUS_THIS hidden_dac.lockindex == 4) { BX_CIRRUS_THIS hidden_dac.data = value; } BX_CIRRUS_THIS hidden_dac.lockindex = 0; return; } break; case 0x03c9: /* PEL Data Register, hidden pel colors 00..0F */ BX_CIRRUS_THIS svga_needs_update_dispentire = 1; if (BX_CIRRUS_THIS sequencer.reg[0x12] & CIRRUS_CURSOR_HIDDENPEL) { Bit8u index = (BX_CIRRUS_THIS s.pel.write_data_register & 0x0f) * 3 + BX_CIRRUS_THIS s.pel.write_data_cycle; BX_CIRRUS_THIS hidden_dac.palette[index] = value; BX_CIRRUS_THIS s.pel.write_data_cycle ++; if (BX_CIRRUS_THIS s.pel.write_data_cycle >= 3) { BX_CIRRUS_THIS s.pel.write_data_cycle = 0; BX_CIRRUS_THIS s.pel.write_data_register++; } return; } break; case 0x03ce: /* VGA: Graphics Controller Index Register */ BX_CIRRUS_THIS control.index = value; break; case 0x03cf: /* VGA: Graphics Controller Registers */ if (BX_CIRRUS_THIS is_unlocked()) { BX_CIRRUS_THIS svga_write_control(address,BX_CIRRUS_THIS control.index,value); return; } break; default: break; } VGA_WRITE(address,value,io_len); } void bx_svga_cirrus_c::refresh_display(void *this_ptr, bx_bool redraw) { if (BX_CIRRUS_THIS s.vga_override && (BX_CIRRUS_THIS s.nvgadev != NULL)) { BX_CIRRUS_THIS s.nvgadev->refresh_display(BX_CIRRUS_THIS s.nvgadev, redraw); } else { if (redraw) { redraw_area(0, 0, BX_CIRRUS_THIS s.last_xres, BX_CIRRUS_THIS s.last_yres); } svga_timer_handler(this_ptr); } } void bx_svga_cirrus_c::svga_timer_handler(void *this_ptr) { #if !BX_USE_CIRRUS_SMF bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr; class_ptr->svga_timer(); } void bx_svga_cirrus_c::svga_timer(void) { #else // !BX_USE_CIRRUS_SMF UNUSED(this_ptr); #endif // !BX_USE_CIRRUS_SMF BX_CIRRUS_THIS svga_update(); bx_gui->flush(); } void bx_svga_cirrus_c::svga_modeupdate(void) { Bit32u iTopOffset, iWidth, iHeight; Bit8u iBpp, iDispBpp; iTopOffset = (BX_CIRRUS_THIS crtc.reg[0x0c] << 8) + BX_CIRRUS_THIS crtc.reg[0x0d] + ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x01) << 16) + ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x0c) << 15) + ((BX_CIRRUS_THIS crtc.reg[0x1d] & 0x80) << 12); iTopOffset <<= 2; iHeight = 1 + BX_CIRRUS_THIS crtc.reg[0x12] + ((BX_CIRRUS_THIS crtc.reg[0x07] & 0x02) << 7) + ((BX_CIRRUS_THIS crtc.reg[0x07] & 0x40) << 3); if ((BX_CIRRUS_THIS crtc.reg[0x1a] & 0x01) > 0) { iHeight <<= 1; } iWidth = (BX_CIRRUS_THIS crtc.reg[0x01] + 1) * 8; iBpp = 8; iDispBpp = 4; if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x1) == CIRRUS_SR7_BPP_SVGA) { switch (BX_CIRRUS_THIS sequencer.reg[0x07] & CIRRUS_SR7_BPP_MASK) { case CIRRUS_SR7_BPP_8: iBpp = 8; iDispBpp = 8; break; case CIRRUS_SR7_BPP_16_DOUBLEVCLK: case CIRRUS_SR7_BPP_16: iBpp = 16; iDispBpp = (BX_CIRRUS_THIS hidden_dac.data & 0x1) ? 16 : 15; break; case CIRRUS_SR7_BPP_24: iBpp = 24; iDispBpp = 24; break; case CIRRUS_SR7_BPP_32: iBpp = 32; iDispBpp = 32; break; default: BX_PANIC(("unknown bpp - seqencer.reg[0x07] = %02x",BX_CIRRUS_THIS sequencer.reg[0x07])); break; } } if ((iWidth != BX_CIRRUS_THIS svga_xres) || (iHeight != BX_CIRRUS_THIS svga_yres) || (iDispBpp != BX_CIRRUS_THIS svga_dispbpp)) { BX_INFO(("switched to %u x %u x %u", iWidth, iHeight, iDispBpp)); } BX_CIRRUS_THIS svga_xres = iWidth; BX_CIRRUS_THIS svga_yres = iHeight; BX_CIRRUS_THIS svga_bpp = iBpp; BX_CIRRUS_THIS svga_dispbpp = iDispBpp; BX_CIRRUS_THIS disp_ptr = BX_CIRRUS_THIS s.memory + iTopOffset; // compatibilty settings for VGA core BX_CIRRUS_THIS s.last_xres = iWidth; BX_CIRRUS_THIS s.last_yres = iHeight; BX_CIRRUS_THIS s.last_bpp = iDispBpp; } void bx_svga_cirrus_c::draw_hardware_cursor(unsigned xc, unsigned yc, bx_svga_tileinfo_t *info) { if (BX_CIRRUS_THIS hw_cursor.size && (xc < (unsigned)(BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size)) && (xc+X_TILESIZE > BX_CIRRUS_THIS hw_cursor.x) && (yc < (unsigned)(BX_CIRRUS_THIS hw_cursor.y+BX_CIRRUS_THIS hw_cursor.size)) && (yc+Y_TILESIZE > BX_CIRRUS_THIS hw_cursor.y)) { int i; unsigned w, h, pitch, cx, cy, cx0, cy0, cx1, cy1; Bit8u * tile_ptr, * tile_ptr2; Bit8u * plane0_ptr, *plane0_ptr2; Bit8u * plane1_ptr, *plane1_ptr2; unsigned long fgcol, bgcol; Bit64u plane0, plane1; cx0 = BX_CIRRUS_THIS hw_cursor.x > xc ? BX_CIRRUS_THIS hw_cursor.x : xc; cy0 = BX_CIRRUS_THIS hw_cursor.y > yc ? BX_CIRRUS_THIS hw_cursor.y : yc; cx1 = (unsigned)(BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size) < xc+X_TILESIZE ? BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size : xc+X_TILESIZE; cy1 = (unsigned)(BX_CIRRUS_THIS hw_cursor.y+BX_CIRRUS_THIS hw_cursor.size) < yc+Y_TILESIZE ? BX_CIRRUS_THIS hw_cursor.y+BX_CIRRUS_THIS hw_cursor.size : yc+Y_TILESIZE; if (info->bpp == 15) info->bpp = 16; tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h) + info->pitch * (cy0 - yc) + (info->bpp / 8) * (cx0 - xc); plane0_ptr = BX_CIRRUS_THIS s.memory + BX_CIRRUS_THIS s.memsize - 16384; switch (BX_CIRRUS_THIS hw_cursor.size) { case 32: plane0_ptr += (BX_CIRRUS_THIS sequencer.reg[0x13] & 0x3f) * 256; plane1_ptr = plane0_ptr + 128; pitch = 4; break; case 64: plane0_ptr += (BX_CIRRUS_THIS sequencer.reg[0x13] & 0x3c) * 256; plane1_ptr = plane0_ptr + 8; pitch = 16; break; default: BX_ERROR(("unsupported hardware cursor size")); return; break; } if (!info->is_indexed) { fgcol = MAKE_COLOUR( BX_CIRRUS_THIS hidden_dac.palette[45], 6, info->red_shift, info->red_mask, BX_CIRRUS_THIS hidden_dac.palette[46], 6, info->green_shift, info->green_mask, BX_CIRRUS_THIS hidden_dac.palette[47], 6, info->blue_shift, info->blue_mask); bgcol = MAKE_COLOUR( BX_CIRRUS_THIS hidden_dac.palette[0], 6, info->red_shift, info->red_mask, BX_CIRRUS_THIS hidden_dac.palette[1], 6, info->green_shift, info->green_mask, BX_CIRRUS_THIS hidden_dac.palette[2], 6, info->blue_shift, info->blue_mask); } else { // FIXME: this is a hack that works in Windows guests // TODO: compare hidden DAC entries with DAC entries to find nearest match fgcol = 0xff; bgcol = 0x00; } plane0_ptr += pitch * (cy0 - BX_CIRRUS_THIS hw_cursor.y); plane1_ptr += pitch * (cy0 - BX_CIRRUS_THIS hw_cursor.y); for (cy=cy0; cybpp/8) * (cx1 - cx0) - 1; plane0_ptr2 = plane0_ptr; plane1_ptr2 = plane1_ptr; plane0 = plane1 = 0; for (i=0; i>= BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size - cx1; plane1 >>= BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size - cx1; for (cx=cx0; cxis_little_endian) { for (i=info->bpp-8; i>-8; i-=8) { *(tile_ptr2--) = (Bit8u)(fgcol >> i); } } else { for (i=0; ibpp; i+=8) { *(tile_ptr2--) = (Bit8u)(fgcol >> i); } } } else { for (i=0; ibpp; i+=8) { *(tile_ptr2--) ^= 0xff; } } } else { if (plane1 & 1) { if (info->is_little_endian) { for (i=info->bpp-8; i>-8; i-=8) { *(tile_ptr2--) = (Bit8u)(bgcol >> i); } } else { for (i=0; ibpp; i+=8) { *(tile_ptr2--) = (Bit8u)(bgcol >> i); } } } else { tile_ptr2 -= (info->bpp/8); } } plane0 >>= 1; plane1 >>= 1; } tile_ptr += info->pitch; plane0_ptr += pitch; plane1_ptr += pitch; } } } void bx_svga_cirrus_c::svga_update(void) { unsigned width, height, pitch; /* skip screen update when the sequencer is in reset mode or video is disabled */ if (! BX_CIRRUS_THIS s.sequencer.reset1 || ! BX_CIRRUS_THIS s.sequencer.reset2 || ! BX_CIRRUS_THIS s.attribute_ctrl.video_enabled) { return; } if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { if (BX_CIRRUS_THIS svga_needs_update_mode) { BX_CIRRUS_THIS s.vga_mem_updated = 1; BX_CIRRUS_THIS svga_needs_update_mode = 0; } BX_CIRRUS_THIS bx_vgacore_c::update(); return; } else { if (BX_CIRRUS_THIS svga_needs_update_mode) { svga_modeupdate(); } } width = BX_CIRRUS_THIS svga_xres; height = BX_CIRRUS_THIS svga_yres; pitch = BX_CIRRUS_THIS svga_pitch; if (BX_CIRRUS_THIS svga_needs_update_mode) { width = BX_CIRRUS_THIS svga_xres; height = BX_CIRRUS_THIS svga_yres; bx_gui->dimension_update(width, height, 0, 0, BX_CIRRUS_THIS svga_dispbpp); BX_CIRRUS_THIS s.last_bpp = BX_CIRRUS_THIS svga_dispbpp; BX_CIRRUS_THIS svga_needs_update_mode = 0; BX_CIRRUS_THIS svga_needs_update_dispentire = 1; } if (BX_CIRRUS_THIS svga_needs_update_dispentire) { BX_CIRRUS_THIS redraw_area(0,0,width,height); BX_CIRRUS_THIS svga_needs_update_dispentire = 0; } if (!BX_CIRRUS_THIS svga_needs_update_tile) { return; } BX_CIRRUS_THIS svga_needs_update_tile = 0; unsigned xc, yc, xti, yti; unsigned r, c, w, h; int i; Bit8u red, green, blue; Bit32u colour; Bit8u * vid_ptr, * vid_ptr2; Bit8u * tile_ptr, * tile_ptr2; bx_svga_tileinfo_t info; if (bx_gui->graphics_tile_info_common(&info)) { if (info.snapshot_mode) { vid_ptr = BX_CIRRUS_THIS disp_ptr; tile_ptr = bx_gui->get_snapshot_buffer(); if (tile_ptr != NULL) { for (yc = 0; yc < height; yc++) { memcpy(tile_ptr, vid_ptr, info.pitch); vid_ptr += pitch; tile_ptr += info.pitch; } } } else if (info.is_indexed) { switch (BX_CIRRUS_THIS svga_dispbpp) { case 4: case 15: case 16: case 24: case 32: BX_ERROR(("current guest pixel format is unsupported on indexed colour host displays, svga_dispbpp=%d", BX_CIRRUS_THIS svga_dispbpp)); break; case 8: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; } } else { switch (BX_CIRRUS_THIS svga_dispbpp) { case 4: BX_ERROR(("cannot draw 4bpp SVGA")); break; case 8: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 15: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 16: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 24: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 32: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; } } } else { BX_PANIC(("cannot get svga tile info")); } } void bx_svga_cirrus_c::update_bank_ptr(Bit8u bank_index) { unsigned offset; unsigned limit; if (BX_CIRRUS_THIS banking_is_dual()) offset = BX_CIRRUS_THIS control.reg[0x09 + bank_index]; else offset = BX_CIRRUS_THIS control.reg[0x09]; if (BX_CIRRUS_THIS banking_granularity_is_16k()) offset <<= 14; else offset <<= 12; if (BX_CIRRUS_THIS s.memsize <= offset) { limit = 0; BX_ERROR(("bank offset %08x is invalid",offset)); } else { limit = BX_CIRRUS_THIS s.memsize - offset; } if (!BX_CIRRUS_THIS banking_is_dual() && (bank_index != 0)) { if (limit > 0x8000) { offset += 0x8000; limit -= 0x8000; } else { limit = 0; } } if (limit > 0) { BX_CIRRUS_THIS bank_base[bank_index] = offset; BX_CIRRUS_THIS bank_limit[bank_index] = limit; } else { BX_CIRRUS_THIS bank_base[bank_index] = 0; BX_CIRRUS_THIS bank_limit[bank_index] = 0; } } Bit8u bx_svga_cirrus_c::svga_read_crtc(Bit32u address, unsigned index) { switch (index) { case 0x00: // VGA case 0x01: // VGA case 0x02: // VGA case 0x03: // VGA case 0x04: // VGA case 0x05: // VGA case 0x06: // VGA case 0x07: // VGA case 0x08: // VGA case 0x09: // VGA case 0x0a: // VGA case 0x0b: // VGA case 0x0c: // VGA case 0x0d: // VGA case 0x0e: // VGA case 0x0f: // VGA case 0x10: // VGA case 0x11: // VGA case 0x12: // VGA case 0x13: // VGA case 0x14: // VGA case 0x15: // VGA case 0x16: // VGA case 0x17: // VGA case 0x18: // VGA break; case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x22: case 0x24: case 0x25: case 0x27: break; case 0x26: return (BX_CIRRUS_THIS s.attribute_ctrl.address & 0x3f); default: BX_DEBUG(("CRTC index 0x%02x is unknown(read)", index)); break; } if (index <= VGA_CRTC_MAX) { return VGA_READ(address,1); } if (index <= CIRRUS_CRTC_MAX) { return BX_CIRRUS_THIS crtc.reg[index]; } return 0xff; } void bx_svga_cirrus_c::svga_write_crtc(Bit32u address, unsigned index, Bit8u value) { BX_DEBUG(("crtc: index 0x%02x write 0x%02x", index, (unsigned)value)); bx_bool update_pitch = 0; switch (index) { case 0x00: // VGA case 0x02: // VGA case 0x03: // VGA case 0x04: // VGA case 0x05: // VGA case 0x06: // VGA case 0x08: // VGA case 0x0a: // VGA case 0x0b: // VGA case 0x0e: // VGA case 0x0f: // VGA case 0x10: // VGA case 0x11: // VGA case 0x14: // VGA case 0x15: // VGA case 0x16: // VGA case 0x17: // VGA case 0x18: // VGA break; case 0x01: // VGA case 0x07: // VGA case 0x09: // VGA case 0x0c: // VGA (display offset 0x00ff00) case 0x0d: // VGA (display offset 0x0000ff) case 0x12: // VGA case 0x1A: // 0x01: interlaced video mode case 0x1D: // 0x80: offset 0x080000 (>=CLGD5434) BX_CIRRUS_THIS svga_needs_update_mode = 1; break; case 0x13: // VGA case 0x1B: // 0x01: offset 0x010000, 0x0c: offset 0x060000 update_pitch = 1; break; case 0x19: case 0x1C: break; default: BX_DEBUG(("CRTC index 0x%02x is unknown(write 0x%02x)", index, (unsigned)value)); return; } if (index <= CIRRUS_CRTC_MAX) { BX_CIRRUS_THIS crtc.reg[index] = value; } if (index <= VGA_CRTC_MAX) { VGA_WRITE(address,value,1); } if (update_pitch) { BX_CIRRUS_THIS svga_pitch = (BX_CIRRUS_THIS crtc.reg[0x13] << 3) | ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x10) << 7); BX_CIRRUS_THIS svga_needs_update_mode = 1; } } Bit8u bx_svga_cirrus_c::svga_read_sequencer(Bit32u address, unsigned index) { switch (index) { case 0x00: // VGA case 0x01: // VGA case 0x02: // VGA case 0x03: // VGA case 0x04: // VGA break; case 0x6: // cirrus unlock extensions case 0x7: // cirrus extended sequencer mode case 0xf: // cirrus dram control case 0x12: // graphics cursor attribute case 0x13: // graphics cursor pattern address offset case 0x17: // configuration readback & extended control break; case 0x10: // cursor xpos << 5 (index & 0x3f) case 0x30: case 0x50: case 0x70: case 0x90: case 0xb0: case 0xd0: case 0xf0: return BX_CIRRUS_THIS sequencer.reg[0x10]; case 0x11: // cursor ypos << 5 (index & 0x3f) case 0x31: case 0x51: case 0x71: case 0x91: case 0xb1: case 0xd1: case 0xf1: return BX_CIRRUS_THIS sequencer.reg[0x11]; default: BX_DEBUG(("sequencer index 0x%02x is unknown(read)", index)); break; } if (index <= VGA_SEQENCER_MAX) { return VGA_READ(address,1); } if (index <= CIRRUS_SEQENCER_MAX) { return BX_CIRRUS_THIS sequencer.reg[index]; } return 0xff; } void bx_svga_cirrus_c::svga_write_sequencer(Bit32u address, unsigned index, Bit8u value) { BX_DEBUG(("sequencer: index 0x%02x write 0x%02x", index, (unsigned)value)); bx_bool update_cursor = 0; Bit16u x, y, size; x = BX_CIRRUS_THIS hw_cursor.x; y = BX_CIRRUS_THIS hw_cursor.y; size = BX_CIRRUS_THIS hw_cursor.size; switch (index) { case 0x00: // VGA case 0x02: // VGA case 0x03: // VGA break; case 0x01: // VGA case 0x04: // VGA BX_CIRRUS_THIS svga_needs_update_mode = 1; break; case 0x6: // cirrus unlock extensions value &= 0x17; if (value == 0x12) { BX_CIRRUS_THIS svga_unlock_special = 1; BX_CIRRUS_THIS sequencer.reg[0x6] = 0x12; } else { #if BX_SUPPORT_PCI BX_CIRRUS_THIS svga_unlock_special = 0; #else if (!BX_CIRRUS_THIS pci_enabled) { BX_CIRRUS_THIS svga_unlock_special = 0; } #endif BX_CIRRUS_THIS sequencer.reg[0x6] = 0x0f; } return; case 0x7: // cirrus extended sequencer mode if (value != BX_CIRRUS_THIS sequencer.reg[0x7]) { BX_CIRRUS_THIS svga_needs_update_mode = 1; } break; case 0x08: case 0x09: case 0x0a: // cirrus scratch reg 1 case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x1b: case 0x1c: case 0x1d: case 0x1e: break; case 0x0f: return; case 0x10: // cursor xpos << 5 (index & 0x3f) case 0x30: case 0x50: case 0x70: case 0x90: case 0xb0: case 0xd0: case 0xf0: BX_CIRRUS_THIS sequencer.reg[0x10] = value; x = BX_CIRRUS_THIS hw_cursor.x; BX_CIRRUS_THIS hw_cursor.x = (value << 3) | (index >> 5); update_cursor = 1; break; case 0x11: // cursor ypos << 5 (index & 0x3f) case 0x31: case 0x51: case 0x71: case 0x91: case 0xb1: case 0xd1: case 0xf1: BX_CIRRUS_THIS sequencer.reg[0x11] = value; y = BX_CIRRUS_THIS hw_cursor.y; BX_CIRRUS_THIS hw_cursor.y = (value << 3) | (index >> 5); update_cursor = 1; break; case 0x12: size = BX_CIRRUS_THIS hw_cursor.size; if (value & CIRRUS_CURSOR_SHOW) { if (value & CIRRUS_CURSOR_LARGE) { BX_CIRRUS_THIS hw_cursor.size = 64; } else { BX_CIRRUS_THIS hw_cursor.size = 32; } } else { BX_CIRRUS_THIS hw_cursor.size = 0; } update_cursor = 1; break; case 0x13: update_cursor = 1; break; case 0x17: value = (BX_CIRRUS_THIS sequencer.reg[0x17] & 0x38) | (value & 0xc7); break; default: BX_DEBUG(("sequencer index 0x%02x is unknown(write 0x%02x)", index, (unsigned)value)); break; } if (update_cursor) { BX_CIRRUS_THIS redraw_area(x, y, size, size); BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS hw_cursor.x, BX_CIRRUS_THIS hw_cursor.y, BX_CIRRUS_THIS hw_cursor.size, BX_CIRRUS_THIS hw_cursor.size); } if (index <= CIRRUS_SEQENCER_MAX) { BX_CIRRUS_THIS sequencer.reg[index] = value; } if (index <= VGA_SEQENCER_MAX) { VGA_WRITE(address,value,1); } } Bit8u bx_svga_cirrus_c::svga_read_control(Bit32u address, unsigned index) { switch (index) { case 0x00: // VGA return BX_CIRRUS_THIS control.shadow_reg0; case 0x01: // VGA return BX_CIRRUS_THIS control.shadow_reg1; case 0x05: // VGA return BX_CIRRUS_THIS control.reg[index]; case 0x02: // VGA case 0x03: // VGA case 0x04: // VGA case 0x06: // VGA case 0x07: // VGA case 0x08: // VGA break; case 0x09: // bank offset #0 case 0x0A: // bank offset #1 case 0x0B: break; case 0x10: // BGCOLOR 0x0000ff00 case 0x11: // FGCOLOR 0x0000ff00 case 0x12: // BGCOLOR 0x00ff0000 case 0x13: // FGCOLOR 0x00ff0000 case 0x14: // BGCOLOR 0xff000000 case 0x15: // FGCOLOR 0xff000000 break; case 0x20: // BLT WIDTH 0x0000ff case 0x21: // BLT WIDTH 0x001f00 case 0x22: // BLT HEIGHT 0x0000ff case 0x23: // BLT HEIGHT 0x001f00 case 0x24: // BLT DEST PITCH 0x0000ff case 0x25: // BLT DEST PITCH 0x001f00 case 0x26: // BLT SRC PITCH 0x0000ff case 0x27: // BLT SRC PITCH 0x001f00 case 0x28: // BLT DEST ADDR 0x0000ff case 0x29: // BLT DEST ADDR 0x00ff00 case 0x2a: // BLT DEST ADDR 0x3f0000 case 0x2c: // BLT SRC ADDR 0x0000ff case 0x2d: // BLT SRC ADDR 0x00ff00 case 0x2e: // BLT SRC ADDR 0x3f0000 case 0x2f: // BLT WRITE MASK case 0x30: // BLT MODE case 0x31: // BLT STATUS case 0x32: // RASTER OP case 0x33: // BLT MODE EXTENSION case 0x34: // BLT TRANSPARENT COLOR 0x00ff case 0x35: // BLT TRANSPARENT COLOR 0xff00 case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00 break; default: BX_DEBUG(("control index 0x%02x is unknown(read)", index)); break; } if (index <= VGA_CONTROL_MAX) { return VGA_READ(address,1); } if (index <= CIRRUS_CONTROL_MAX) { return BX_CIRRUS_THIS control.reg[index]; } return 0xff; } void bx_svga_cirrus_c::svga_write_control(Bit32u address, unsigned index, Bit8u value) { Bit8u old_value = BX_CIRRUS_THIS control.reg[index]; BX_DEBUG(("control: index 0x%02x write 0x%02x", index, (unsigned)value)); switch (index) { case 0x00: // VGA BX_CIRRUS_THIS control.shadow_reg0 = value; break; case 0x01: // VGA BX_CIRRUS_THIS control.shadow_reg1 = value; break; case 0x02: // VGA case 0x03: // VGA case 0x04: // VGA case 0x07: // VGA case 0x08: // VGA break; case 0x05: // VGA case 0x06: // VGA BX_CIRRUS_THIS svga_needs_update_mode = 1; break; case 0x09: // bank offset #0 case 0x0A: // bank offset #1 case 0x0B: BX_CIRRUS_THIS control.reg[index] = value; update_bank_ptr(0); update_bank_ptr(1); break; case 0x10: // BGCOLOR 0x0000ff00 case 0x11: // FGCOLOR 0x0000ff00 case 0x12: // BGCOLOR 0x00ff0000 case 0x13: // FGCOLOR 0x00ff0000 case 0x14: // BGCOLOR 0xff000000 case 0x15: // FGCOLOR 0xff000000 break; case 0x20: // BLT WIDTH 0x0000ff break; case 0x21: // BLT WIDTH 0x001f00 value &= 0x1f; break; case 0x22: // BLT HEIGHT 0x0000ff break; case 0x23: // BLT HEIGHT 0x001f00 value &= 0x1f; break; case 0x24: // BLT DEST PITCH 0x0000ff break; case 0x25: // BLT DEST PITCH 0x001f00 value &= 0x1f; break; case 0x26: // BLT SRC PITCH 0x0000ff break; case 0x27: // BLT SRC PITCH 0x001f00 value &= 0x1f; break; case 0x28: // BLT DEST ADDR 0x0000ff break; case 0x29: // BLT DEST ADDR 0x00ff00 break; case 0x2a: // BLT DEST ADDR 0x3f0000 BX_CIRRUS_THIS control.reg[index] = value & 0x3f; if (BX_CIRRUS_THIS control.reg[0x31] & CIRRUS_BLT_AUTOSTART) { svga_bitblt(); } return; case 0x2b: // BLT DEST ADDR (unused bits) break; case 0x2c: // BLT SRC ADDR 0x0000ff break; case 0x2d: // BLT SRC ADDR 0x00ff00 break; case 0x2e: // BLT SRC ADDR 0x3f0000 value &= 0x3f; break; case 0x2f: // BLT WRITE MASK if (((value ^ old_value) & 0x60) && (value & 0x60)) { BX_ERROR(("BLT WRITE MASK support is not complete (value = 0x%02x)", value)); } break; case 0x30: // BLT MODE break; case 0x31: // BLT STATUS/START BX_CIRRUS_THIS control.reg[0x31] = value; if (((old_value & CIRRUS_BLT_RESET) != 0) && ((value & CIRRUS_BLT_RESET) == 0)) { svga_reset_bitblt(); } else if (((old_value & CIRRUS_BLT_START) == 0) && ((value & CIRRUS_BLT_START) != 0)) { BX_CIRRUS_THIS control.reg[0x31] |= CIRRUS_BLT_BUSY; svga_bitblt(); } return; case 0x32: // RASTER OP break; case 0x33: // BLT MODE EXTENSION #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { if (((value ^ old_value) & 0x18) && (value & 0x18)) { BX_ERROR(("BLT MODE EXTENSION support is not complete (value = 0x%02x)", value & 0x18)); } } else #endif { BX_DEBUG(("BLT MODE EXTENSION not available")); return; } break; case 0x34: // BLT TRANSPARENT COLOR 0x00ff case 0x35: // BLT TRANSPARENT COLOR 0xff00 case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00 default: BX_DEBUG(("control index 0x%02x is unknown (write 0x%02x)", index, (unsigned)value)); break; } if (index <= CIRRUS_CONTROL_MAX) { BX_CIRRUS_THIS control.reg[index] = value; } if (index <= VGA_CONTROL_MAX) { VGA_WRITE(address,value,1); } } Bit8u bx_svga_cirrus_c::svga_mmio_vga_read(Bit32u address) { Bit8u value = 0xff; BX_DEBUG(("MMIO vga read - address 0x%04x, value 0x%02x",address,value)); #if BX_USE_CIRRUS_SMF value = (Bit8u)svga_read_handler(theSvga,0x3c0+address,1); #else // BX_USE_CIRRUS_SMF value = (Bit8u)svga_read(0x3c0+address,1); #endif // BX_USE_CIRRUS_SMF return value; } void bx_svga_cirrus_c::svga_mmio_vga_write(Bit32u address,Bit8u value) { BX_DEBUG(("MMIO vga write - address 0x%04x, value 0x%02x",address,value)); #if BX_USE_CIRRUS_SMF svga_write_handler(theSvga,0x3c0+address,value,1); #else // BX_USE_CIRRUS_SMF svga_write(0x3c0+address,value,1); #endif // BX_USE_CIRRUS_SMF } Bit8u bx_svga_cirrus_c::svga_mmio_blt_read(Bit32u address) { Bit8u value = 0xff; switch (address) { case (CLGD543x_MMIO_BLTBGCOLOR+0): value = BX_CIRRUS_THIS control.shadow_reg0; break; case (CLGD543x_MMIO_BLTBGCOLOR+1): value = svga_read_control(0x3cf,0x10); break; case (CLGD543x_MMIO_BLTBGCOLOR+2): value = svga_read_control(0x3cf,0x12); break; case (CLGD543x_MMIO_BLTBGCOLOR+3): value = svga_read_control(0x3cf,0x14); break; case (CLGD543x_MMIO_BLTFGCOLOR+0): value = BX_CIRRUS_THIS control.shadow_reg1; break; case (CLGD543x_MMIO_BLTFGCOLOR+1): value = svga_read_control(0x3cf,0x11); break; case (CLGD543x_MMIO_BLTFGCOLOR+2): value = svga_read_control(0x3cf,0x13); break; case (CLGD543x_MMIO_BLTFGCOLOR+3): value = svga_read_control(0x3cf,0x15); break; case (CLGD543x_MMIO_BLTWIDTH+0): value = svga_read_control(0x3cf,0x20); break; case (CLGD543x_MMIO_BLTWIDTH+1): value = svga_read_control(0x3cf,0x21); break; case (CLGD543x_MMIO_BLTHEIGHT+0): value = svga_read_control(0x3cf,0x22); break; case (CLGD543x_MMIO_BLTHEIGHT+1): value = svga_read_control(0x3cf,0x23); break; case (CLGD543x_MMIO_BLTDESTPITCH+0): value = svga_read_control(0x3cf,0x24); break; case (CLGD543x_MMIO_BLTDESTPITCH+1): value = svga_read_control(0x3cf,0x25); break; case (CLGD543x_MMIO_BLTSRCPITCH+0): value = svga_read_control(0x3cf,0x26); break; case (CLGD543x_MMIO_BLTSRCPITCH+1): value = svga_read_control(0x3cf,0x27); break; case (CLGD543x_MMIO_BLTDESTADDR+0): value = svga_read_control(0x3cf,0x28); break; case (CLGD543x_MMIO_BLTDESTADDR+1): value = svga_read_control(0x3cf,0x29); break; case (CLGD543x_MMIO_BLTDESTADDR+2): value = svga_read_control(0x3cf,0x2a); break; case (CLGD543x_MMIO_BLTDESTADDR+3): value = svga_read_control(0x3cf,0x2b); break; case (CLGD543x_MMIO_BLTSRCADDR+0): value = svga_read_control(0x3cf,0x2c); break; case (CLGD543x_MMIO_BLTSRCADDR+1): value = svga_read_control(0x3cf,0x2d); break; case (CLGD543x_MMIO_BLTSRCADDR+2): value = svga_read_control(0x3cf,0x2e); break; case CLGD543x_MMIO_BLTWRITEMASK: value = svga_read_control(0x3cf,0x2f); break; case CLGD543x_MMIO_BLTMODE: value = svga_read_control(0x3cf,0x30); break; case CLGD543x_MMIO_BLTROP: value = svga_read_control(0x3cf,0x32); break; case CLGD543x_MMIO_BLTMODEEXT: value = svga_read_control(0x3cf,0x33); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+0): value = svga_read_control(0x3cf,0x34); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+1): value = svga_read_control(0x3cf,0x35); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+2): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+3): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+0): value = svga_read_control(0x3cf,0x38); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+1): value = svga_read_control(0x3cf,0x39); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+2): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+3): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK")); break; case CLGD543x_MMIO_BLTSTATUS: value = svga_read_control(0x3cf,0x31); break; default: BX_ERROR(("MMIO blt read - address 0x%04x",address)); break; } BX_DEBUG(("MMIO blt read - address 0x%04x, value 0x%02x",address,value)); return value; } void bx_svga_cirrus_c::svga_mmio_blt_write(Bit32u address,Bit8u value) { BX_DEBUG(("MMIO blt write - address 0x%04x, value 0x%02x",address,value)); switch (address) { case (CLGD543x_MMIO_BLTBGCOLOR+0): BX_CIRRUS_THIS control.shadow_reg0 = value; break; case (CLGD543x_MMIO_BLTBGCOLOR+1): svga_write_control(0x3cf,0x10,value); break; case (CLGD543x_MMIO_BLTBGCOLOR+2): svga_write_control(0x3cf,0x12,value); break; case (CLGD543x_MMIO_BLTBGCOLOR+3): svga_write_control(0x3cf,0x14,value); break; case (CLGD543x_MMIO_BLTFGCOLOR+0): BX_CIRRUS_THIS control.shadow_reg1 = value; break; case (CLGD543x_MMIO_BLTFGCOLOR+1): svga_write_control(0x3cf,0x11,value); break; case (CLGD543x_MMIO_BLTFGCOLOR+2): svga_write_control(0x3cf,0x13,value); break; case (CLGD543x_MMIO_BLTFGCOLOR+3): svga_write_control(0x3cf,0x15,value); break; case (CLGD543x_MMIO_BLTWIDTH+0): svga_write_control(0x3cf,0x20,value); break; case (CLGD543x_MMIO_BLTWIDTH+1): svga_write_control(0x3cf,0x21,value); break; case (CLGD543x_MMIO_BLTHEIGHT+0): svga_write_control(0x3cf,0x22,value); break; case (CLGD543x_MMIO_BLTHEIGHT+1): svga_write_control(0x3cf,0x23,value); break; case (CLGD543x_MMIO_BLTDESTPITCH+0): svga_write_control(0x3cf,0x24,value); break; case (CLGD543x_MMIO_BLTDESTPITCH+1): svga_write_control(0x3cf,0x25,value); break; case (CLGD543x_MMIO_BLTSRCPITCH+0): svga_write_control(0x3cf,0x26,value); break; case (CLGD543x_MMIO_BLTSRCPITCH+1): svga_write_control(0x3cf,0x27,value); break; case (CLGD543x_MMIO_BLTDESTADDR+0): svga_write_control(0x3cf,0x28,value); break; case (CLGD543x_MMIO_BLTDESTADDR+1): svga_write_control(0x3cf,0x29,value); break; case (CLGD543x_MMIO_BLTDESTADDR+2): svga_write_control(0x3cf,0x2a,value); break; case (CLGD543x_MMIO_BLTDESTADDR+3): svga_write_control(0x3cf,0x2b,value); break; case (CLGD543x_MMIO_BLTSRCADDR+0): svga_write_control(0x3cf,0x2c,value); break; case (CLGD543x_MMIO_BLTSRCADDR+1): svga_write_control(0x3cf,0x2d,value); break; case (CLGD543x_MMIO_BLTSRCADDR+2): svga_write_control(0x3cf,0x2e,value); break; case CLGD543x_MMIO_BLTWRITEMASK: svga_write_control(0x3cf,0x2f,value); break; case CLGD543x_MMIO_BLTMODE: svga_write_control(0x3cf,0x30,value); break; case CLGD543x_MMIO_BLTMODE+1: // unused ??? - ignored for now break; case CLGD543x_MMIO_BLTROP: svga_write_control(0x3cf,0x32,value); break; case CLGD543x_MMIO_BLTMODEEXT: svga_write_control(0x3cf,0x33,value); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+0): svga_write_control(0x3cf,0x34,value); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+1): svga_write_control(0x3cf,0x35,value); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+2): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+3): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+0): svga_write_control(0x3cf,0x38,value); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+1): svga_write_control(0x3cf,0x39,value); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+2): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+3): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK")); break; case CLGD543x_MMIO_BLTSTATUS: svga_write_control(0x3cf,0x31,value); break; default: BX_ERROR(("MMIO blt write - address 0x%04x, value 0x%02x",address,value)); break; } } ///////////////////////////////////////////////////////////////////////// // // PCI support // ///////////////////////////////////////////////////////////////////////// #if BX_SUPPORT_PCI void bx_svga_cirrus_c::svga_init_pcihandlers(void) { Bit8u devfunc = 0x00; DEV_register_pci_handlers(BX_CIRRUS_THIS_PTR, &devfunc, "cirrus", "SVGA Cirrus PCI"); // initialize readonly registers BX_CIRRUS_THIS init_pci_conf(PCI_VENDOR_CIRRUS, PCI_DEVICE_CLGD5446, 0x00, (PCI_CLASS_BASE_DISPLAY << 16) | (PCI_CLASS_SUB_VGA << 8), PCI_CLASS_HEADERTYPE_00h); BX_CIRRUS_THIS pci_conf[0x04] = (PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS); WriteHostDWordToLittleEndian( &BX_CIRRUS_THIS pci_conf[0x10], (PCI_MAP_MEM | PCI_MAP_MEMFLAGS_32BIT | PCI_MAP_MEMFLAGS_CACHEABLE)); WriteHostDWordToLittleEndian( &BX_CIRRUS_THIS pci_conf[0x14], (PCI_MAP_MEM | PCI_MAP_MEMFLAGS_32BIT)); BX_CIRRUS_THIS pci_base_address[0] = 0; BX_CIRRUS_THIS pci_base_address[1] = 0; BX_CIRRUS_THIS pci_rom_address = 0; BX_CIRRUS_THIS load_pci_rom(SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr()); } Bit32u bx_svga_cirrus_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u ret = 0; for (unsigned i = 0; i < io_len; i++) { ret |= (Bit32u)(BX_CIRRUS_THIS pci_conf[address + i]) << (i*8); } BX_DEBUG(("pci_read: address 0x%02x, io_len 0x%02x, value 0x%x", (unsigned)address, (unsigned)io_len, (unsigned)ret)); return ret; } void bx_svga_cirrus_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len) { unsigned i; unsigned write_addr; Bit8u new_value, old_value; bx_bool baseaddr0_change = 0; bx_bool baseaddr1_change = 0; bx_bool romaddr_change = 0; BX_DEBUG(("pci_write: address 0x%02x, io_len 0x%02x, value 0x%x", (unsigned)address, (unsigned)io_len, (unsigned)value)); if ((address > 0x17) && (address < 0x30)) return; if (address == 0x30) { value = value & 0xfffffc01; romaddr_change = 1; } for (i = 0; i < io_len; i++) { write_addr = address + i; old_value = BX_CIRRUS_THIS pci_conf[write_addr]; new_value = (Bit8u)(value & 0xff); switch (write_addr) { case 0x04: // command bit0-7 new_value &= PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS; new_value |= old_value & ~(PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS); break; case 0x05: // command bit8-15 new_value = old_value; break; case 0x06: // status bit0-7 new_value = old_value & (~new_value); break; case 0x07: // status bit8-15 new_value = old_value & (~new_value); break; case 0x10: // base address #0 new_value = (new_value & 0xf0) | (old_value & 0x0f); case 0x11: case 0x12: case 0x13: baseaddr0_change |= (old_value != new_value); break; case 0x14: // base address #1 new_value = (new_value & 0xf0) | (old_value & 0x0f); case 0x15: case 0x16: case 0x17: baseaddr1_change |= (old_value != new_value); break; // read-only. case 0x00: case 0x01: // vendor case 0x02: case 0x03: // device case 0x08: // revision case 0x09: case 0x0a: case 0x0b: // class case 0x0e: // header type case 0x0f: // built-in self test(unimplemented) new_value = old_value; break; default: break; } BX_CIRRUS_THIS pci_conf[write_addr] = new_value; value >>= 8; } if (baseaddr0_change) { if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_base_address[0], &BX_CIRRUS_THIS pci_conf[0x10], 0x2000000)) { BX_INFO(("new pci_memaddr: 0x%04x", BX_CIRRUS_THIS pci_base_address[0])); } } if (baseaddr1_change) { if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_base_address[1], &BX_CIRRUS_THIS pci_conf[0x14], CIRRUS_PNPMMIO_SIZE)) { BX_INFO(("new pci_mmioaddr = 0x%08x", BX_CIRRUS_THIS pci_base_address[1])); } } if (romaddr_change) { if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_rom_address, &BX_CIRRUS_THIS pci_conf[0x30], BX_CIRRUS_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_CIRRUS_THIS pci_rom_address)); } } } #endif // BX_SUPPORT_PCI ///////////////////////////////////////////////////////////////////////// // // Bitblt. // ///////////////////////////////////////////////////////////////////////// void bx_svga_cirrus_c::svga_reset_bitblt(void) { BX_CIRRUS_THIS control.reg[0x31] &= ~(CIRRUS_BLT_START|CIRRUS_BLT_BUSY|CIRRUS_BLT_FIFOUSED); BX_CIRRUS_THIS bitblt.rop_handler = NULL; BX_CIRRUS_THIS bitblt.src = NULL; BX_CIRRUS_THIS bitblt.dst = NULL; BX_CIRRUS_THIS bitblt.memsrc_ptr = NULL; BX_CIRRUS_THIS bitblt.memsrc_endptr = NULL; BX_CIRRUS_THIS bitblt.memsrc_needed = 0; BX_CIRRUS_THIS bitblt.memdst_ptr = NULL; BX_CIRRUS_THIS bitblt.memdst_endptr = NULL; BX_CIRRUS_THIS bitblt.memdst_needed = 0; } void bx_svga_cirrus_c::svga_bitblt() { Bit16u tmp16; Bit32u tmp32; Bit32u dstaddr; Bit32u srcaddr; Bit32u offset; ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x20],tmp16); BX_CIRRUS_THIS bitblt.bltwidth = ((int)tmp16 & (int)0x1fff) + 1; ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x22],tmp16); BX_CIRRUS_THIS bitblt.bltheight = ((int)tmp16 & (int)0x07ff) + 1; ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x24],tmp16); BX_CIRRUS_THIS bitblt.dstpitch = (int)tmp16 & (int)0x1fff; ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x26],tmp16); BX_CIRRUS_THIS bitblt.srcpitch = (int)tmp16 & (int)0x1fff; ReadHostDWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x28],tmp32); dstaddr = tmp32 & BX_CIRRUS_THIS memsize_mask; ReadHostDWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x2c],tmp32); srcaddr = tmp32 & BX_CIRRUS_THIS memsize_mask; BX_CIRRUS_THIS bitblt.srcaddr = srcaddr; BX_CIRRUS_THIS bitblt.bltmode = BX_CIRRUS_THIS control.reg[0x30]; BX_CIRRUS_THIS bitblt.bltmodeext = BX_CIRRUS_THIS control.reg[0x33]; BX_CIRRUS_THIS bitblt.bltrop = BX_CIRRUS_THIS control.reg[0x32]; offset = dstaddr - (BX_CIRRUS_THIS disp_ptr - BX_CIRRUS_THIS s.memory); BX_CIRRUS_THIS redraw.x = (offset % BX_CIRRUS_THIS bitblt.dstpitch) / (BX_CIRRUS_THIS svga_bpp >> 3); BX_CIRRUS_THIS redraw.y = offset / BX_CIRRUS_THIS bitblt.dstpitch; BX_CIRRUS_THIS redraw.w = BX_CIRRUS_THIS bitblt.bltwidth / (BX_CIRRUS_THIS svga_bpp >> 3); BX_CIRRUS_THIS redraw.h = BX_CIRRUS_THIS bitblt.bltheight; BX_DEBUG(("BLT: src:0x%08x,dst 0x%08x,block %ux%u,mode 0x%02x,ROP 0x%02x", (unsigned)srcaddr,(unsigned)dstaddr, (unsigned)BX_CIRRUS_THIS bitblt.bltwidth,(unsigned)BX_CIRRUS_THIS bitblt.bltheight, (unsigned)BX_CIRRUS_THIS bitblt.bltmode,(unsigned)BX_CIRRUS_THIS bitblt.bltrop)); BX_DEBUG(("BLT: srcpitch:0x%08x,dstpitch 0x%08x,modeext 0x%02x,writemask 0x%02x", (unsigned)BX_CIRRUS_THIS bitblt.srcpitch, (unsigned)BX_CIRRUS_THIS bitblt.dstpitch, (unsigned)BX_CIRRUS_THIS bitblt.bltmodeext, BX_CIRRUS_THIS control.reg[0x2f])); switch (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { case CIRRUS_BLTMODE_PIXELWIDTH8: BX_CIRRUS_THIS bitblt.pixelwidth = 1; break; case CIRRUS_BLTMODE_PIXELWIDTH16: BX_CIRRUS_THIS bitblt.pixelwidth = 2; break; case CIRRUS_BLTMODE_PIXELWIDTH24: BX_CIRRUS_THIS bitblt.pixelwidth = 3; break; case CIRRUS_BLTMODE_PIXELWIDTH32: BX_CIRRUS_THIS bitblt.pixelwidth = 4; break; default: BX_PANIC(("unknown pixel width")); goto ignoreblt; } BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK; if ((BX_CIRRUS_THIS bitblt.bltmode & (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_MEMSYSDEST)) == (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_MEMSYSDEST)) { BX_ERROR(("BLT: memory-to-memory copy is requested, ROP %02x", (unsigned)BX_CIRRUS_THIS bitblt.bltrop)); goto ignoreblt; } if ((BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_SOLIDFILL) && (BX_CIRRUS_THIS bitblt.bltmode & (CIRRUS_BLTMODE_MEMSYSDEST | CIRRUS_BLTMODE_TRANSPARENTCOMP | CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) == (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) { BX_CIRRUS_THIS bitblt.rop_handler = svga_get_fwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop); BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS s.memory + dstaddr; svga_solidfill(); } else { if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_BACKWARDS) { BX_CIRRUS_THIS bitblt.dstpitch = -BX_CIRRUS_THIS bitblt.dstpitch; BX_CIRRUS_THIS bitblt.srcpitch = -BX_CIRRUS_THIS bitblt.srcpitch; BX_CIRRUS_THIS bitblt.rop_handler = svga_get_bkwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop); BX_CIRRUS_THIS redraw.x -= BX_CIRRUS_THIS redraw.w; BX_CIRRUS_THIS redraw.y -= BX_CIRRUS_THIS redraw.h; } else { BX_CIRRUS_THIS bitblt.rop_handler = svga_get_fwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop); } BX_DEBUG(("BLT redraw: x = %d, y = %d, w = %d, h = %d", BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y, BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h)); // setup bitblt engine. if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_MEMSYSSRC) { svga_setup_bitblt_cputovideo(dstaddr,srcaddr); } else if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_MEMSYSDEST) { svga_setup_bitblt_videotocpu(dstaddr,srcaddr); } else { svga_setup_bitblt_videotovideo(dstaddr,srcaddr); } return; } ignoreblt: svga_reset_bitblt(); } void bx_svga_cirrus_c::svga_setup_bitblt_cputovideo(Bit32u dstaddr,Bit32u srcaddr) { Bit16u w; BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_MEMSYSSRC; BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS s.memory + dstaddr; BX_CIRRUS_THIS bitblt.src = NULL; BX_CIRRUS_THIS bitblt.memsrc_ptr = &BX_CIRRUS_THIS bitblt.memsrc[0]; BX_CIRRUS_THIS bitblt.memsrc_endptr = &BX_CIRRUS_THIS bitblt.memsrc[0]; if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) { if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) { BX_CIRRUS_THIS bitblt.srcpitch = 8; } else { BX_CIRRUS_THIS bitblt.srcpitch = 8 * 8 * BX_CIRRUS_THIS bitblt.pixelwidth; } BX_CIRRUS_THIS bitblt.memsrc_needed = BX_CIRRUS_THIS bitblt.srcpitch; BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_memsrc_static; } else { if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) { w = BX_CIRRUS_THIS bitblt.bltwidth / BX_CIRRUS_THIS bitblt.pixelwidth; if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) { BX_CIRRUS_THIS bitblt.srcpitch = (w + 31) >> 5; } else { BX_CIRRUS_THIS bitblt.srcpitch = (w + 7) >> 3; } if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_colorexpand_transp_memsrc_static; } else { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_memsrc_static; } } else { BX_CIRRUS_THIS bitblt.srcpitch = (BX_CIRRUS_THIS bitblt.bltwidth + 3) & (~3); BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_memsrc_static; } BX_CIRRUS_THIS bitblt.memsrc_needed = BX_CIRRUS_THIS bitblt.srcpitch * BX_CIRRUS_THIS bitblt.bltheight; } BX_CIRRUS_THIS bitblt.memsrc_endptr += BX_CIRRUS_THIS bitblt.srcpitch; } void bx_svga_cirrus_c::svga_setup_bitblt_videotocpu(Bit32u dstaddr,Bit32u srcaddr) { BX_ERROR(("BLT: MEMSYSDEST is not implemented")); BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_MEMSYSDEST; #if 0 BX_CIRRUS_THIS bitblt.dst = NULL; BX_CIRRUS_THIS bitblt.src = BX_CIRRUS_THIS s.memory + srcaddr; BX_CIRRUS_THIS bitblt.memdst_ptr = &BX_CIRRUS_THIS bitblt.memdst[0]; BX_CIRRUS_THIS bitblt.memdst_endptr = &BX_CIRRUS_THIS bitblt.memdst[0]; BX_CIRRUS_THIS bitblt.memdst_needed = BX_CIRRUS_THIS bitblt.bltwidth * BX_CIRRUS_THIS bitblt.bltheight; BX_CIRRUS_THIS bitblt.memdst_needed = (BX_CIRRUS_THIS bitblt.memdst_needed + 3) & (~3); if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_memdst_static; } else { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_memdst_static; } #endif } void bx_svga_cirrus_c::svga_setup_bitblt_videotovideo(Bit32u dstaddr,Bit32u srcaddr) { BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS s.memory + dstaddr; if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_static; BX_CIRRUS_THIS bitblt.src = BX_CIRRUS_THIS s.memory + (srcaddr & ~0x07); } else { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_static; BX_CIRRUS_THIS bitblt.src = BX_CIRRUS_THIS s.memory + srcaddr; } (*BX_CIRRUS_THIS bitblt.bitblt_ptr)(); svga_reset_bitblt(); BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y, BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h); } void bx_svga_cirrus_c::svga_colorexpand(Bit8u *dst,const Bit8u *src,int count,int pixelwidth) { BX_DEBUG(("svga_cirrus: COLOR EXPAND")); switch (pixelwidth) { case 1: svga_colorexpand_8(dst,src,count); break; case 2: svga_colorexpand_16(dst,src,count); break; case 3: svga_colorexpand_24(dst,src,count); break; case 4: svga_colorexpand_32(dst,src,count); break; default: BX_PANIC(("COLOREXPAND: unknown pixelwidth %u",(unsigned)pixelwidth)); break; } } #if !BX_USE_CIRRUS_SMF void bx_svga_cirrus_c::svga_colorexpand_8_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count) { ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_8(dst,src,count); } void bx_svga_cirrus_c::svga_colorexpand_16_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count) { ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_16(dst,src,count); } void bx_svga_cirrus_c::svga_colorexpand_24_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count) { ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_24(dst,src,count); } void bx_svga_cirrus_c::svga_colorexpand_32_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count) { ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_32(dst,src,count); } #endif // BX_USE_CIRRUS_SMF void bx_svga_cirrus_c::svga_colorexpand_8(Bit8u *dst,const Bit8u *src,int count) { Bit8u colors[2]; unsigned bits; unsigned bitmask; colors[0] = BX_CIRRUS_THIS control.shadow_reg0; colors[1] = BX_CIRRUS_THIS control.shadow_reg1; bitmask = 0x80; bits = *src++; for (int x = 0; x < count; x++) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *src++; } *dst++ = colors[!!(bits & bitmask)]; bitmask >>= 1; } } void bx_svga_cirrus_c::svga_colorexpand_16(Bit8u *dst,const Bit8u *src,int count) { Bit8u colors[2][2]; unsigned bits; unsigned bitmask; unsigned index; colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0; colors[0][1] = BX_CIRRUS_THIS control.reg[0x10]; colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1; colors[1][1] = BX_CIRRUS_THIS control.reg[0x11]; bitmask = 0x80; bits = *src++; for (int x = 0; x < count; x++) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *src++; } index = !!(bits & bitmask); *dst++ = colors[index][0]; *dst++ = colors[index][1]; bitmask >>= 1; } } void bx_svga_cirrus_c::svga_colorexpand_24(Bit8u *dst,const Bit8u *src,int count) { Bit8u colors[2][3]; unsigned bits; unsigned bitmask; unsigned index; colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0; colors[0][1] = BX_CIRRUS_THIS control.reg[0x10]; colors[0][2] = BX_CIRRUS_THIS control.reg[0x12]; colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1; colors[1][1] = BX_CIRRUS_THIS control.reg[0x11]; colors[1][2] = BX_CIRRUS_THIS control.reg[0x13]; bitmask = 0x80; bits = *src++; for (int x = 0; x < count; x++) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *src++; } index = !!(bits & bitmask); *dst++ = colors[index][0]; *dst++ = colors[index][1]; *dst++ = colors[index][2]; bitmask >>= 1; } } void bx_svga_cirrus_c::svga_colorexpand_32(Bit8u *dst,const Bit8u *src,int count) { Bit8u colors[2][4]; unsigned bits; unsigned bitmask; unsigned index; colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0; colors[0][1] = BX_CIRRUS_THIS control.reg[0x10]; colors[0][2] = BX_CIRRUS_THIS control.reg[0x12]; colors[0][3] = BX_CIRRUS_THIS control.reg[0x14]; colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1; colors[1][1] = BX_CIRRUS_THIS control.reg[0x11]; colors[1][2] = BX_CIRRUS_THIS control.reg[0x13]; colors[1][3] = BX_CIRRUS_THIS control.reg[0x15]; bitmask = 0x80; bits = *src++; for (int x = 0; x < count; x++) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *src++; } index = !!(bits & bitmask); *dst++ = colors[index][0]; *dst++ = colors[index][1]; *dst++ = colors[index][2]; *dst++ = colors[index][3]; bitmask >>= 1; } } #if !BX_USE_CIRRUS_SMF void bx_svga_cirrus_c::svga_patterncopy_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_patterncopy(); } void bx_svga_cirrus_c::svga_simplebitblt_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_simplebitblt(); } void bx_svga_cirrus_c::svga_solidfill_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_solidfill(); } void bx_svga_cirrus_c::svga_patterncopy_memsrc_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_patterncopy_memsrc(); } void bx_svga_cirrus_c::svga_simplebitblt_memsrc_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_simplebitblt_memsrc(); } void bx_svga_cirrus_c::svga_colorexpand_transp_memsrc_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_transp_memsrc(); } #endif // !BX_USE_CIRRUS_SMF void bx_svga_cirrus_c::svga_patterncopy() { Bit8u color[4]; Bit8u work_colorexp[256]; Bit8u *src, *dst; Bit8u *dstc, *srcc, *src2; int x, y, pattern_x, pattern_y, srcskipleft; int patternbytes = 8 * BX_CIRRUS_THIS bitblt.pixelwidth; int pattern_pitch = patternbytes; int bltbytes = BX_CIRRUS_THIS bitblt.bltwidth; unsigned bits, bits_xor, bitmask; if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) { pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f; srcskipleft = pattern_x / 3; } else { srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07; pattern_x = srcskipleft * BX_CIRRUS_THIS bitblt.pixelwidth; } if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) { if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { color[0] = BX_CIRRUS_THIS control.shadow_reg1; color[1] = BX_CIRRUS_THIS control.reg[0x11]; color[2] = BX_CIRRUS_THIS control.reg[0x13]; color[3] = BX_CIRRUS_THIS control.reg[0x15]; if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { bits_xor = 0xff; } else { bits_xor = 0x00; } pattern_y = BX_CIRRUS_THIS bitblt.srcaddr & 0x07; for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) { dst = BX_CIRRUS_THIS bitblt.dst + pattern_x; bitmask = 0x80 >> srcskipleft; bits = BX_CIRRUS_THIS bitblt.src[pattern_y] ^ bits_xor; for (x = pattern_x; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = BX_CIRRUS_THIS bitblt.src[pattern_y] ^ bits_xor; } if (bits & bitmask) { (*BX_CIRRUS_THIS bitblt.rop_handler)( dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1); } dst += BX_CIRRUS_THIS bitblt.pixelwidth; bitmask >>= 1; } pattern_y = (pattern_y + 1) & 7; BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch; } return; } else { svga_colorexpand(work_colorexp,BX_CIRRUS_THIS bitblt.src,8*8,BX_CIRRUS_THIS bitblt.pixelwidth); BX_CIRRUS_THIS bitblt.src = work_colorexp; BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_COLOREXPAND; } } else { if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) { pattern_pitch = 32; } } if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_PATTERNCOPY) { BX_ERROR(("PATTERNCOPY: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode)); return; } BX_DEBUG(("svga_cirrus: PATTERN COPY")); dst = BX_CIRRUS_THIS bitblt.dst; pattern_y = BX_CIRRUS_THIS bitblt.srcaddr & 0x07; src = (Bit8u *)BX_CIRRUS_THIS bitblt.src; for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) { srcc = src + pattern_y * pattern_pitch; dstc = dst + pattern_x; for (x = pattern_x; x < bltbytes; x += BX_CIRRUS_THIS bitblt.pixelwidth) { src2 = srcc + (x % patternbytes); (*BX_CIRRUS_THIS bitblt.rop_handler)( dstc, src2, 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1); dstc += BX_CIRRUS_THIS bitblt.pixelwidth; } pattern_y = (pattern_y + 1) & 7; dst += BX_CIRRUS_THIS bitblt.dstpitch; } } void bx_svga_cirrus_c::svga_simplebitblt() { Bit8u color[4]; Bit8u work_colorexp[2048]; Bit16u w, x, y; Bit8u *dst; unsigned bits, bits_xor, bitmask; int pattern_x, srcskipleft; if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) { pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f; srcskipleft = pattern_x / 3; } else { srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07; pattern_x = srcskipleft * BX_CIRRUS_THIS bitblt.pixelwidth; } if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) { if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { color[0] = BX_CIRRUS_THIS control.shadow_reg1; color[1] = BX_CIRRUS_THIS control.reg[0x11]; color[2] = BX_CIRRUS_THIS control.reg[0x13]; color[3] = BX_CIRRUS_THIS control.reg[0x15]; if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { bits_xor = 0xff; } else { bits_xor = 0x00; } for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) { dst = BX_CIRRUS_THIS bitblt.dst + pattern_x; bitmask = 0x80 >> srcskipleft; bits = *BX_CIRRUS_THIS bitblt.src++ ^ bits_xor; for (x = pattern_x; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *BX_CIRRUS_THIS bitblt.src++ ^ bits_xor; } if (bits & bitmask) { (*BX_CIRRUS_THIS bitblt.rop_handler)( dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1); } dst += BX_CIRRUS_THIS bitblt.pixelwidth; bitmask >>= 1; } BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch; } return; } else { w = BX_CIRRUS_THIS bitblt.bltwidth / BX_CIRRUS_THIS bitblt.pixelwidth; for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) { svga_colorexpand(work_colorexp,BX_CIRRUS_THIS bitblt.src, w, BX_CIRRUS_THIS bitblt.pixelwidth); dst = BX_CIRRUS_THIS bitblt.dst + pattern_x; (*BX_CIRRUS_THIS bitblt.rop_handler)( dst, work_colorexp + pattern_x, 0, 0, BX_CIRRUS_THIS bitblt.bltwidth - pattern_x, 1); BX_CIRRUS_THIS bitblt.src += ((w + 7) >> 3); BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch; } return; } } if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_BACKWARDS) { BX_ERROR(("SIMPLE BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode)); return; } BX_DEBUG(("svga_cirrus: BITBLT")); (*BX_CIRRUS_THIS bitblt.rop_handler)( BX_CIRRUS_THIS bitblt.dst, BX_CIRRUS_THIS bitblt.src, BX_CIRRUS_THIS bitblt.dstpitch, BX_CIRRUS_THIS bitblt.srcpitch, BX_CIRRUS_THIS bitblt.bltwidth, BX_CIRRUS_THIS bitblt.bltheight); } void bx_svga_cirrus_c::svga_solidfill() { Bit8u color[4]; int x, y; Bit8u *dst; BX_DEBUG(("BLT: SOLIDFILL")); color[0] = BX_CIRRUS_THIS control.shadow_reg1; color[1] = BX_CIRRUS_THIS control.reg[0x11]; color[2] = BX_CIRRUS_THIS control.reg[0x13]; color[3] = BX_CIRRUS_THIS control.reg[0x15]; for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) { dst = BX_CIRRUS_THIS bitblt.dst; for (x = 0; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) { (*BX_CIRRUS_THIS bitblt.rop_handler)( dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1); dst += BX_CIRRUS_THIS bitblt.pixelwidth; } BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch; } BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y, BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h); } void bx_svga_cirrus_c::svga_patterncopy_memsrc() { BX_INFO(("svga_patterncopy_memsrc() - not tested")); BX_CIRRUS_THIS bitblt.src = &BX_CIRRUS_THIS bitblt.memsrc[0]; svga_patterncopy(); BX_CIRRUS_THIS bitblt.memsrc_needed = 0; BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y, BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h); } void bx_svga_cirrus_c::svga_simplebitblt_memsrc() { Bit8u *srcptr = &BX_CIRRUS_THIS bitblt.memsrc[0]; Bit8u work_colorexp[2048]; Bit16u w; int pattern_x; BX_DEBUG(("svga_cirrus: BLT, cpu-to-video")); if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) { pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f; } else { pattern_x = (BX_CIRRUS_THIS control.reg[0x2f] & 0x07) * BX_CIRRUS_THIS bitblt.pixelwidth; } if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) { if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_COLOREXPAND) { BX_ERROR(("cpu-to-video BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode)); return; } w = BX_CIRRUS_THIS bitblt.bltwidth / BX_CIRRUS_THIS bitblt.pixelwidth; svga_colorexpand(work_colorexp,srcptr,w,BX_CIRRUS_THIS bitblt.pixelwidth); (*BX_CIRRUS_THIS bitblt.rop_handler)( BX_CIRRUS_THIS bitblt.dst + pattern_x, work_colorexp + pattern_x, 0, 0, BX_CIRRUS_THIS bitblt.bltwidth - pattern_x, 1); } else { if (BX_CIRRUS_THIS bitblt.bltmode != 0) { BX_ERROR(("cpu-to-video BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode)); return; } (*BX_CIRRUS_THIS bitblt.rop_handler)( BX_CIRRUS_THIS bitblt.dst, srcptr, 0, 0, BX_CIRRUS_THIS bitblt.bltwidth, 1); } } void bx_svga_cirrus_c::svga_colorexpand_transp_memsrc() { Bit8u *src = &BX_CIRRUS_THIS bitblt.memsrc[0]; Bit8u color[4]; int x, pattern_x, srcskipleft; Bit8u *dst; unsigned bits, bits_xor, bitmask; BX_DEBUG(("BLT, cpu-to-video, transparent")); if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) { pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f; srcskipleft = pattern_x / 3; } else { srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07; pattern_x = srcskipleft * BX_CIRRUS_THIS bitblt.pixelwidth; } color[0] = BX_CIRRUS_THIS control.shadow_reg1; color[1] = BX_CIRRUS_THIS control.reg[0x11]; color[2] = BX_CIRRUS_THIS control.reg[0x13]; color[3] = BX_CIRRUS_THIS control.reg[0x15]; if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { bits_xor = 0xff; } else { bits_xor = 0x00; } dst = BX_CIRRUS_THIS bitblt.dst + pattern_x; bitmask = 0x80 >> srcskipleft; bits = *src++ ^ bits_xor; for (x = pattern_x; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *src++ ^ bits_xor; } if (bits & bitmask) { (*BX_CIRRUS_THIS bitblt.rop_handler)( dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1); } dst += BX_CIRRUS_THIS bitblt.pixelwidth; bitmask >>= 1; } } bx_bool // 1 if finished, 0 otherwise bx_svga_cirrus_c::svga_asyncbitblt_next() { int count; int avail; if (BX_CIRRUS_THIS bitblt.bitblt_ptr == NULL) { BX_PANIC(("svga_asyncbitblt_next: unexpected call")); goto cleanup; } if (BX_CIRRUS_THIS bitblt.memdst_needed > 0) { BX_CIRRUS_THIS bitblt.memdst_needed -= BX_CIRRUS_THIS bitblt.memdst_ptr - &BX_CIRRUS_THIS bitblt.memdst[0]; avail = BX_MIN(CIRRUS_BLT_CACHESIZE, BX_CIRRUS_THIS bitblt.memdst_needed); BX_CIRRUS_THIS bitblt.memdst_ptr = &BX_CIRRUS_THIS bitblt.memdst[0]; BX_CIRRUS_THIS bitblt.memdst_endptr = &BX_CIRRUS_THIS bitblt.memdst[avail]; if (BX_CIRRUS_THIS bitblt.memsrc_needed <= 0 && BX_CIRRUS_THIS bitblt.memdst_needed <= 0) { goto cleanup; } } (*BX_CIRRUS_THIS bitblt.bitblt_ptr)(); if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) { BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch; BX_CIRRUS_THIS bitblt.memsrc_needed -= BX_CIRRUS_THIS bitblt.srcpitch; if (BX_CIRRUS_THIS bitblt.memsrc_needed <= 0) { BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y, BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h); if (BX_CIRRUS_THIS bitblt.memdst_needed <= 0) { goto cleanup; } } else { count = BX_CIRRUS_THIS bitblt.memsrc_endptr - BX_CIRRUS_THIS bitblt.memsrc_ptr; memmove(&BX_CIRRUS_THIS bitblt.memsrc[0], BX_CIRRUS_THIS bitblt.memsrc_ptr, count); BX_CIRRUS_THIS bitblt.memsrc_ptr = &BX_CIRRUS_THIS bitblt.memsrc[count]; } } return 0; cleanup: svga_reset_bitblt(); return 1; } ///////////////////////////////////////////////////////////////////////// // // Raster operations. // ///////////////////////////////////////////////////////////////////////// #define IMPLEMENT_FORWARD_BITBLT(name,opline) \ static void bitblt_rop_fwd_##name( \ Bit8u *dst,const Bit8u *src, \ int dstpitch,int srcpitch, \ int bltwidth,int bltheight) \ { \ int x,y; \ dstpitch -= bltwidth; \ srcpitch -= bltwidth; \ for (y = 0; y < bltheight; y++) { \ for (x = 0; x < bltwidth; x++) { \ opline; \ dst++; \ src++; \ } \ dst += dstpitch; \ src += srcpitch; \ } \ } #define IMPLEMENT_BACKWARD_BITBLT(name,opline) \ static void bitblt_rop_bkwd_##name( \ Bit8u *dst,const Bit8u *src, \ int dstpitch,int srcpitch, \ int bltwidth,int bltheight) \ { \ int x,y; \ dstpitch += bltwidth; \ srcpitch += bltwidth; \ for (y = 0; y < bltheight; y++) { \ for (x = 0; x < bltwidth; x++) { \ opline; \ dst--; \ src--; \ } \ dst += dstpitch; \ src += srcpitch; \ } \ } IMPLEMENT_FORWARD_BITBLT(0, *dst = 0) IMPLEMENT_FORWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst)) IMPLEMENT_FORWARD_BITBLT(nop, (void)0) IMPLEMENT_FORWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst))) IMPLEMENT_FORWARD_BITBLT(notdst, *dst = ~(*dst)) IMPLEMENT_FORWARD_BITBLT(src, *dst = *src) IMPLEMENT_FORWARD_BITBLT(1, *dst = 0xff) IMPLEMENT_FORWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst)) IMPLEMENT_FORWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst)) IMPLEMENT_FORWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst)) IMPLEMENT_FORWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst))) IMPLEMENT_FORWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst))) IMPLEMENT_FORWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst))) IMPLEMENT_FORWARD_BITBLT(notsrc, *dst = (~(*src))) IMPLEMENT_FORWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst)) IMPLEMENT_FORWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst))) IMPLEMENT_BACKWARD_BITBLT(0, *dst = 0) IMPLEMENT_BACKWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst)) IMPLEMENT_BACKWARD_BITBLT(nop, (void)0) IMPLEMENT_BACKWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst))) IMPLEMENT_BACKWARD_BITBLT(notdst, *dst = ~(*dst)) IMPLEMENT_BACKWARD_BITBLT(src, *dst = *src) IMPLEMENT_BACKWARD_BITBLT(1, *dst = 0xff) IMPLEMENT_BACKWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst)) IMPLEMENT_BACKWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst)) IMPLEMENT_BACKWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst)) IMPLEMENT_BACKWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst))) IMPLEMENT_BACKWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst))) IMPLEMENT_BACKWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst))) IMPLEMENT_BACKWARD_BITBLT(notsrc, *dst = (~(*src))) IMPLEMENT_BACKWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst)) IMPLEMENT_BACKWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst))) bx_cirrus_bitblt_rop_t bx_svga_cirrus_c::svga_get_fwd_rop_handler(Bit8u rop) { bx_cirrus_bitblt_rop_t rop_handler = bitblt_rop_fwd_nop; switch (rop) { case CIRRUS_ROP_0: rop_handler = bitblt_rop_fwd_0; break; case CIRRUS_ROP_SRC_AND_DST: rop_handler = bitblt_rop_fwd_src_and_dst; break; case CIRRUS_ROP_NOP: rop_handler = bitblt_rop_fwd_nop; break; case CIRRUS_ROP_SRC_AND_NOTDST: rop_handler = bitblt_rop_fwd_src_and_notdst; break; case CIRRUS_ROP_NOTDST: rop_handler = bitblt_rop_fwd_notdst; break; case CIRRUS_ROP_SRC: rop_handler = bitblt_rop_fwd_src; break; case CIRRUS_ROP_1: rop_handler = bitblt_rop_fwd_1; break; case CIRRUS_ROP_NOTSRC_AND_DST: rop_handler = bitblt_rop_fwd_notsrc_and_dst; break; case CIRRUS_ROP_SRC_XOR_DST: rop_handler = bitblt_rop_fwd_src_xor_dst; break; case CIRRUS_ROP_SRC_OR_DST: rop_handler = bitblt_rop_fwd_src_or_dst; break; case CIRRUS_ROP_NOTSRC_OR_NOTDST: rop_handler = bitblt_rop_fwd_notsrc_or_notdst; break; case CIRRUS_ROP_SRC_NOTXOR_DST: rop_handler = bitblt_rop_fwd_src_notxor_dst; break; case CIRRUS_ROP_SRC_OR_NOTDST: rop_handler = bitblt_rop_fwd_src_or_notdst; break; case CIRRUS_ROP_NOTSRC: rop_handler = bitblt_rop_fwd_notsrc; break; case CIRRUS_ROP_NOTSRC_OR_DST: rop_handler = bitblt_rop_fwd_notsrc_or_dst; break; case CIRRUS_ROP_NOTSRC_AND_NOTDST: rop_handler = bitblt_rop_fwd_notsrc_and_notdst; break; default: BX_ERROR(("unknown ROP %02x",rop)); break; } return rop_handler; } bx_cirrus_bitblt_rop_t bx_svga_cirrus_c::svga_get_bkwd_rop_handler(Bit8u rop) { bx_cirrus_bitblt_rop_t rop_handler = bitblt_rop_bkwd_nop; switch (rop) { case CIRRUS_ROP_0: rop_handler = bitblt_rop_bkwd_0; break; case CIRRUS_ROP_SRC_AND_DST: rop_handler = bitblt_rop_bkwd_src_and_dst; break; case CIRRUS_ROP_NOP: rop_handler = bitblt_rop_bkwd_nop; break; case CIRRUS_ROP_SRC_AND_NOTDST: rop_handler = bitblt_rop_bkwd_src_and_notdst; break; case CIRRUS_ROP_NOTDST: rop_handler = bitblt_rop_bkwd_notdst; break; case CIRRUS_ROP_SRC: rop_handler = bitblt_rop_bkwd_src; break; case CIRRUS_ROP_1: rop_handler = bitblt_rop_bkwd_1; break; case CIRRUS_ROP_NOTSRC_AND_DST: rop_handler = bitblt_rop_bkwd_notsrc_and_dst; break; case CIRRUS_ROP_SRC_XOR_DST: rop_handler = bitblt_rop_bkwd_src_xor_dst; break; case CIRRUS_ROP_SRC_OR_DST: rop_handler = bitblt_rop_bkwd_src_or_dst; break; case CIRRUS_ROP_NOTSRC_OR_NOTDST: rop_handler = bitblt_rop_bkwd_notsrc_or_notdst; break; case CIRRUS_ROP_SRC_NOTXOR_DST: rop_handler = bitblt_rop_bkwd_src_notxor_dst; break; case CIRRUS_ROP_SRC_OR_NOTDST: rop_handler = bitblt_rop_bkwd_src_or_notdst; break; case CIRRUS_ROP_NOTSRC: rop_handler = bitblt_rop_bkwd_notsrc; break; case CIRRUS_ROP_NOTSRC_OR_DST: rop_handler = bitblt_rop_bkwd_notsrc_or_dst; break; case CIRRUS_ROP_NOTSRC_AND_NOTDST: rop_handler = bitblt_rop_bkwd_notsrc_and_notdst; break; default: BX_ERROR(("unknown ROP %02x",rop)); break; } return rop_handler; } #if BX_DEBUGGER void bx_svga_cirrus_c::debug_dump(int argc, char **argv) { if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_SVGA) { #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { dbg_printf("CL-GD5446 PCI\n\n"); } else #endif { dbg_printf("CL-GD5430 ISA\n\n"); } dbg_printf("current mode: %u x %u x %u\n", BX_CIRRUS_THIS svga_xres, BX_CIRRUS_THIS svga_yres, BX_CIRRUS_THIS svga_dispbpp); } else { bx_vgacore_c::debug_dump(); } if (argc > 0) { dbg_printf("\nAdditional options not supported\n"); } } #endif #endif // BX_SUPPORT_CLGD54XX