- added instructions how to update the online documentation
[bochs-mirror.git] / iodev / svga_cirrus.cc
blobae537180ef342ba74e5beec1ad80ce0c85f1d111
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: svga_cirrus.cc,v 1.45 2008/09/18 20:16:27 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (c) 2004 Makoto Suzuki (suzu)
6 // Volker Ruppert (vruppert)
7 // Robin Kay (komadori)
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 /////////////////////////////////////////////////////////////////////////
25 // limited PCI/ISA CLGD5446 support for Bochs
27 // there are still many unimplemented features:
29 // - destination write mask support is not complete (bit 5..7)
30 // - 1bpp/4bpp modes
31 // - ???
33 // some codes are copied from vga.cc and modified.
34 // some codes are ported from the cirrus emulation in qemu
35 // (http://savannah.nongnu.org/projects/qemu).
37 #define BX_PLUGGABLE
39 #include "iodev.h"
41 #if BX_SUPPORT_CLGD54XX
43 // Only reference the array if the tile numbers are within the bounds
44 // of the array. If out of bounds, do nothing.
45 #define SET_TILE_UPDATED(xtile,ytile,value) \
46 do { \
47 if (((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES)) \
48 BX_CIRRUS_THIS s.vga_tile_updated[(xtile)][(ytile)] = value; \
49 } while (0)
50 // Only reference the array if the tile numbers are within the bounds
51 // of the array. If out of bounds, return 1.
52 #define GET_TILE_UPDATED(xtile,ytile) \
53 ((((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES))? \
54 BX_CIRRUS_THIS s.vga_tile_updated[(xtile)][(ytile)] \
55 : 1)
57 #define LOG_THIS BX_CIRRUS_THIS
59 #if BX_USE_CIRRUS_SMF
60 #define VGA_READ(addr,len) bx_vga_c::read_handler(theSvga,addr,len)
61 #define VGA_WRITE(addr,val,len) bx_vga_c::write_handler(theSvga,addr,val,len)
62 #define SVGA_READ(addr,len) svga_read_handler(theSvga,addr,len)
63 #define SVGA_WRITE(addr,val,len) svga_write_handler(theSvga,addr,val,len)
64 #else
65 #define VGA_READ(addr,len) bx_vga_c::read(addr,len)
66 #define VGA_WRITE(addr,val,len) bx_vga_c::write(addr,val,len)
67 #define SVGA_READ(addr,len) svga_read(addr,len)
68 #define SVGA_WRITE(addr,val,len) svga_write(addr,val,len)
69 #endif // BX_USE_CIRRUS_SMF
71 #define ID_CLGD5428 (0x26<<2)
72 #define ID_CLGD5430 (0x28<<2)
73 #define ID_CLGD5434 (0x2A<<2)
74 #define ID_CLGD5446 (0x2E<<2)
76 // sequencer 0x07
77 #define CIRRUS_SR7_BPP_VGA 0x00
78 #define CIRRUS_SR7_BPP_SVGA 0x01
79 #define CIRRUS_SR7_BPP_MASK 0x0e
80 #define CIRRUS_SR7_BPP_8 0x00
81 #define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02
82 #define CIRRUS_SR7_BPP_24 0x04
83 #define CIRRUS_SR7_BPP_16 0x06
84 #define CIRRUS_SR7_BPP_32 0x08
85 #define CIRRUS_SR7_ISAADDR_MASK 0xe0
87 // sequencer 0x0f
88 #define CIRRUS_MEMSIZE_512k 0x08
89 #define CIRRUS_MEMSIZE_1M 0x10
90 #define CIRRUS_MEMSIZE_2M 0x18
91 #define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled.
93 // sequencer 0x12
94 #define CIRRUS_CURSOR_SHOW 0x01
95 #define CIRRUS_CURSOR_HIDDENPEL 0x02
96 #define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear
98 // sequencer 0x17
99 #define CIRRUS_BUSTYPE_VLBFAST 0x10
100 #define CIRRUS_BUSTYPE_PCI 0x20
101 #define CIRRUS_BUSTYPE_VLBSLOW 0x30
102 #define CIRRUS_BUSTYPE_ISA 0x38
103 #define CIRRUS_MMIO_ENABLE 0x04
104 #define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared.
105 #define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
107 // control 0x0b
108 #define CIRRUS_BANKING_DUAL 0x01
109 #define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k
111 // control 0x30
112 #define CIRRUS_BLTMODE_BACKWARDS 0x01
113 #define CIRRUS_BLTMODE_MEMSYSDEST 0x02
114 #define CIRRUS_BLTMODE_MEMSYSSRC 0x04
115 #define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08
116 #define CIRRUS_BLTMODE_PATTERNCOPY 0x40
117 #define CIRRUS_BLTMODE_COLOREXPAND 0x80
118 #define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30
119 #define CIRRUS_BLTMODE_PIXELWIDTH8 0x00
120 #define CIRRUS_BLTMODE_PIXELWIDTH16 0x10
121 #define CIRRUS_BLTMODE_PIXELWIDTH24 0x20
122 #define CIRRUS_BLTMODE_PIXELWIDTH32 0x30
124 // control 0x31
125 #define CIRRUS_BLT_BUSY 0x01
126 #define CIRRUS_BLT_START 0x02
127 #define CIRRUS_BLT_RESET 0x04
128 #define CIRRUS_BLT_FIFOUSED 0x10
129 #define CIRRUS_BLT_AUTOSTART 0x80
131 // control 0x32
132 #define CIRRUS_ROP_0 0x00
133 #define CIRRUS_ROP_SRC_AND_DST 0x05
134 #define CIRRUS_ROP_NOP 0x06
135 #define CIRRUS_ROP_SRC_AND_NOTDST 0x09
136 #define CIRRUS_ROP_NOTDST 0x0b
137 #define CIRRUS_ROP_SRC 0x0d
138 #define CIRRUS_ROP_1 0x0e
139 #define CIRRUS_ROP_NOTSRC_AND_DST 0x50
140 #define CIRRUS_ROP_SRC_XOR_DST 0x59
141 #define CIRRUS_ROP_SRC_OR_DST 0x6d
142 #define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90
143 #define CIRRUS_ROP_SRC_NOTXOR_DST 0x95
144 #define CIRRUS_ROP_SRC_OR_NOTDST 0xad
145 #define CIRRUS_ROP_NOTSRC 0xd0
146 #define CIRRUS_ROP_NOTSRC_OR_DST 0xd6
147 #define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda
149 // control 0x33
150 #define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04
151 #define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02
152 #define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01
154 #define CLGD543x_MMIO_BLTBGCOLOR 0x00 // dword
155 #define CLGD543x_MMIO_BLTFGCOLOR 0x04 // dword
156 #define CLGD543x_MMIO_BLTWIDTH 0x08 // word
157 #define CLGD543x_MMIO_BLTHEIGHT 0x0a // word
158 #define CLGD543x_MMIO_BLTDESTPITCH 0x0c // word
159 #define CLGD543x_MMIO_BLTSRCPITCH 0x0e // word
160 #define CLGD543x_MMIO_BLTDESTADDR 0x10 // dword
161 #define CLGD543x_MMIO_BLTSRCADDR 0x14 // dword
162 #define CLGD543x_MMIO_BLTWRITEMASK 0x17 // byte
163 #define CLGD543x_MMIO_BLTMODE 0x18 // byte
164 #define CLGD543x_MMIO_BLTROP 0x1a // byte
165 #define CLGD543x_MMIO_BLTMODEEXT 0x1b // byte
166 #define CLGD543x_MMIO_BLTTRANSPARENTCOLOR 0x1c // word?
167 #define CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word?
168 #define CLGD543x_MMIO_BLTSTATUS 0x40 // byte
170 // PCI 0x00: vendor, 0x02: device
171 #define PCI_VENDOR_CIRRUS 0x1013
172 #define PCI_DEVICE_CLGD5430 0x00a0 // CLGD5430 or CLGD5440
173 #define PCI_DEVICE_CLGD5434 0x00a8
174 #define PCI_DEVICE_CLGD5436 0x00ac
175 #define PCI_DEVICE_CLGD5446 0x00b8
176 #define PCI_DEVICE_CLGD5462 0x00d0
177 #define PCI_DEVICE_CLGD5465 0x00d6
178 // PCI 0x04: command(word), 0x06(word): status
179 #define PCI_COMMAND_IOACCESS 0x0001
180 #define PCI_COMMAND_MEMACCESS 0x0002
181 #define PCI_COMMAND_BUSMASTER 0x0004
182 #define PCI_COMMAND_SPECIALCYCLE 0x0008
183 #define PCI_COMMAND_MEMWRITEINVALID 0x0010
184 #define PCI_COMMAND_PALETTESNOOPING 0x0020
185 #define PCI_COMMAND_PARITYDETECTION 0x0040
186 #define PCI_COMMAND_ADDRESSDATASTEPPING 0x0080
187 #define PCI_COMMAND_SERR 0x0100
188 #define PCI_COMMAND_BACKTOBACKTRANS 0x0200
189 // PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
190 #define PCI_CLASS_BASE_DISPLAY 0x03
191 // PCI 0x08, 0x00ff0000
192 #define PCI_CLASS_SUB_VGA 0x00
193 // PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test)
194 #define PCI_CLASS_HEADERTYPE_00h 0x00
195 // 0x10-0x3f (headertype 00h)
196 // PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers
197 // 0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x)
198 #define PCI_MAP_MEM 0x0
199 #define PCI_MAP_IO 0x1
200 #define PCI_MAP_MEM_ADDR_MASK (~0xf)
201 #define PCI_MAP_IO_ADDR_MASK (~0x3)
202 #define PCI_MAP_MEMFLAGS_32BIT 0x0
203 #define PCI_MAP_MEMFLAGS_32BIT_1M 0x1
204 #define PCI_MAP_MEMFLAGS_64BIT 0x4
205 #define PCI_MAP_MEMFLAGS_CACHEABLE 0x8
206 // PCI 0x28: cardbus CIS pointer
207 // PCI 0x2c: subsystem vendor id, 0x2e: subsystem id
208 // PCI 0x30: expansion ROM base address
209 // PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer
210 // PCI 0x38: reserved
211 // PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat
212 // PCI 0x40-0xff: device dependent fields
214 // default PnP memory and memory-mapped I/O sizes
215 #define CIRRUS_PNPMEM_SIZE CIRRUS_VIDEO_MEMORY_BYTES
216 #define CIRRUS_PNPMMIO_SIZE 0x1000
218 #define BX_MAX(a,b) ((a) > (b) ? (a) : (b))
219 #define BX_MIN(a,b) ((a) < (b) ? (a) : (b))
221 static bx_svga_cirrus_c *theSvga = NULL;
223 int libvga_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
225 theSvga = new bx_svga_cirrus_c();
226 libvga_set_smf_pointer(theSvga);
227 bx_devices.pluginVgaDevice = theSvga;
228 BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theSvga, BX_PLUGIN_VGA);
229 return(0); // Success
232 void libvga_LTX_plugin_fini(void)
234 delete theSvga;
237 bx_svga_cirrus_c::bx_svga_cirrus_c() : bx_vga_c ()
239 put("CLVGA");
242 bx_svga_cirrus_c::~bx_svga_cirrus_c()
244 BX_DEBUG(("Exit"));
247 void bx_svga_cirrus_c::init(void)
249 // initialize VGA stuffs.
250 BX_CIRRUS_THIS bx_vga_c::init();
251 if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "cirrus")) {
252 // initialize SVGA stuffs.
253 BX_CIRRUS_THIS bx_vga_c::init_iohandlers(
254 svga_read_handler, svga_write_handler);
255 BX_CIRRUS_THIS bx_vga_c::init_systemtimer(
256 svga_timer_handler, svga_param_handler);
257 #if BX_SUPPORT_PCI
258 BX_CIRRUS_THIS pci_enabled = DEV_is_pci_device("cirrus");
259 #endif
260 BX_CIRRUS_THIS svga_init_members();
261 #if BX_SUPPORT_PCI
262 if (BX_CIRRUS_THIS pci_enabled)
264 BX_CIRRUS_THIS svga_init_pcihandlers();
265 BX_INFO(("CL-GD5446 PCI initialized"));
267 else
268 #endif
270 BX_INFO(("CL-GD5430 ISA initialized"));
272 BX_CIRRUS_THIS extension_init = 1;
273 } else {
274 BX_CIRRUS_THIS sequencer.reg[0x07] = 0x00; // Cirrus extension disabled
275 // initialize VGA read/write handlers and timer
276 BX_CIRRUS_THIS bx_vga_c::init_iohandlers(
277 bx_vga_c::read_handler, bx_vga_c::write_handler);
278 BX_CIRRUS_THIS bx_vga_c::init_systemtimer(
279 bx_vga_c::timer_handler, bx_vga_c::vga_param_handler);
283 void bx_svga_cirrus_c::svga_init_members()
285 unsigned i;
287 // clear all registers.
288 BX_CIRRUS_THIS sequencer.index = CIRRUS_SEQENCER_MAX + 1;
289 for (i = 0; i <= CIRRUS_SEQENCER_MAX; i++)
290 BX_CIRRUS_THIS sequencer.reg[i] = 0x00;
291 BX_CIRRUS_THIS control.index = CIRRUS_CONTROL_MAX + 1;
292 for (i = 0; i <= CIRRUS_CONTROL_MAX; i++)
293 BX_CIRRUS_THIS control.reg[i] = 0x00;
294 BX_CIRRUS_THIS control.shadow_reg0 = 0x00;
295 BX_CIRRUS_THIS control.shadow_reg1 = 0x00;
296 BX_CIRRUS_THIS crtc.index = CIRRUS_CRTC_MAX + 1;
297 for (i = 0; i <= CIRRUS_CRTC_MAX; i++)
298 BX_CIRRUS_THIS crtc.reg[i] = 0x00;
299 BX_CIRRUS_THIS hidden_dac.lockindex = 0;
300 BX_CIRRUS_THIS hidden_dac.data = 0x00;
302 BX_CIRRUS_THIS svga_unlock_special = false;
303 BX_CIRRUS_THIS svga_needs_update_tile = true;
304 BX_CIRRUS_THIS svga_needs_update_dispentire = true;
305 BX_CIRRUS_THIS svga_needs_update_mode = false;
307 BX_CIRRUS_THIS svga_xres = 640;
308 BX_CIRRUS_THIS svga_yres = 480;
309 BX_CIRRUS_THIS svga_bpp = 8;
310 BX_CIRRUS_THIS svga_pitch = 640;
311 BX_CIRRUS_THIS bank_base[0] = 0;
312 BX_CIRRUS_THIS bank_base[1] = 0;
313 BX_CIRRUS_THIS bank_limit[0] = 0;
314 BX_CIRRUS_THIS bank_limit[1] = 0;
316 svga_reset_bitblt();
318 BX_CIRRUS_THIS hw_cursor.x = 0;
319 BX_CIRRUS_THIS hw_cursor.y = 0;
320 BX_CIRRUS_THIS hw_cursor.size = 0;
322 // memory allocation.
323 if (BX_CIRRUS_THIS s.memory == NULL)
324 BX_CIRRUS_THIS s.memory = new Bit8u[CIRRUS_VIDEO_MEMORY_BYTES];
326 // set some registers.
328 BX_CIRRUS_THIS sequencer.reg[0x06] = 0x0f;
329 BX_CIRRUS_THIS sequencer.reg[0x07] = 0x00; // 0xf0:linearbase(0x00 if disabled)
330 #if BX_SUPPORT_PCI
331 if (BX_CIRRUS_THIS pci_enabled) {
332 BX_CIRRUS_THIS crtc.reg[0x27] = ID_CLGD5446;
333 BX_CIRRUS_THIS sequencer.reg[0x1F] = 0x2d; // MemClock
334 BX_CIRRUS_THIS control.reg[0x18] = 0x0f;
335 BX_CIRRUS_THIS sequencer.reg[0x0F] = 0x98;
336 BX_CIRRUS_THIS sequencer.reg[0x17] = CIRRUS_BUSTYPE_PCI;
337 BX_CIRRUS_THIS sequencer.reg[0x15] = 0x04; // memory size 4MB
338 BX_CIRRUS_THIS s.memsize = (4 << 20);
339 } else
340 #endif
342 BX_CIRRUS_THIS crtc.reg[0x27] = ID_CLGD5430;
343 BX_CIRRUS_THIS sequencer.reg[0x1F] = 0x22; // MemClock
344 BX_CIRRUS_THIS sequencer.reg[0x0F] = CIRRUS_MEMSIZE_2M;
345 BX_CIRRUS_THIS sequencer.reg[0x17] = CIRRUS_BUSTYPE_ISA;
346 BX_CIRRUS_THIS sequencer.reg[0x15] = 0x03; // memory size 2MB
347 BX_CIRRUS_THIS s.memsize = (2 << 20);
350 BX_CIRRUS_THIS hidden_dac.lockindex = 5;
351 BX_CIRRUS_THIS hidden_dac.data = 0;
353 memset(BX_CIRRUS_THIS s.memory, 0xff, CIRRUS_VIDEO_MEMORY_BYTES);
354 BX_CIRRUS_THIS disp_ptr = BX_CIRRUS_THIS s.memory;
357 void bx_svga_cirrus_c::reset(unsigned type)
359 // reset VGA stuffs.
360 BX_CIRRUS_THIS bx_vga_c::reset(type);
362 if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "cirrus")) {
363 // reset SVGA stuffs.
364 BX_CIRRUS_THIS svga_init_members();
368 void bx_svga_cirrus_c::register_state(void)
370 unsigned i;
371 char name[6];
372 bx_list_c *reg;
374 if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "cirrus")) {
375 bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "svga_cirrus", "Cirrus SVGA State", 18);
376 bx_list_c *crtc = new bx_list_c(list, "crtc", 2);
377 new bx_shadow_num_c(crtc, "index", &BX_CIRRUS_THIS crtc.index, BASE_HEX);
378 reg = new bx_list_c(crtc, "reg", CIRRUS_CRTC_MAX+1);
379 for (i=0; i<=CIRRUS_CRTC_MAX; i++) {
380 sprintf(name, "0x%02x", i);
381 new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS crtc.reg[i], BASE_HEX);
383 bx_list_c *sequ = new bx_list_c(list, "sequencer", 2);
384 new bx_shadow_num_c(sequ, "index", &BX_CIRRUS_THIS sequencer.index, BASE_HEX);
385 reg = new bx_list_c(sequ, "reg", CIRRUS_SEQENCER_MAX+1);
386 for (i=0; i<=CIRRUS_SEQENCER_MAX; i++) {
387 sprintf(name, "0x%02x", i);
388 new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS sequencer.reg[i], BASE_HEX);
390 bx_list_c *ctrl = new bx_list_c(list, "control", 4);
391 new bx_shadow_num_c(ctrl, "index", &BX_CIRRUS_THIS control.index, BASE_HEX);
392 reg = new bx_list_c(ctrl, "reg", CIRRUS_CONTROL_MAX+1);
393 for (i=0; i<=CIRRUS_CONTROL_MAX; i++) {
394 sprintf(name, "0x%02x", i);
395 new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS control.reg[i], BASE_HEX);
397 new bx_shadow_num_c(ctrl, "shadow_reg0", &BX_CIRRUS_THIS control.shadow_reg0, BASE_HEX);
398 new bx_shadow_num_c(ctrl, "shadow_reg1", &BX_CIRRUS_THIS control.shadow_reg1, BASE_HEX);
399 bx_list_c *hdac = new bx_list_c(list, "hidden_dac", 3);
400 new bx_shadow_num_c(hdac, "lockindex", &BX_CIRRUS_THIS hidden_dac.lockindex, BASE_HEX);
401 new bx_shadow_num_c(hdac, "data", &BX_CIRRUS_THIS hidden_dac.data, BASE_HEX);
402 reg = new bx_list_c(hdac, "palette", 48);
403 for (i=0; i<48; i++) {
404 sprintf(name, "0x%02x", i);
405 new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS hidden_dac.palette[i], BASE_HEX);
407 new bx_shadow_bool_c(list, "svga_unlock_special", &BX_CIRRUS_THIS svga_unlock_special);
408 new bx_shadow_num_c(list, "svga_xres", &BX_CIRRUS_THIS svga_xres);
409 new bx_shadow_num_c(list, "svga_yres", &BX_CIRRUS_THIS svga_yres);
410 new bx_shadow_num_c(list, "svga_pitch", &BX_CIRRUS_THIS svga_pitch);
411 new bx_shadow_num_c(list, "svga_bpp", &BX_CIRRUS_THIS svga_bpp);
412 new bx_shadow_num_c(list, "svga_dispbpp", &BX_CIRRUS_THIS svga_dispbpp);
413 new bx_shadow_num_c(list, "bank_base0", &BX_CIRRUS_THIS bank_base[0], BASE_HEX);
414 new bx_shadow_num_c(list, "bank_base1", &BX_CIRRUS_THIS bank_base[1], BASE_HEX);
415 new bx_shadow_num_c(list, "bank_limit0", &BX_CIRRUS_THIS bank_limit[0], BASE_HEX);
416 new bx_shadow_num_c(list, "bank_limit1", &BX_CIRRUS_THIS bank_limit[1], BASE_HEX);
417 bx_list_c *cursor = new bx_list_c(list, "hw_cursor", 3);
418 new bx_shadow_num_c(cursor, "x", &BX_CIRRUS_THIS hw_cursor.x, BASE_HEX);
419 new bx_shadow_num_c(cursor, "y", &BX_CIRRUS_THIS hw_cursor.y, BASE_HEX);
420 new bx_shadow_num_c(cursor, "size", &BX_CIRRUS_THIS hw_cursor.size, BASE_HEX);
421 #if BX_SUPPORT_PCI
422 if (BX_CIRRUS_THIS pci_enabled) {
423 register_pci_state(list, BX_CIRRUS_THIS pci_conf);
425 #endif
427 bx_vga_c::register_state();
430 void bx_svga_cirrus_c::after_restore_state(void)
432 if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) {
433 BX_CIRRUS_THIS bx_vga_c::after_restore_state();
434 } else {
435 #if BX_SUPPORT_PCI
436 if (BX_CIRRUS_THIS pci_enabled) {
437 if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler,
438 cirrus_mem_write_handler,
439 &BX_CIRRUS_THIS pci_memaddr,
440 &BX_CIRRUS_THIS pci_conf[0x10],
441 0x2000000)) {
442 BX_INFO(("new pci_memaddr: 0x%04x", BX_CIRRUS_THIS pci_memaddr));
444 if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler,
445 cirrus_mem_write_handler,
446 &BX_CIRRUS_THIS pci_mmioaddr,
447 &BX_CIRRUS_THIS pci_conf[0x14],
448 CIRRUS_PNPMMIO_SIZE)) {
449 BX_INFO(("new pci_mmioaddr = 0x%08x", BX_CIRRUS_THIS pci_mmioaddr));
452 #endif
453 for (unsigned i=0; i<256; i++) {
454 bx_gui->palette_change(i, BX_CIRRUS_THIS s.pel.data[i].red<<2,
455 BX_CIRRUS_THIS s.pel.data[i].green<<2,
456 BX_CIRRUS_THIS s.pel.data[i].blue<<2);
458 BX_CIRRUS_THIS svga_needs_update_mode = 1;
459 BX_CIRRUS_THIS svga_update();
463 void bx_svga_cirrus_c::redraw_area(unsigned x0, unsigned y0,
464 unsigned width, unsigned height)
466 unsigned xti, yti, xt0, xt1, yt0, yt1;
468 if ((width == 0) || (height == 0)) {
469 return;
472 if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) {
473 BX_CIRRUS_THIS bx_vga_c::redraw_area(x0,y0,width,height);
474 return;
477 if (BX_CIRRUS_THIS svga_needs_update_mode) {
478 return;
481 BX_CIRRUS_THIS svga_needs_update_tile = true;
483 xt0 = x0 / X_TILESIZE;
484 yt0 = y0 / Y_TILESIZE;
485 if (x0 < BX_CIRRUS_THIS svga_xres) {
486 xt1 = (x0 + width - 1) / X_TILESIZE;
487 } else {
488 xt1 = (BX_CIRRUS_THIS svga_xres - 1) / X_TILESIZE;
490 if (y0 < BX_CIRRUS_THIS svga_yres) {
491 yt1 = (y0 + height - 1) / Y_TILESIZE;
492 } else {
493 yt1 = (BX_CIRRUS_THIS svga_yres - 1) / Y_TILESIZE;
495 for (yti=yt0; yti<=yt1; yti++) {
496 for (xti=xt0; xti<=xt1; xti++) {
497 SET_TILE_UPDATED (xti, yti, 1);
502 void bx_svga_cirrus_c::mem_write_mode4and5_8bpp(Bit8u mode, Bit32u offset, Bit8u value)
504 Bit8u val = value;
505 Bit8u *dst;
507 dst = BX_CIRRUS_THIS s.memory + offset;
508 for (int x = 0; x < 8; x++) {
509 if (val & 0x80) {
510 *dst = BX_CIRRUS_THIS control.shadow_reg1;
511 } else if (mode == 5) {
512 *dst = BX_CIRRUS_THIS control.shadow_reg0;
514 val <<= 1;
515 dst++;
519 void bx_svga_cirrus_c::mem_write_mode4and5_16bpp(Bit8u mode, Bit32u offset, Bit8u value)
521 Bit8u val = value;
522 Bit8u *dst;
524 dst = BX_CIRRUS_THIS s.memory + offset;
525 for (int x = 0; x < 8; x++) {
526 if (val & 0x80) {
527 *dst = BX_CIRRUS_THIS control.shadow_reg1;
528 *(dst + 1) = BX_CIRRUS_THIS control.reg[0x11];
529 } else if (mode == 5) {
530 *dst = BX_CIRRUS_THIS control.shadow_reg0;
531 *(dst + 1) = BX_CIRRUS_THIS control.reg[0x10];
533 val <<= 1;
534 dst += 2;
538 #if BX_SUPPORT_PCI
539 bx_bool bx_svga_cirrus_c::cirrus_mem_read_handler(bx_phy_address addr, unsigned len,
540 void *data, void *param)
542 Bit8u *data_ptr;
543 #ifdef BX_LITTLE_ENDIAN
544 data_ptr = (Bit8u *) data;
545 #else // BX_BIG_ENDIAN
546 data_ptr = (Bit8u *) data + (len - 1);
547 #endif
548 for (unsigned i = 0; i < len; i++) {
549 *data_ptr = BX_CIRRUS_THIS mem_read(addr);
550 addr++;
551 #ifdef BX_LITTLE_ENDIAN
552 data_ptr++;
553 #else // BX_BIG_ENDIAN
554 data_ptr--;
555 #endif
557 return 1;
559 #endif
561 Bit8u bx_svga_cirrus_c::mem_read(bx_phy_address addr)
563 if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) {
564 return BX_CIRRUS_THIS bx_vga_c::mem_read(addr);
567 #if BX_SUPPORT_PCI
568 if (BX_CIRRUS_THIS pci_enabled) {
569 if ((addr >= BX_CIRRUS_THIS pci_memaddr) &&
570 (addr < (BX_CIRRUS_THIS pci_memaddr + CIRRUS_PNPMEM_SIZE))) {
571 Bit8u *ptr;
573 Bit32u offset = addr & (BX_CIRRUS_THIS s.memsize - 1);
574 if ((offset >= (BX_CIRRUS_THIS s.memsize - 256)) &&
575 ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x44)) {
576 return svga_mmio_blt_read(offset & 0xff);
579 // video-to-cpu BLT
580 if (BX_CIRRUS_THIS bitblt.memdst_needed != 0) {
581 ptr = BX_CIRRUS_THIS bitblt.memdst_ptr;
582 if (ptr != BX_CIRRUS_THIS bitblt.memdst_endptr) {
583 BX_CIRRUS_THIS bitblt.memdst_ptr ++;
584 return *ptr;
586 if (!svga_asyncbitblt_next()) {
587 ptr = BX_CIRRUS_THIS bitblt.memdst_ptr;
588 BX_CIRRUS_THIS bitblt.memdst_ptr ++;
589 return *ptr;
593 ptr = BX_CIRRUS_THIS s.memory;
594 if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) {
595 offset <<= 4;
596 } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) {
597 offset <<= 3;
599 offset &= (BX_CIRRUS_THIS s.memsize - 1);
600 return *(ptr + offset);
601 } else if ((addr >= BX_CIRRUS_THIS pci_mmioaddr) &&
602 (addr < (BX_CIRRUS_THIS pci_mmioaddr + CIRRUS_PNPMMIO_SIZE))) {
604 Bit32u offset = addr & (CIRRUS_PNPMMIO_SIZE - 1);
605 if (offset >= 0x100) {
606 return svga_mmio_blt_read(offset - 0x100);
607 } else {
608 return svga_mmio_vga_read(offset);
612 #endif // BX_SUPPORT_PCI
614 if (addr >= 0xA0000 && addr <= 0xAFFFF)
616 Bit32u bank;
617 Bit32u offset;
618 Bit8u *ptr;
620 // video-to-cpu BLT
621 if (BX_CIRRUS_THIS bitblt.memdst_needed != 0) {
622 ptr = BX_CIRRUS_THIS bitblt.memdst_ptr;
623 if (ptr != BX_CIRRUS_THIS bitblt.memdst_endptr) {
624 BX_CIRRUS_THIS bitblt.memdst_ptr ++;
625 return *ptr;
627 if (!svga_asyncbitblt_next()) {
628 ptr = BX_CIRRUS_THIS bitblt.memdst_ptr;
629 BX_CIRRUS_THIS bitblt.memdst_ptr ++;
630 return *ptr;
634 offset = addr & 0xffff;
635 bank = (offset >> 15);
636 offset &= 0x7fff;
637 if (offset < bank_limit[bank]) {
638 offset += bank_base[bank];
639 if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) {
640 offset <<= 4;
641 } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) {
642 offset <<= 3;
644 offset &= (BX_CIRRUS_THIS s.memsize - 1);
645 return *(BX_CIRRUS_THIS s.memory + offset);
647 else {
648 return 0xff;
651 else if (addr >= 0xB8000 && addr <= 0xB8100) {
652 // memory-mapped I/O.
653 Bit32u offset;
655 offset = addr - 0xb8000;
656 if ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x04)
657 return svga_mmio_blt_read(offset);
659 else {
660 BX_DEBUG(("mem_read 0x%08x",addr));
663 return 0xff;
666 #if BX_SUPPORT_PCI
667 bx_bool bx_svga_cirrus_c::cirrus_mem_write_handler(bx_phy_address addr, unsigned len,
668 void *data, void *param)
670 Bit8u *data_ptr;
671 #ifdef BX_LITTLE_ENDIAN
672 data_ptr = (Bit8u *) data;
673 #else // BX_BIG_ENDIAN
674 data_ptr = (Bit8u *) data + (len - 1);
675 #endif
676 for (unsigned i = 0; i < len; i++) {
677 BX_CIRRUS_THIS mem_write(addr, *data_ptr);
678 addr++;
679 #ifdef BX_LITTLE_ENDIAN
680 data_ptr++;
681 #else // BX_BIG_ENDIAN
682 data_ptr--;
683 #endif
685 return 1;
687 #endif
689 void bx_svga_cirrus_c::mem_write(bx_phy_address addr, Bit8u value)
691 if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) {
692 BX_CIRRUS_THIS bx_vga_c::mem_write(addr,value);
693 return;
696 #if BX_SUPPORT_PCI
697 if (BX_CIRRUS_THIS pci_enabled) {
698 if ((addr >= BX_CIRRUS_THIS pci_memaddr) &&
699 (addr < (BX_CIRRUS_THIS pci_memaddr + CIRRUS_PNPMEM_SIZE))) {
701 Bit32u offset = addr & (BX_CIRRUS_THIS s.memsize - 1);
702 if ((offset >= (BX_CIRRUS_THIS s.memsize - 256)) &&
703 ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x44)) {
704 svga_mmio_blt_write(addr & 0xff, value);
705 return;
708 // cpu-to-video BLT
709 if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) {
710 *(BX_CIRRUS_THIS bitblt.memsrc_ptr)++ = (value);
711 if (BX_CIRRUS_THIS bitblt.memsrc_ptr >= BX_CIRRUS_THIS bitblt.memsrc_endptr) {
712 svga_asyncbitblt_next();
714 return;
717 // BX_DEBUG(("write offset 0x%08x,value 0x%02x",offset,value));
718 if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) {
719 offset <<= 4;
720 } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) {
721 offset <<= 3;
723 offset &= (BX_CIRRUS_THIS s.memsize - 1);
724 Bit8u mode = BX_CIRRUS_THIS control.reg[0x05] & 0x07;
725 if ((mode < 4) || (mode > 5) || ((BX_CIRRUS_THIS control.reg[0x0b] & 0x4) == 0)) {
726 *(BX_CIRRUS_THIS s.memory + offset) = value;
727 } else {
728 if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) != 0x14) {
729 mem_write_mode4and5_8bpp(mode, offset, value);
730 } else {
731 mem_write_mode4and5_16bpp(mode, offset, value);
734 BX_CIRRUS_THIS svga_needs_update_tile = true;
735 SET_TILE_UPDATED(((offset % BX_CIRRUS_THIS svga_pitch) / (BX_CIRRUS_THIS svga_bpp / 8)) / X_TILESIZE,
736 (offset / BX_CIRRUS_THIS svga_pitch) / Y_TILESIZE, 1);
737 return;
738 } else if ((addr >= BX_CIRRUS_THIS pci_mmioaddr) &&
739 (addr < (BX_CIRRUS_THIS pci_mmioaddr + CIRRUS_PNPMMIO_SIZE))) {
740 // memory-mapped I/O.
742 // BX_DEBUG(("write mmio 0x%08x",addr));
743 Bit32u offset = addr & (CIRRUS_PNPMMIO_SIZE - 1);
744 if (offset >= 0x100) {
745 svga_mmio_blt_write(offset - 0x100, value);
746 } else {
747 svga_mmio_vga_write(offset,value);
749 return;
752 #endif // BX_SUPPORT_PCI
754 if (addr >= 0xA0000 && addr <= 0xAFFFF) {
755 Bit32u bank, offset;
756 Bit8u mode;
758 // cpu-to-video BLT
759 if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) {
760 *(BX_CIRRUS_THIS bitblt.memsrc_ptr)++ = (value);
761 if (BX_CIRRUS_THIS bitblt.memsrc_ptr >= BX_CIRRUS_THIS bitblt.memsrc_endptr) {
762 svga_asyncbitblt_next();
764 return;
767 offset = addr & 0xffff;
768 bank = (offset >> 15);
769 offset &= 0x7fff;
770 if (offset < bank_limit[bank]) {
771 offset += bank_base[bank];
772 if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) {
773 offset <<= 4;
774 } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) {
775 offset <<= 3;
777 offset &= (BX_CIRRUS_THIS s.memsize - 1);
778 mode = BX_CIRRUS_THIS control.reg[0x05] & 0x07;
779 if ((mode < 4) || (mode > 5) || ((BX_CIRRUS_THIS control.reg[0x0b] & 0x4) == 0)) {
780 *(BX_CIRRUS_THIS s.memory + offset) = value;
781 } else {
782 if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) != 0x14) {
783 mem_write_mode4and5_8bpp(mode, offset, value);
784 } else {
785 mem_write_mode4and5_16bpp(mode, offset, value);
788 BX_CIRRUS_THIS svga_needs_update_tile = true;
789 SET_TILE_UPDATED(((offset % BX_CIRRUS_THIS svga_pitch) / (BX_CIRRUS_THIS svga_bpp / 8)) / X_TILESIZE,
790 (offset / BX_CIRRUS_THIS svga_pitch) / Y_TILESIZE, 1);
792 } else if (addr >= 0xB8000 && addr < 0xB8100) {
793 // memory-mapped I/O.
794 Bit32u offset;
796 offset = addr - 0xb8000;
797 if ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x04) {
798 svga_mmio_blt_write(offset & 0xff, value);
801 else {
802 BX_DEBUG(("mem_write 0x%08x, value 0x%02x",addr,value));
806 void bx_svga_cirrus_c::get_text_snapshot(Bit8u **text_snapshot,
807 unsigned *txHeight, unsigned *txWidth)
809 BX_CIRRUS_THIS bx_vga_c::get_text_snapshot(text_snapshot,txHeight,txWidth);
812 void bx_svga_cirrus_c::trigger_timer(void *this_ptr)
814 BX_CIRRUS_THIS timer_handler(this_ptr);
817 Bit64s bx_svga_cirrus_c::svga_param_handler(bx_param_c *param, int set, Bit64s val)
819 if (set) {
820 BX_INFO (("Changing timer interval to %d", (Bit32u)val));
821 BX_CIRRUS_THIS svga_timer_handler (theSvga);
822 bx_pc_system.activate_timer (BX_CIRRUS_THIS timer_id, (Bit32u)val, 1);
824 return val;
827 Bit8u bx_svga_cirrus_c::get_actl_palette_idx(Bit8u index)
829 return BX_CIRRUS_THIS bx_vga_c::get_actl_palette_idx(index);
832 Bit32u bx_svga_cirrus_c::svga_read_handler(void *this_ptr, Bit32u address, unsigned io_len)
834 #if !BX_USE_CIRRUS_SMF
835 bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr;
837 return class_ptr->svga_read(address, io_len);
840 Bit32u bx_svga_cirrus_c::svga_read(Bit32u address, unsigned io_len)
842 #else
843 UNUSED(this_ptr);
844 #endif // !BX_USE_CIRRUS_SMF
846 if ((io_len == 2) && ((address & 1) == 0)) {
847 Bit32u value;
848 value = (Bit32u)SVGA_READ(address,1);
849 value |= (Bit32u)SVGA_READ(address+1,1) << 8;
850 return value;
853 if (io_len != 1) {
854 BX_PANIC(("SVGA read: io_len != 1"));
857 switch (address) {
858 case 0x03b4: /* VGA: CRTC Index Register (monochrome emulation modes) */
859 case 0x03d4: /* VGA: CRTC Index Register (color emulation modes) */
860 return BX_CIRRUS_THIS crtc.index;
861 case 0x03b5: /* VGA: CRTC Registers (monochrome emulation modes) */
862 case 0x03d5: /* VGA: CRTC Registers (color emulation modes) */
863 if (BX_CIRRUS_THIS is_unlocked())
864 return BX_CIRRUS_THIS svga_read_crtc(address,BX_CIRRUS_THIS crtc.index);
865 break;
867 case 0x03c4: /* VGA: Sequencer Index Register */
868 if (BX_CIRRUS_THIS is_unlocked()) {
869 Bit32u value = BX_CIRRUS_THIS sequencer.index;
870 if ((value & 0x1e) == 0x10) { /* SR10-F0, SR11-F1 */
871 if (value & 1)
872 value = ((BX_CIRRUS_THIS hw_cursor.y & 7) << 5) | 0x11;
873 else
874 value = ((BX_CIRRUS_THIS hw_cursor.x & 7) << 5) | 0x10;
876 return value;
878 return BX_CIRRUS_THIS sequencer.index;
879 case 0x03c5: /* VGA: Sequencer Registers */
880 if ((BX_CIRRUS_THIS sequencer.index == 0x06) ||
881 (BX_CIRRUS_THIS is_unlocked())) {
882 return BX_CIRRUS_THIS svga_read_sequencer(address,BX_CIRRUS_THIS sequencer.index);
884 break;
886 case 0x03c6: /* Hidden DAC */
887 if (BX_CIRRUS_THIS is_unlocked()) {
888 if ((++BX_CIRRUS_THIS hidden_dac.lockindex) == 5) {
889 BX_CIRRUS_THIS hidden_dac.lockindex = 0;
890 return BX_CIRRUS_THIS hidden_dac.data;
893 break;
894 case 0x03c8: /* PEL write address */
895 BX_CIRRUS_THIS hidden_dac.lockindex = 0;
896 break;
897 case 0x03c9: /* PEL Data Register, hiddem pel colors 00..0F */
898 if (BX_CIRRUS_THIS sequencer.reg[0x12] & CIRRUS_CURSOR_HIDDENPEL) {
899 Bit8u index = (BX_CIRRUS_THIS s.pel.read_data_register & 0x0f) * 3 +
900 BX_CIRRUS_THIS s.pel.read_data_cycle;
901 Bit8u retval = BX_CIRRUS_THIS hidden_dac.palette[index];
902 BX_CIRRUS_THIS s.pel.read_data_cycle ++;
903 if (BX_CIRRUS_THIS s.pel.read_data_cycle >= 3) {
904 BX_CIRRUS_THIS s.pel.read_data_cycle = 0;
905 BX_CIRRUS_THIS s.pel.read_data_register++;
907 return retval;
909 break;
910 case 0x03ce: /* VGA: Graphics Controller Index Register */
911 return BX_CIRRUS_THIS control.index;
912 case 0x03cf: /* VGA: Graphics Controller Registers */
913 if (BX_CIRRUS_THIS is_unlocked())
914 return BX_CIRRUS_THIS svga_read_control(address,BX_CIRRUS_THIS control.index);
915 break;
917 default:
918 break;
921 return VGA_READ(address,io_len);
924 void bx_svga_cirrus_c::svga_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
926 #if !BX_USE_CIRRUS_SMF
927 bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr;
928 class_ptr->svga_write(address, value, io_len);
931 void bx_svga_cirrus_c::svga_write(Bit32u address, Bit32u value, unsigned io_len)
933 #else
934 UNUSED(this_ptr);
935 #endif // !BX_USE_CIRRUS_SMF
937 if ((io_len == 2) && ((address & 1) == 0)) {
938 SVGA_WRITE(address,value & 0xff,1);
939 SVGA_WRITE(address+1,value >> 8,1);
940 return;
943 if (io_len != 1) {
944 BX_PANIC(("SVGA write: io_len != 1"));
947 switch (address) {
948 case 0x03b4: /* VGA: CRTC Index Register (monochrome emulation modes) */
949 case 0x03d4: /* VGA: CRTC Index Register (color emulation modes) */
950 BX_CIRRUS_THIS crtc.index = value & 0x7f;
951 break;
952 case 0x03b5: /* VGA: CRTC Registers (monochrome emulation modes) */
953 case 0x03d5: /* VGA: CRTC Registers (color emulation modes) */
954 if (BX_CIRRUS_THIS is_unlocked()) {
955 BX_CIRRUS_THIS svga_write_crtc(address,BX_CIRRUS_THIS crtc.index,value);
956 return;
958 break;
960 case 0x03c4: /* VGA: Sequencer Index Register */
961 BX_CIRRUS_THIS sequencer.index = value;
962 break;
963 case 0x03c5: /* VGA: Sequencer Registers */
964 if ((BX_CIRRUS_THIS sequencer.index == 0x06) ||
965 (BX_CIRRUS_THIS is_unlocked())) {
966 BX_CIRRUS_THIS svga_write_sequencer(address,BX_CIRRUS_THIS sequencer.index,value);
967 return;
969 break;
970 case 0x03c6: /* Hidden DAC */
971 if (BX_CIRRUS_THIS is_unlocked()) {
972 if (BX_CIRRUS_THIS hidden_dac.lockindex == 4) {
973 BX_CIRRUS_THIS hidden_dac.data = value;
975 BX_CIRRUS_THIS hidden_dac.lockindex = 0;
976 return;
978 break;
979 case 0x03c9: /* PEL Data Register, hidden pel colors 00..0F */
980 BX_CIRRUS_THIS svga_needs_update_dispentire = true;
982 if (BX_CIRRUS_THIS sequencer.reg[0x12] & CIRRUS_CURSOR_HIDDENPEL) {
983 Bit8u index = (BX_CIRRUS_THIS s.pel.write_data_register & 0x0f) * 3 +
984 BX_CIRRUS_THIS s.pel.write_data_cycle;
985 BX_CIRRUS_THIS hidden_dac.palette[index] = value;
986 BX_CIRRUS_THIS s.pel.write_data_cycle ++;
987 if (BX_CIRRUS_THIS s.pel.write_data_cycle >= 3) {
988 BX_CIRRUS_THIS s.pel.write_data_cycle = 0;
989 BX_CIRRUS_THIS s.pel.write_data_register++;
991 return;
993 break;
994 case 0x03ce: /* VGA: Graphics Controller Index Register */
995 BX_CIRRUS_THIS control.index = value;
996 break;
997 case 0x03cf: /* VGA: Graphics Controller Registers */
998 if (BX_CIRRUS_THIS is_unlocked()) {
999 BX_CIRRUS_THIS svga_write_control(address,BX_CIRRUS_THIS control.index,value);
1000 return;
1002 break;
1003 default:
1004 break;
1007 VGA_WRITE(address,value,io_len);
1010 void bx_svga_cirrus_c::svga_timer_handler(void *this_ptr)
1012 #if !BX_USE_CIRRUS_SMF
1013 bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr;
1014 class_ptr->svga_timer();
1017 void bx_svga_cirrus_c::svga_timer(void)
1019 #else // !BX_USE_CIRRUS_SMF
1020 UNUSED(this_ptr);
1021 #endif // !BX_USE_CIRRUS_SMF
1023 BX_CIRRUS_THIS svga_update();
1024 bx_gui->flush();
1027 void bx_svga_cirrus_c::svga_modeupdate(void)
1029 Bit32u iTopOffset, iWidth, iHeight;
1030 Bit8u iBpp, iDispBpp;
1032 iTopOffset = (BX_CIRRUS_THIS crtc.reg[0x0c] << 8)
1033 + BX_CIRRUS_THIS crtc.reg[0x0d]
1034 + ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x01) << 16)
1035 + ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x0c) << 15)
1036 + ((BX_CIRRUS_THIS crtc.reg[0x1d] & 0x80) << 12);
1037 iTopOffset <<= 2;
1039 iHeight = 1 + BX_CIRRUS_THIS crtc.reg[0x12]
1040 + ((BX_CIRRUS_THIS crtc.reg[0x07] & 0x02) << 7)
1041 + ((BX_CIRRUS_THIS crtc.reg[0x07] & 0x40) << 3);
1042 if ((BX_CIRRUS_THIS crtc.reg[0x1a] & 0x01) > 0) {
1043 iHeight <<= 1;
1045 iWidth = (BX_CIRRUS_THIS crtc.reg[0x01] + 1) * 8;
1046 iBpp = 8;
1047 iDispBpp = 4;
1048 if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x1) == CIRRUS_SR7_BPP_SVGA) {
1049 switch (BX_CIRRUS_THIS sequencer.reg[0x07] & CIRRUS_SR7_BPP_MASK) {
1050 case CIRRUS_SR7_BPP_8:
1051 iBpp = 8;
1052 iDispBpp = 8;
1053 break;
1054 case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
1055 case CIRRUS_SR7_BPP_16:
1056 iBpp = 16;
1057 iDispBpp = (BX_CIRRUS_THIS hidden_dac.data & 0x1) ? 16 : 15;
1058 break;
1059 case CIRRUS_SR7_BPP_24:
1060 iBpp = 24;
1061 iDispBpp = 24;
1062 break;
1063 case CIRRUS_SR7_BPP_32:
1064 iBpp = 32;
1065 iDispBpp = 32;
1066 break;
1067 default:
1068 BX_PANIC(("unknown bpp - seqencer.reg[0x07] = %02x",BX_CIRRUS_THIS sequencer.reg[0x07]));
1069 break;
1072 if ((iWidth != BX_CIRRUS_THIS svga_xres) || (iHeight != BX_CIRRUS_THIS svga_yres)
1073 || (iDispBpp != BX_CIRRUS_THIS svga_dispbpp)) {
1074 BX_INFO(("switched to %u x %u x %u", iWidth, iHeight, iDispBpp));
1076 BX_CIRRUS_THIS svga_xres = iWidth;
1077 BX_CIRRUS_THIS svga_yres = iHeight;
1078 BX_CIRRUS_THIS svga_bpp = iBpp;
1079 BX_CIRRUS_THIS svga_dispbpp = iDispBpp;
1080 BX_CIRRUS_THIS disp_ptr = BX_CIRRUS_THIS s.memory + iTopOffset;
1083 void bx_svga_cirrus_c::draw_hardware_cursor(unsigned xc, unsigned yc, bx_svga_tileinfo_t *info)
1085 if (BX_CIRRUS_THIS hw_cursor.size &&
1086 (xc < (unsigned)(BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size)) &&
1087 (xc+X_TILESIZE > BX_CIRRUS_THIS hw_cursor.x) &&
1088 (yc < (unsigned)(BX_CIRRUS_THIS hw_cursor.y+BX_CIRRUS_THIS hw_cursor.size)) &&
1089 (yc+Y_TILESIZE > BX_CIRRUS_THIS hw_cursor.y)) {
1090 int i;
1091 unsigned w, h, pitch, cx, cy, cx0, cy0, cx1, cy1;
1093 Bit8u * tile_ptr, * tile_ptr2;
1094 Bit8u * plane0_ptr, *plane0_ptr2;
1095 Bit8u * plane1_ptr, *plane1_ptr2;
1096 unsigned long fgcol, bgcol;
1097 Bit64u plane0, plane1;
1099 cx0 = BX_CIRRUS_THIS hw_cursor.x > xc ? BX_CIRRUS_THIS hw_cursor.x : xc;
1100 cy0 = BX_CIRRUS_THIS hw_cursor.y > yc ? BX_CIRRUS_THIS hw_cursor.y : yc;
1101 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;
1102 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;
1104 if (info->bpp == 15) info->bpp = 16;
1105 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h) +
1106 info->pitch * (cy0 - yc) + (info->bpp / 8) * (cx0 - xc);
1107 plane0_ptr = BX_CIRRUS_THIS s.memory + BX_CIRRUS_THIS s.memsize - 16384;
1109 switch (BX_CIRRUS_THIS hw_cursor.size) {
1110 case 32:
1111 plane0_ptr += (BX_CIRRUS_THIS sequencer.reg[0x13] & 0x3f) * 256;
1112 plane1_ptr = plane0_ptr + 128;
1113 pitch = 4;
1114 break;
1116 case 64:
1117 plane0_ptr += (BX_CIRRUS_THIS sequencer.reg[0x13] & 0x3c) * 256;
1118 plane1_ptr = plane0_ptr + 8;
1119 pitch = 16;
1120 break;
1122 default:
1123 BX_ERROR(("unsupported hardware cursor size"));
1124 return;
1125 break;
1128 if (!info->is_indexed) {
1129 fgcol = MAKE_COLOUR(
1130 BX_CIRRUS_THIS hidden_dac.palette[45], 6, info->red_shift, info->red_mask,
1131 BX_CIRRUS_THIS hidden_dac.palette[46], 6, info->green_shift, info->green_mask,
1132 BX_CIRRUS_THIS hidden_dac.palette[47], 6, info->blue_shift, info->blue_mask);
1133 bgcol = MAKE_COLOUR(
1134 BX_CIRRUS_THIS hidden_dac.palette[0], 6, info->red_shift, info->red_mask,
1135 BX_CIRRUS_THIS hidden_dac.palette[1], 6, info->green_shift, info->green_mask,
1136 BX_CIRRUS_THIS hidden_dac.palette[2], 6, info->blue_shift, info->blue_mask);
1137 } else {
1138 // FIXME: this is a hack that works in Windows guests
1139 // TODO: compare hidden DAC entries with DAC entries to find nearest match
1140 fgcol = 0xff;
1141 bgcol = 0x00;
1144 plane0_ptr += pitch * (cy0 - BX_CIRRUS_THIS hw_cursor.y);
1145 plane1_ptr += pitch * (cy0 - BX_CIRRUS_THIS hw_cursor.y);
1146 for (cy=cy0; cy<cy1; cy++) {
1147 tile_ptr2 = tile_ptr + (info->bpp/8) * (cx1 - cx0) - 1;
1148 plane0_ptr2 = plane0_ptr;
1149 plane1_ptr2 = plane1_ptr;
1150 plane0 = plane1 = 0;
1151 for (i=0; i<BX_CIRRUS_THIS hw_cursor.size; i+=8) {
1152 plane0 = (plane0 << 8) | *(plane0_ptr2++);
1153 plane1 = (plane1 << 8) | *(plane1_ptr2++);
1155 plane0 >>= BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size - cx1;
1156 plane1 >>= BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size - cx1;
1157 for (cx=cx0; cx<cx1; cx++) {
1158 if (plane0 & 1) {
1159 if (plane1 & 1) {
1160 if (info->is_little_endian) {
1161 for (i=info->bpp-8; i>-8; i-=8) {
1162 *(tile_ptr2--) = (Bit8u)(fgcol >> i);
1165 else {
1166 for (i=0; i<info->bpp; i+=8) {
1167 *(tile_ptr2--) = (Bit8u)(fgcol >> i);
1171 else {
1172 for (i=0; i<info->bpp; i+=8) {
1173 *(tile_ptr2--) ^= 0xff;
1177 else {
1178 if (plane1 & 1) {
1179 if (info->is_little_endian) {
1180 for (i=info->bpp-8; i>-8; i-=8) {
1181 *(tile_ptr2--) = (Bit8u)(bgcol >> i);
1184 else {
1185 for (i=0; i<info->bpp; i+=8) {
1186 *(tile_ptr2--) = (Bit8u)(bgcol >> i);
1190 else {
1191 tile_ptr2 -= (info->bpp/8);
1194 plane0 >>= 1;
1195 plane1 >>= 1;
1197 tile_ptr += info->pitch;
1198 plane0_ptr += pitch;
1199 plane1_ptr += pitch;
1204 void bx_svga_cirrus_c::svga_update(void)
1206 unsigned width, height, pitch;
1208 /* skip screen update when the sequencer is in reset mode or video is disabled */
1209 if (! BX_CIRRUS_THIS s.sequencer.reset1 ||
1210 ! BX_CIRRUS_THIS s.sequencer.reset2 ||
1211 ! BX_CIRRUS_THIS s.attribute_ctrl.video_enabled) {
1212 return;
1215 if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) {
1216 if (BX_CIRRUS_THIS svga_needs_update_mode) {
1217 BX_CIRRUS_THIS s.vga_mem_updated = 1;
1218 BX_CIRRUS_THIS svga_needs_update_mode = false;
1220 BX_CIRRUS_THIS bx_vga_c::update();
1221 return;
1223 else {
1224 if (BX_CIRRUS_THIS svga_needs_update_mode) {
1225 svga_modeupdate();
1229 width = BX_CIRRUS_THIS svga_xres;
1230 height = BX_CIRRUS_THIS svga_yres;
1231 pitch = BX_CIRRUS_THIS svga_pitch;
1233 if (BX_CIRRUS_THIS svga_needs_update_mode) {
1234 width = BX_CIRRUS_THIS svga_xres;
1235 height = BX_CIRRUS_THIS svga_yres;
1236 bx_gui->dimension_update(width, height, 0, 0, BX_CIRRUS_THIS svga_dispbpp);
1237 BX_CIRRUS_THIS s.last_bpp = BX_CIRRUS_THIS svga_dispbpp;
1238 BX_CIRRUS_THIS svga_needs_update_mode = false;
1239 BX_CIRRUS_THIS svga_needs_update_dispentire = true;
1242 if (BX_CIRRUS_THIS svga_needs_update_dispentire) {
1243 BX_CIRRUS_THIS redraw_area(0,0,width,height);
1244 BX_CIRRUS_THIS svga_needs_update_dispentire = false;
1247 if (!BX_CIRRUS_THIS svga_needs_update_tile) {
1248 return;
1250 BX_CIRRUS_THIS svga_needs_update_tile = false;
1252 unsigned xc, yc, xti, yti;
1253 unsigned r, c, w, h;
1254 int i;
1255 Bit8u red, green, blue;
1256 Bit32u colour;
1257 Bit8u * vid_ptr, * vid_ptr2;
1258 Bit8u * tile_ptr, * tile_ptr2;
1259 bx_svga_tileinfo_t info;
1261 if (bx_gui->graphics_tile_info(&info)) {
1262 if (info.is_indexed) {
1263 switch (BX_CIRRUS_THIS svga_dispbpp) {
1264 case 4:
1265 case 15:
1266 case 16:
1267 case 24:
1268 case 32:
1269 BX_ERROR(("current guest pixel format is unsupported on indexed colour host displays, svga_dispbpp=%d",
1270 BX_CIRRUS_THIS svga_dispbpp));
1271 break;
1272 case 8:
1273 for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
1274 for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
1275 if (GET_TILE_UPDATED (xti, yti)) {
1276 vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + xc);
1277 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1278 for (r=0; r<h; r++) {
1279 vid_ptr2 = vid_ptr;
1280 tile_ptr2 = tile_ptr;
1281 for (c=0; c<w; c++) {
1282 colour = 0;
1283 for (i=0; i<(int)BX_CIRRUS_THIS svga_bpp; i+=8) {
1284 colour |= *(vid_ptr2++) << i;
1286 if (info.is_little_endian) {
1287 for (i=0; i<info.bpp; i+=8) {
1288 *(tile_ptr2++) = colour >> i;
1291 else {
1292 for (i=info.bpp-8; i>-8; i-=8) {
1293 *(tile_ptr2++) = colour >> i;
1297 vid_ptr += pitch;
1298 tile_ptr += info.pitch;
1300 draw_hardware_cursor(xc, yc, &info);
1301 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1302 SET_TILE_UPDATED (xti, yti, 0);
1306 break;
1309 else {
1310 switch (BX_CIRRUS_THIS svga_dispbpp) {
1311 case 4:
1312 BX_ERROR(("cannot draw 4bpp SVGA"));
1313 break;
1314 case 8:
1315 for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
1316 for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
1317 if (GET_TILE_UPDATED (xti, yti)) {
1318 vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + xc);
1319 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1320 for (r=0; r<h; r++) {
1321 vid_ptr2 = vid_ptr;
1322 tile_ptr2 = tile_ptr;
1323 for (c=0; c<w; c++) {
1324 colour = *(vid_ptr2++);
1325 colour = MAKE_COLOUR(
1326 BX_CIRRUS_THIS s.pel.data[colour].red, 6, info.red_shift, info.red_mask,
1327 BX_CIRRUS_THIS s.pel.data[colour].green, 6, info.green_shift, info.green_mask,
1328 BX_CIRRUS_THIS s.pel.data[colour].blue, 6, info.blue_shift, info.blue_mask);
1329 if (info.is_little_endian) {
1330 for (i=0; i<info.bpp; i+=8) {
1331 *(tile_ptr2++) = colour >> i;
1334 else {
1335 for (i=info.bpp-8; i>-8; i-=8) {
1336 *(tile_ptr2++) = colour >> i;
1340 vid_ptr += pitch;
1341 tile_ptr += info.pitch;
1343 draw_hardware_cursor(xc, yc, &info);
1344 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1345 SET_TILE_UPDATED (xti, yti, 0);
1349 break;
1350 case 15:
1351 for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
1352 for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
1353 if (GET_TILE_UPDATED (xti, yti)) {
1354 vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + (xc<<1));
1355 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1356 for (r=0; r<h; r++) {
1357 vid_ptr2 = vid_ptr;
1358 tile_ptr2 = tile_ptr;
1359 for (c=0; c<w; c++) {
1360 colour = *(vid_ptr2++);
1361 colour |= *(vid_ptr2++) << 8;
1362 colour = MAKE_COLOUR(
1363 colour & 0x001f, 5, info.blue_shift, info.blue_mask,
1364 colour & 0x03e0, 10, info.green_shift, info.green_mask,
1365 colour & 0x7c00, 15, info.red_shift, info.red_mask);
1366 if (info.is_little_endian) {
1367 for (i=0; i<info.bpp; i+=8) {
1368 *(tile_ptr2++) = colour >> i;
1371 else {
1372 for (i=info.bpp-8; i>-8; i-=8) {
1373 *(tile_ptr2++) = colour >> i;
1377 vid_ptr += pitch;
1378 tile_ptr += info.pitch;
1380 draw_hardware_cursor(xc, yc, &info);
1381 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1382 SET_TILE_UPDATED (xti, yti, 0);
1386 break;
1387 case 16:
1388 for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
1389 for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
1390 if (GET_TILE_UPDATED (xti, yti)) {
1391 vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + (xc<<1));
1392 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1393 for (r=0; r<h; r++) {
1394 vid_ptr2 = vid_ptr;
1395 tile_ptr2 = tile_ptr;
1396 for (c=0; c<w; c++) {
1397 colour = *(vid_ptr2++);
1398 colour |= *(vid_ptr2++) << 8;
1399 colour = MAKE_COLOUR(
1400 colour & 0x001f, 5, info.blue_shift, info.blue_mask,
1401 colour & 0x07e0, 11, info.green_shift, info.green_mask,
1402 colour & 0xf800, 16, info.red_shift, info.red_mask);
1403 if (info.is_little_endian) {
1404 for (i=0; i<info.bpp; i+=8) {
1405 *(tile_ptr2++) = colour >> i;
1408 else {
1409 for (i=info.bpp-8; i>-8; i-=8) {
1410 *(tile_ptr2++) = colour >> i;
1414 vid_ptr += pitch;
1415 tile_ptr += info.pitch;
1417 draw_hardware_cursor(xc, yc, &info);
1418 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1419 SET_TILE_UPDATED (xti, yti, 0);
1423 break;
1424 case 24:
1425 for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
1426 for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
1427 if (GET_TILE_UPDATED (xti, yti)) {
1428 vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + 3*xc);
1429 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1430 for (r=0; r<h; r++) {
1431 vid_ptr2 = vid_ptr;
1432 tile_ptr2 = tile_ptr;
1433 for (c=0; c<w; c++) {
1434 blue = *(vid_ptr2++);
1435 green = *(vid_ptr2++);
1436 red = *(vid_ptr2++);
1437 colour = MAKE_COLOUR(
1438 red, 8, info.red_shift, info.red_mask,
1439 green, 8, info.green_shift, info.green_mask,
1440 blue, 8, info.blue_shift, info.blue_mask);
1441 if (info.is_little_endian) {
1442 for (i=0; i<info.bpp; i+=8) {
1443 *(tile_ptr2++) = colour >> i;
1446 else {
1447 for (i=info.bpp-8; i>-8; i-=8) {
1448 *(tile_ptr2++) = colour >> i;
1452 vid_ptr += pitch;
1453 tile_ptr += info.pitch;
1455 draw_hardware_cursor(xc, yc, &info);
1456 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1457 SET_TILE_UPDATED (xti, yti, 0);
1461 break;
1462 case 32:
1463 for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
1464 for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
1465 if (GET_TILE_UPDATED (xti, yti)) {
1466 vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + (xc<<2));
1467 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
1468 for (r=0; r<h; r++) {
1469 vid_ptr2 = vid_ptr;
1470 tile_ptr2 = tile_ptr;
1471 for (c=0; c<w; c++) {
1472 blue = *(vid_ptr2++);
1473 green = *(vid_ptr2++);
1474 red = *(vid_ptr2++);
1475 vid_ptr2++;
1476 colour = MAKE_COLOUR(
1477 red, 8, info.red_shift, info.red_mask,
1478 green, 8, info.green_shift, info.green_mask,
1479 blue, 8, info.blue_shift, info.blue_mask);
1480 if (info.is_little_endian) {
1481 for (i=0; i<info.bpp; i+=8) {
1482 *(tile_ptr2++) = colour >> i;
1485 else {
1486 for (i=info.bpp-8; i>-8; i-=8) {
1487 *(tile_ptr2++) = colour >> i;
1491 vid_ptr += pitch;
1492 tile_ptr += info.pitch;
1494 draw_hardware_cursor(xc, yc, &info);
1495 bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
1496 SET_TILE_UPDATED (xti, yti, 0);
1500 break;
1504 else {
1505 BX_PANIC(("cannot get svga tile info"));
1509 void bx_svga_cirrus_c::update_bank_ptr(Bit8u bank_index)
1511 unsigned offset;
1512 unsigned limit;
1514 if (BX_CIRRUS_THIS banking_is_dual())
1515 offset = BX_CIRRUS_THIS control.reg[0x09 + bank_index];
1516 else
1517 offset = BX_CIRRUS_THIS control.reg[0x09];
1519 if (BX_CIRRUS_THIS banking_granularity_is_16k())
1520 offset <<= 14;
1521 else
1522 offset <<= 12;
1524 if (BX_CIRRUS_THIS s.memsize <= offset) {
1525 limit = 0;
1526 BX_ERROR(("bank offset %08x is invalid",offset));
1527 } else {
1528 limit = BX_CIRRUS_THIS s.memsize - offset;
1531 if (!BX_CIRRUS_THIS banking_is_dual() && (bank_index != 0)) {
1532 if (limit > 0x8000) {
1533 offset += 0x8000;
1534 limit -= 0x8000;
1535 } else {
1536 limit = 0;
1540 if (limit > 0) {
1541 BX_CIRRUS_THIS bank_base[bank_index] = offset;
1542 BX_CIRRUS_THIS bank_limit[bank_index] = limit;
1543 } else {
1544 BX_CIRRUS_THIS bank_base[bank_index] = 0;
1545 BX_CIRRUS_THIS bank_limit[bank_index] = 0;
1549 Bit8u bx_svga_cirrus_c::svga_read_crtc(Bit32u address, unsigned index)
1551 switch (index) {
1552 case 0x00: // VGA
1553 case 0x01: // VGA
1554 case 0x02: // VGA
1555 case 0x03: // VGA
1556 case 0x04: // VGA
1557 case 0x05: // VGA
1558 case 0x06: // VGA
1559 case 0x07: // VGA
1560 case 0x08: // VGA
1561 case 0x09: // VGA
1562 case 0x0a: // VGA
1563 case 0x0b: // VGA
1564 case 0x0c: // VGA
1565 case 0x0d: // VGA
1566 case 0x0e: // VGA
1567 case 0x0f: // VGA
1568 case 0x10: // VGA
1569 case 0x11: // VGA
1570 case 0x12: // VGA
1571 case 0x13: // VGA
1572 case 0x14: // VGA
1573 case 0x15: // VGA
1574 case 0x16: // VGA
1575 case 0x17: // VGA
1576 case 0x18: // VGA
1577 break;
1578 case 0x19:
1579 case 0x1A:
1580 case 0x1B:
1581 case 0x1C:
1582 case 0x1D:
1583 case 0x22:
1584 case 0x24:
1585 case 0x25:
1586 case 0x27:
1587 break;
1588 case 0x26:
1589 return (BX_CIRRUS_THIS s.attribute_ctrl.address & 0x3f);
1590 default:
1591 BX_DEBUG(("CRTC index 0x%02x is unknown(read)", index));
1592 break;
1595 if (index <= VGA_CRTC_MAX) {
1596 return VGA_READ(address,1);
1599 if (index <= CIRRUS_CRTC_MAX) {
1600 return BX_CIRRUS_THIS crtc.reg[index];
1603 return 0xff;
1606 void bx_svga_cirrus_c::svga_write_crtc(Bit32u address, unsigned index, Bit8u value)
1608 BX_DEBUG(("crtc: index 0x%02x write 0x%02x", index, (unsigned)value));
1610 bx_bool update_pitch = 0;
1612 switch (index) {
1613 case 0x00: // VGA
1614 case 0x02: // VGA
1615 case 0x03: // VGA
1616 case 0x04: // VGA
1617 case 0x05: // VGA
1618 case 0x06: // VGA
1619 case 0x08: // VGA
1620 case 0x0a: // VGA
1621 case 0x0b: // VGA
1622 case 0x0e: // VGA
1623 case 0x0f: // VGA
1624 case 0x10: // VGA
1625 case 0x11: // VGA
1626 case 0x14: // VGA
1627 case 0x15: // VGA
1628 case 0x16: // VGA
1629 case 0x17: // VGA
1630 case 0x18: // VGA
1631 break;
1633 case 0x01: // VGA
1634 case 0x07: // VGA
1635 case 0x09: // VGA
1636 case 0x0c: // VGA (display offset 0x00ff00)
1637 case 0x0d: // VGA (display offset 0x0000ff)
1638 case 0x12: // VGA
1639 case 0x1A: // 0x01: interlaced video mode
1640 case 0x1D: // 0x80: offset 0x080000 (>=CLGD5434)
1641 BX_CIRRUS_THIS svga_needs_update_mode = true;
1642 break;
1644 case 0x13: // VGA
1645 case 0x1B: // 0x01: offset 0x010000, 0x0c: offset 0x060000
1646 update_pitch = 1;
1647 break;
1649 case 0x19:
1650 case 0x1C:
1651 break;
1653 default:
1654 BX_DEBUG(("CRTC index 0x%02x is unknown(write 0x%02x)", index, (unsigned)value));
1655 return;
1658 if (index <= CIRRUS_CRTC_MAX) {
1659 BX_CIRRUS_THIS crtc.reg[index] = value;
1661 if (index <= VGA_CRTC_MAX) {
1662 VGA_WRITE(address,value,1);
1665 if (update_pitch) {
1666 BX_CIRRUS_THIS svga_pitch = (BX_CIRRUS_THIS crtc.reg[0x13] << 3) | ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x10) << 7);
1667 BX_CIRRUS_THIS svga_needs_update_mode = true;
1671 Bit8u bx_svga_cirrus_c::svga_read_sequencer(Bit32u address, unsigned index)
1673 switch (index) {
1674 case 0x00: // VGA
1675 case 0x01: // VGA
1676 case 0x02: // VGA
1677 case 0x03: // VGA
1678 case 0x04: // VGA
1679 break;
1680 case 0x6: // cirrus unlock extensions
1681 case 0x7: // cirrus extended sequencer mode
1682 case 0xf: // cirrus dram control
1683 case 0x12: // graphics cursor attribute
1684 case 0x13: // graphics cursor pattern address offset
1685 case 0x17: // configuration readback & extended control
1686 break;
1687 case 0x10: // cursor xpos << 5 (index & 0x3f)
1688 case 0x30:
1689 case 0x50:
1690 case 0x70:
1691 case 0x90:
1692 case 0xb0:
1693 case 0xd0:
1694 case 0xf0:
1695 return BX_CIRRUS_THIS sequencer.reg[0x10];
1696 case 0x11: // cursor ypos << 5 (index & 0x3f)
1697 case 0x31:
1698 case 0x51:
1699 case 0x71:
1700 case 0x91:
1701 case 0xb1:
1702 case 0xd1:
1703 case 0xf1:
1704 return BX_CIRRUS_THIS sequencer.reg[0x11];
1705 default:
1706 BX_DEBUG(("sequencer index 0x%02x is unknown(read)", index));
1707 break;
1710 if (index <= VGA_SEQENCER_MAX) {
1711 return VGA_READ(address,1);
1714 if (index <= CIRRUS_SEQENCER_MAX) {
1715 return BX_CIRRUS_THIS sequencer.reg[index];
1718 return 0xff;
1721 void bx_svga_cirrus_c::svga_write_sequencer(Bit32u address, unsigned index, Bit8u value)
1723 BX_DEBUG(("sequencer: index 0x%02x write 0x%02x", index, (unsigned)value));
1725 bx_bool update_cursor = 0;
1726 Bit16u x, y, size;
1728 x = BX_CIRRUS_THIS hw_cursor.x;
1729 y = BX_CIRRUS_THIS hw_cursor.y;
1730 size = BX_CIRRUS_THIS hw_cursor.size;
1732 switch (index) {
1733 case 0x00: // VGA
1734 case 0x02: // VGA
1735 case 0x03: // VGA
1736 break;
1737 case 0x01: // VGA
1738 case 0x04: // VGA
1739 BX_CIRRUS_THIS svga_needs_update_mode = true;
1740 break;
1741 case 0x6: // cirrus unlock extensions
1742 value &= 0x17;
1743 if (value == 0x12) {
1744 BX_CIRRUS_THIS svga_unlock_special = true;
1745 BX_CIRRUS_THIS sequencer.reg[0x6] = 0x12;
1747 else {
1748 BX_CIRRUS_THIS svga_unlock_special = false;
1749 BX_CIRRUS_THIS sequencer.reg[0x6] = 0x0f;
1751 return;
1752 case 0x7: // cirrus extended sequencer mode
1753 if (value != BX_CIRRUS_THIS sequencer.reg[0x7]) {
1754 BX_CIRRUS_THIS svga_needs_update_mode = true;
1756 break;
1757 case 0x08:
1758 case 0x09:
1759 case 0x0a: // cirrus scratch reg 1
1760 case 0x0b:
1761 case 0x0c:
1762 case 0x0d:
1763 case 0x0e:
1764 case 0x1b:
1765 case 0x1c:
1766 case 0x1d:
1767 case 0x1e:
1768 break;
1769 case 0x0f:
1770 return;
1771 case 0x10: // cursor xpos << 5 (index & 0x3f)
1772 case 0x30:
1773 case 0x50:
1774 case 0x70:
1775 case 0x90:
1776 case 0xb0:
1777 case 0xd0:
1778 case 0xf0:
1779 BX_CIRRUS_THIS sequencer.reg[0x10] = value;
1780 x = BX_CIRRUS_THIS hw_cursor.x;
1781 BX_CIRRUS_THIS hw_cursor.x = (value << 3) | (index >> 5);
1782 update_cursor = 1;
1783 break;
1784 case 0x11: // cursor ypos << 5 (index & 0x3f)
1785 case 0x31:
1786 case 0x51:
1787 case 0x71:
1788 case 0x91:
1789 case 0xb1:
1790 case 0xd1:
1791 case 0xf1:
1792 BX_CIRRUS_THIS sequencer.reg[0x11] = value;
1793 y = BX_CIRRUS_THIS hw_cursor.y;
1794 BX_CIRRUS_THIS hw_cursor.y = (value << 3) | (index >> 5);
1795 update_cursor = 1;
1796 break;
1797 case 0x12:
1798 size = BX_CIRRUS_THIS hw_cursor.size;
1799 if (value & CIRRUS_CURSOR_SHOW) {
1800 if (value & CIRRUS_CURSOR_LARGE) {
1801 BX_CIRRUS_THIS hw_cursor.size = 64;
1803 else {
1804 BX_CIRRUS_THIS hw_cursor.size = 32;
1807 else {
1808 BX_CIRRUS_THIS hw_cursor.size = 0;
1810 update_cursor = 1;
1811 break;
1812 case 0x13:
1813 update_cursor = 1;
1814 break;
1815 case 0x17:
1816 value = (BX_CIRRUS_THIS sequencer.reg[0x17] & 0x38) | (value & 0xc7);
1817 break;
1818 default:
1819 BX_DEBUG(("sequencer index 0x%02x is unknown(write 0x%02x)", index, (unsigned)value));
1820 break;
1823 if (update_cursor) {
1824 BX_CIRRUS_THIS redraw_area(x, y, size, size);
1825 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);
1828 if (index <= CIRRUS_SEQENCER_MAX) {
1829 BX_CIRRUS_THIS sequencer.reg[index] = value;
1831 if (index <= VGA_SEQENCER_MAX) {
1832 VGA_WRITE(address,value,1);
1836 Bit8u bx_svga_cirrus_c::svga_read_control(Bit32u address, unsigned index)
1838 switch (index) {
1839 case 0x00: // VGA
1840 return BX_CIRRUS_THIS control.shadow_reg0;
1841 case 0x01: // VGA
1842 return BX_CIRRUS_THIS control.shadow_reg1;
1843 case 0x05: // VGA
1844 return BX_CIRRUS_THIS control.reg[index];
1845 case 0x02: // VGA
1846 case 0x03: // VGA
1847 case 0x04: // VGA
1848 case 0x06: // VGA
1849 case 0x07: // VGA
1850 case 0x08: // VGA
1851 break;
1852 case 0x09: // bank offset #0
1853 case 0x0A: // bank offset #1
1854 case 0x0B:
1855 break;
1857 case 0x10: // BGCOLOR 0x0000ff00
1858 case 0x11: // FGCOLOR 0x0000ff00
1859 case 0x12: // BGCOLOR 0x00ff0000
1860 case 0x13: // FGCOLOR 0x00ff0000
1861 case 0x14: // BGCOLOR 0xff000000
1862 case 0x15: // FGCOLOR 0xff000000
1863 break;
1865 case 0x20: // BLT WIDTH 0x0000ff
1866 case 0x21: // BLT WIDTH 0x001f00
1867 case 0x22: // BLT HEIGHT 0x0000ff
1868 case 0x23: // BLT HEIGHT 0x001f00
1869 case 0x24: // BLT DEST PITCH 0x0000ff
1870 case 0x25: // BLT DEST PITCH 0x001f00
1871 case 0x26: // BLT SRC PITCH 0x0000ff
1872 case 0x27: // BLT SRC PITCH 0x001f00
1873 case 0x28: // BLT DEST ADDR 0x0000ff
1874 case 0x29: // BLT DEST ADDR 0x00ff00
1875 case 0x2a: // BLT DEST ADDR 0x3f0000
1876 case 0x2c: // BLT SRC ADDR 0x0000ff
1877 case 0x2d: // BLT SRC ADDR 0x00ff00
1878 case 0x2e: // BLT SRC ADDR 0x3f0000
1879 case 0x2f: // BLT WRITE MASK
1880 case 0x30: // BLT MODE
1881 case 0x31: // BLT STATUS
1882 case 0x32: // RASTER OP
1883 case 0x33: // BLT MODE EXTENSION
1884 case 0x34: // BLT TRANSPARENT COLOR 0x00ff
1885 case 0x35: // BLT TRANSPARENT COLOR 0xff00
1886 case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff
1887 case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00
1888 break;
1890 default:
1891 BX_DEBUG(("control index 0x%02x is unknown(read)", index));
1892 break;
1895 if (index <= VGA_CONTROL_MAX) {
1896 return VGA_READ(address,1);
1899 if (index <= CIRRUS_CONTROL_MAX) {
1900 return BX_CIRRUS_THIS control.reg[index];
1903 return 0xff;
1906 void bx_svga_cirrus_c::svga_write_control(Bit32u address, unsigned index, Bit8u value)
1908 Bit8u old_value;
1910 BX_DEBUG(("control: index 0x%02x write 0x%02x", index, (unsigned)value));
1912 switch (index) {
1913 case 0x00: // VGA
1914 BX_CIRRUS_THIS control.shadow_reg0 = value;
1915 break;
1916 case 0x01: // VGA
1917 BX_CIRRUS_THIS control.shadow_reg1 = value;
1918 break;
1919 case 0x02: // VGA
1920 case 0x03: // VGA
1921 case 0x04: // VGA
1922 case 0x07: // VGA
1923 case 0x08: // VGA
1924 break;
1925 case 0x05: // VGA
1926 case 0x06: // VGA
1927 BX_CIRRUS_THIS svga_needs_update_mode = true;
1928 break;
1929 case 0x09: // bank offset #0
1930 case 0x0A: // bank offset #1
1931 case 0x0B:
1932 BX_CIRRUS_THIS control.reg[index] = value;
1933 update_bank_ptr(0);
1934 update_bank_ptr(1);
1935 break;
1937 case 0x10: // BGCOLOR 0x0000ff00
1938 case 0x11: // FGCOLOR 0x0000ff00
1939 case 0x12: // BGCOLOR 0x00ff0000
1940 case 0x13: // FGCOLOR 0x00ff0000
1941 case 0x14: // BGCOLOR 0xff000000
1942 case 0x15: // FGCOLOR 0xff000000
1943 break;
1945 case 0x20: // BLT WIDTH 0x0000ff
1946 break;
1947 case 0x21: // BLT WIDTH 0x001f00
1948 value &= 0x1f;
1949 break;
1950 case 0x22: // BLT HEIGHT 0x0000ff
1951 break;
1952 case 0x23: // BLT HEIGHT 0x001f00
1953 value &= 0x1f;
1954 break;
1955 case 0x24: // BLT DEST PITCH 0x0000ff
1956 break;
1957 case 0x25: // BLT DEST PITCH 0x001f00
1958 value &= 0x1f;
1959 break;
1960 case 0x26: // BLT SRC PITCH 0x0000ff
1961 break;
1962 case 0x27: // BLT SRC PITCH 0x001f00
1963 value &= 0x1f;
1964 break;
1965 case 0x28: // BLT DEST ADDR 0x0000ff
1966 break;
1967 case 0x29: // BLT DEST ADDR 0x00ff00
1968 break;
1969 case 0x2a: // BLT DEST ADDR 0x3f0000
1970 BX_CIRRUS_THIS control.reg[index] = value & 0x3f;
1971 if (BX_CIRRUS_THIS control.reg[0x31] & CIRRUS_BLT_AUTOSTART) {
1972 svga_bitblt();
1974 return;
1975 case 0x2b: // BLT DEST ADDR (unused bits)
1976 break;
1977 case 0x2c: // BLT SRC ADDR 0x0000ff
1978 break;
1979 case 0x2d: // BLT SRC ADDR 0x00ff00
1980 break;
1981 case 0x2e: // BLT SRC ADDR 0x3f0000
1982 value &= 0x3f;
1983 break;
1984 case 0x2f: // BLT WRITE MASK
1985 if (value & ~0x1f) {
1986 BX_ERROR(("BLT WRITE MASK support is not complete (value = 0x%02x)", value));
1988 break;
1989 case 0x30: // BLT MODE
1990 break;
1991 case 0x31: // BLT STATUS/START
1992 old_value = BX_CIRRUS_THIS control.reg[0x31];
1993 BX_CIRRUS_THIS control.reg[0x31] = value;
1994 if (((old_value & CIRRUS_BLT_RESET) != 0) &&
1995 ((value & CIRRUS_BLT_RESET) == 0)) {
1996 svga_reset_bitblt();
1998 else if (((old_value & CIRRUS_BLT_START) == 0) &&
1999 ((value & CIRRUS_BLT_START) != 0)) {
2000 BX_CIRRUS_THIS control.reg[0x31] |= CIRRUS_BLT_BUSY;
2001 svga_bitblt();
2003 return;
2004 case 0x32: // RASTER OP
2005 case 0x33: // BLT MODE EXTENSION
2006 break;
2007 case 0x34: // BLT TRANSPARENT COLOR 0x00ff
2008 case 0x35: // BLT TRANSPARENT COLOR 0xff00
2009 case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff
2010 case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00
2011 default:
2012 BX_DEBUG(("control index 0x%02x is unknown(write 0x%02x)", index, (unsigned)value));
2013 break;
2016 if (index <= CIRRUS_CONTROL_MAX) {
2017 BX_CIRRUS_THIS control.reg[index] = value;
2019 if (index <= VGA_CONTROL_MAX) {
2020 VGA_WRITE(address,value,1);
2024 Bit8u bx_svga_cirrus_c::svga_mmio_vga_read(Bit32u address)
2026 Bit8u value = 0xff;
2027 // bx_bool svga_unlock_special_old = BX_CIRRUS_THIS svga_unlock_special;
2029 BX_DEBUG(("MMIO vga read - address 0x%04x, value 0x%02x",address,value));
2031 // BX_CIRRUS_THIS svga_unlock_special = true;
2033 #if BX_USE_CIRRUS_SMF
2034 value = (Bit8u)svga_read_handler(theSvga,0x3c0+address,1);
2035 #else // BX_USE_CIRRUS_SMF
2036 value = (Bit8u)svga_read(0x3c0+address,1);
2037 #endif // BX_USE_CIRRUS_SMF
2039 // BX_CIRRUS_THIS svga_unlock_special = svga_unlock_special_old;
2040 return value;
2043 void bx_svga_cirrus_c::svga_mmio_vga_write(Bit32u address,Bit8u value)
2045 // bx_bool svga_unlock_special_old = BX_CIRRUS_THIS svga_unlock_special;
2047 BX_DEBUG(("MMIO vga write - address 0x%04x, value 0x%02x",address,value));
2049 // BX_CIRRUS_THIS svga_unlock_special = true;
2051 #if BX_USE_CIRRUS_SMF
2052 svga_write_handler(theSvga,0x3c0+address,value,1);
2053 #else // BX_USE_CIRRUS_SMF
2054 svga_write(0x3c0+address,value,1);
2055 #endif // BX_USE_CIRRUS_SMF
2057 /* switch (BX_CIRRUS_THIS sequencer.reg[0x06]) {
2058 case 0x0f:
2059 svga_unlock_special_old = false;
2060 break;
2061 case 0x12:
2062 svga_unlock_special_old = true;
2063 break;
2066 BX_CIRRUS_THIS svga_unlock_special = svga_unlock_special_old;*/
2069 Bit8u bx_svga_cirrus_c::svga_mmio_blt_read(Bit32u address)
2071 Bit8u value = 0xff;
2073 switch (address) {
2074 case (CLGD543x_MMIO_BLTBGCOLOR+0):
2075 value = BX_CIRRUS_THIS control.shadow_reg0;
2076 break;
2077 case (CLGD543x_MMIO_BLTBGCOLOR+1):
2078 value = svga_read_control(0x3cf,0x10);
2079 break;
2080 case (CLGD543x_MMIO_BLTBGCOLOR+2):
2081 value = svga_read_control(0x3cf,0x12);
2082 break;
2083 case (CLGD543x_MMIO_BLTBGCOLOR+3):
2084 value = svga_read_control(0x3cf,0x14);
2085 break;
2086 case (CLGD543x_MMIO_BLTFGCOLOR+0):
2087 value = BX_CIRRUS_THIS control.shadow_reg1;
2088 break;
2089 case (CLGD543x_MMIO_BLTFGCOLOR+1):
2090 value = svga_read_control(0x3cf,0x11);
2091 break;
2092 case (CLGD543x_MMIO_BLTFGCOLOR+2):
2093 value = svga_read_control(0x3cf,0x13);
2094 break;
2095 case (CLGD543x_MMIO_BLTFGCOLOR+3):
2096 value = svga_read_control(0x3cf,0x15);
2097 break;
2098 case (CLGD543x_MMIO_BLTWIDTH+0):
2099 value = svga_read_control(0x3cf,0x20);
2100 break;
2101 case (CLGD543x_MMIO_BLTWIDTH+1):
2102 value = svga_read_control(0x3cf,0x21);
2103 break;
2104 case (CLGD543x_MMIO_BLTHEIGHT+0):
2105 value = svga_read_control(0x3cf,0x22);
2106 break;
2107 case (CLGD543x_MMIO_BLTHEIGHT+1):
2108 value = svga_read_control(0x3cf,0x23);
2109 break;
2110 case (CLGD543x_MMIO_BLTDESTPITCH+0):
2111 value = svga_read_control(0x3cf,0x24);
2112 break;
2113 case (CLGD543x_MMIO_BLTDESTPITCH+1):
2114 value = svga_read_control(0x3cf,0x25);
2115 break;
2116 case (CLGD543x_MMIO_BLTSRCPITCH+0):
2117 value = svga_read_control(0x3cf,0x26);
2118 break;
2119 case (CLGD543x_MMIO_BLTSRCPITCH+1):
2120 value = svga_read_control(0x3cf,0x27);
2121 break;
2122 case (CLGD543x_MMIO_BLTDESTADDR+0):
2123 value = svga_read_control(0x3cf,0x28);
2124 break;
2125 case (CLGD543x_MMIO_BLTDESTADDR+1):
2126 value = svga_read_control(0x3cf,0x29);
2127 break;
2128 case (CLGD543x_MMIO_BLTDESTADDR+2):
2129 value = svga_read_control(0x3cf,0x2a);
2130 break;
2131 case (CLGD543x_MMIO_BLTDESTADDR+3):
2132 value = svga_read_control(0x3cf,0x2b);
2133 break;
2134 case (CLGD543x_MMIO_BLTSRCADDR+0):
2135 value = svga_read_control(0x3cf,0x2c);
2136 break;
2137 case (CLGD543x_MMIO_BLTSRCADDR+1):
2138 value = svga_read_control(0x3cf,0x2d);
2139 break;
2140 case (CLGD543x_MMIO_BLTSRCADDR+2):
2141 value = svga_read_control(0x3cf,0x2e);
2142 break;
2143 case CLGD543x_MMIO_BLTWRITEMASK:
2144 value = svga_read_control(0x3cf,0x2f);
2145 break;
2146 case CLGD543x_MMIO_BLTMODE:
2147 value = svga_read_control(0x3cf,0x30);
2148 break;
2149 case CLGD543x_MMIO_BLTROP:
2150 value = svga_read_control(0x3cf,0x32);
2151 break;
2152 case CLGD543x_MMIO_BLTMODEEXT:
2153 value = svga_read_control(0x3cf,0x33);
2154 break;
2155 case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+0):
2156 value = svga_read_control(0x3cf,0x34);
2157 break;
2158 case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+1):
2159 value = svga_read_control(0x3cf,0x35);
2160 break;
2161 case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+2):
2162 BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR"));
2163 break;
2164 case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+3):
2165 BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR"));
2166 break;
2167 case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+0):
2168 value = svga_read_control(0x3cf,0x38);
2169 break;
2170 case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+1):
2171 value = svga_read_control(0x3cf,0x39);
2172 break;
2173 case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+2):
2174 BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK"));
2175 break;
2176 case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+3):
2177 BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK"));
2178 break;
2179 case CLGD543x_MMIO_BLTSTATUS:
2180 value = svga_read_control(0x3cf,0x31);
2181 break;
2182 default:
2183 BX_ERROR(("MMIO blt read - address 0x%04x",address));
2184 break;
2187 BX_DEBUG(("MMIO blt read - address 0x%04x, value 0x%02x",address,value));
2189 return value;
2192 void bx_svga_cirrus_c::svga_mmio_blt_write(Bit32u address,Bit8u value)
2194 BX_DEBUG(("MMIO blt write - address 0x%04x, value 0x%02x",address,value));
2196 switch (address) {
2197 case (CLGD543x_MMIO_BLTBGCOLOR+0):
2198 BX_CIRRUS_THIS control.shadow_reg0 = value;
2199 break;
2200 case (CLGD543x_MMIO_BLTBGCOLOR+1):
2201 svga_write_control(0x3cf,0x10,value);
2202 break;
2203 case (CLGD543x_MMIO_BLTBGCOLOR+2):
2204 svga_write_control(0x3cf,0x12,value);
2205 break;
2206 case (CLGD543x_MMIO_BLTBGCOLOR+3):
2207 svga_write_control(0x3cf,0x14,value);
2208 break;
2209 case (CLGD543x_MMIO_BLTFGCOLOR+0):
2210 BX_CIRRUS_THIS control.shadow_reg1 = value;
2211 break;
2212 case (CLGD543x_MMIO_BLTFGCOLOR+1):
2213 svga_write_control(0x3cf,0x11,value);
2214 break;
2215 case (CLGD543x_MMIO_BLTFGCOLOR+2):
2216 svga_write_control(0x3cf,0x13,value);
2217 break;
2218 case (CLGD543x_MMIO_BLTFGCOLOR+3):
2219 svga_write_control(0x3cf,0x15,value);
2220 break;
2221 case (CLGD543x_MMIO_BLTWIDTH+0):
2222 svga_write_control(0x3cf,0x20,value);
2223 break;
2224 case (CLGD543x_MMIO_BLTWIDTH+1):
2225 svga_write_control(0x3cf,0x21,value);
2226 break;
2227 case (CLGD543x_MMIO_BLTHEIGHT+0):
2228 svga_write_control(0x3cf,0x22,value);
2229 break;
2230 case (CLGD543x_MMIO_BLTHEIGHT+1):
2231 svga_write_control(0x3cf,0x23,value);
2232 break;
2233 case (CLGD543x_MMIO_BLTDESTPITCH+0):
2234 svga_write_control(0x3cf,0x24,value);
2235 break;
2236 case (CLGD543x_MMIO_BLTDESTPITCH+1):
2237 svga_write_control(0x3cf,0x25,value);
2238 break;
2239 case (CLGD543x_MMIO_BLTSRCPITCH+0):
2240 svga_write_control(0x3cf,0x26,value);
2241 break;
2242 case (CLGD543x_MMIO_BLTSRCPITCH+1):
2243 svga_write_control(0x3cf,0x27,value);
2244 break;
2245 case (CLGD543x_MMIO_BLTDESTADDR+0):
2246 svga_write_control(0x3cf,0x28,value);
2247 break;
2248 case (CLGD543x_MMIO_BLTDESTADDR+1):
2249 svga_write_control(0x3cf,0x29,value);
2250 break;
2251 case (CLGD543x_MMIO_BLTDESTADDR+2):
2252 svga_write_control(0x3cf,0x2a,value);
2253 break;
2254 case (CLGD543x_MMIO_BLTDESTADDR+3):
2255 svga_write_control(0x3cf,0x2b,value);
2256 break;
2257 case (CLGD543x_MMIO_BLTSRCADDR+0):
2258 svga_write_control(0x3cf,0x2c,value);
2259 break;
2260 case (CLGD543x_MMIO_BLTSRCADDR+1):
2261 svga_write_control(0x3cf,0x2d,value);
2262 break;
2263 case (CLGD543x_MMIO_BLTSRCADDR+2):
2264 svga_write_control(0x3cf,0x2e,value);
2265 break;
2266 case CLGD543x_MMIO_BLTWRITEMASK:
2267 svga_write_control(0x3cf,0x2f,value);
2268 break;
2269 case CLGD543x_MMIO_BLTMODE:
2270 svga_write_control(0x3cf,0x30,value);
2271 break;
2272 case CLGD543x_MMIO_BLTMODE+1:
2273 // unused ??? - ignored for now
2274 break;
2275 case CLGD543x_MMIO_BLTROP:
2276 svga_write_control(0x3cf,0x32,value);
2277 break;
2278 case CLGD543x_MMIO_BLTMODEEXT:
2279 svga_write_control(0x3cf,0x33,value);
2280 break;
2281 case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+0):
2282 svga_write_control(0x3cf,0x34,value);
2283 break;
2284 case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+1):
2285 svga_write_control(0x3cf,0x35,value);
2286 break;
2287 case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+2):
2288 BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR"));
2289 break;
2290 case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+3):
2291 BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR"));
2292 break;
2293 case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+0):
2294 svga_write_control(0x3cf,0x38,value);
2295 break;
2296 case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+1):
2297 svga_write_control(0x3cf,0x39,value);
2298 break;
2299 case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+2):
2300 BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK"));
2301 break;
2302 case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+3):
2303 BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK"));
2304 break;
2305 case CLGD543x_MMIO_BLTSTATUS:
2306 svga_write_control(0x3cf,0x31,value);
2307 break;
2308 default:
2309 BX_ERROR(("MMIO blt write - address 0x%04x, value 0x%02x",address,value));
2310 break;
2315 /////////////////////////////////////////////////////////////////////////
2317 // PCI support
2319 /////////////////////////////////////////////////////////////////////////
2321 #if BX_SUPPORT_PCI
2323 void bx_svga_cirrus_c::svga_init_pcihandlers(void)
2325 int i;
2327 Bit8u devfunc = 0x00;
2328 DEV_register_pci_handlers(BX_CIRRUS_THIS_PTR,
2329 &devfunc, "cirrus", "SVGA Cirrus PCI");
2331 for (i=0; i<256; i++) {
2332 BX_CIRRUS_THIS pci_conf[i] = 0x0;
2335 WriteHostWordToLittleEndian(
2336 &BX_CIRRUS_THIS pci_conf[0x00], PCI_VENDOR_CIRRUS);
2337 WriteHostWordToLittleEndian(
2338 &BX_CIRRUS_THIS pci_conf[0x02], PCI_DEVICE_CLGD5446);
2339 WriteHostWordToLittleEndian(
2340 &BX_CIRRUS_THIS pci_conf[0x04],
2341 (PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS));
2342 WriteHostDWordToLittleEndian(
2343 &BX_CIRRUS_THIS pci_conf[0x10],
2344 (PCI_MAP_MEM | PCI_MAP_MEMFLAGS_32BIT | PCI_MAP_MEMFLAGS_CACHEABLE));
2345 WriteHostDWordToLittleEndian(
2346 &BX_CIRRUS_THIS pci_conf[0x14],
2347 (PCI_MAP_MEM | PCI_MAP_MEMFLAGS_32BIT));
2348 BX_CIRRUS_THIS pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
2349 BX_CIRRUS_THIS pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
2350 BX_CIRRUS_THIS pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
2352 BX_CIRRUS_THIS pci_memaddr = 0;
2353 BX_CIRRUS_THIS pci_mmioaddr = 0;
2356 Bit32u bx_svga_cirrus_c::pci_read_handler(Bit8u address, unsigned io_len)
2358 if (io_len > 4) {
2359 BX_PANIC(("pci_read: io_len > 4!"));
2360 return 0xffffffff;
2362 if (((unsigned)address + io_len) > 256) {
2363 BX_PANIC(("pci_read: (address + io_len) > 256!"));
2364 return 0xffffffff;
2367 Bit32u ret = 0;
2368 for (unsigned i = 0; i < io_len; i++) {
2369 ret |= (Bit32u)(BX_CIRRUS_THIS pci_conf[address + i]) << (i*8);
2372 BX_DEBUG(("pci_read: address 0x%02x, io_len 0x%02x, value 0x%x",
2373 (unsigned)address, (unsigned)io_len, (unsigned)ret));
2375 return ret;
2378 void bx_svga_cirrus_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len)
2380 unsigned i;
2381 unsigned write_addr;
2382 Bit8u new_value, old_value;
2383 bx_bool baseaddr0_change = 0;
2384 bx_bool baseaddr1_change = 0;
2386 BX_DEBUG(("pci_write: address 0x%02x, io_len 0x%02x, value 0x%x",
2387 (unsigned)address, (unsigned)io_len, (unsigned)value));
2389 if ((address > 0x17) && (address < 0x34))
2390 return;
2391 if (io_len <= 4) {
2392 for (i = 0; i < io_len; i++) {
2393 write_addr = address + i;
2394 old_value = BX_CIRRUS_THIS pci_conf[write_addr];
2395 new_value = (Bit8u)(value & 0xff);
2396 switch (write_addr) {
2397 case 0x04: // command bit0-7
2398 new_value &= PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
2399 new_value |= old_value & ~(PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS);
2400 break;
2401 case 0x05: // command bit8-15
2402 new_value = old_value;
2403 break;
2404 case 0x06: // status bit0-7
2405 new_value = old_value & (~new_value);
2406 break;
2407 case 0x07: // status bit8-15
2408 new_value = old_value & (~new_value);
2409 break;
2411 case 0x10: // base address #0
2412 new_value = (new_value & 0xf0) | (old_value & 0x0f);
2413 case 0x11: case 0x12: case 0x13:
2414 baseaddr0_change |= (old_value != new_value);
2415 break;
2416 case 0x14: // base address #1
2417 new_value = (new_value & 0xf0) | (old_value & 0x0f);
2418 case 0x15: case 0x16: case 0x17:
2419 baseaddr1_change |= (old_value != new_value);
2420 break;
2422 // read-only.
2423 case 0x00: case 0x01: // vendor
2424 case 0x02: case 0x03: // device
2425 case 0x08: // revision
2426 case 0x09: case 0x0a: case 0x0b: // class
2427 case 0x0e: // header type
2428 case 0x0f: // built-in self test(unimplemented)
2429 new_value = old_value;
2430 break;
2431 default:
2432 break;
2434 BX_CIRRUS_THIS pci_conf[write_addr] = new_value;
2435 value >>= 8;
2437 if (baseaddr0_change) {
2438 if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler,
2439 cirrus_mem_write_handler,
2440 &BX_CIRRUS_THIS pci_memaddr,
2441 &BX_CIRRUS_THIS pci_conf[0x10],
2442 0x2000000)) {
2443 BX_INFO(("new pci_memaddr: 0x%04x", BX_CIRRUS_THIS pci_memaddr));
2446 if (baseaddr1_change) {
2447 if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler,
2448 cirrus_mem_write_handler,
2449 &BX_CIRRUS_THIS pci_mmioaddr,
2450 &BX_CIRRUS_THIS pci_conf[0x14],
2451 CIRRUS_PNPMMIO_SIZE)) {
2452 BX_INFO(("new pci_mmioaddr = 0x%08x", BX_CIRRUS_THIS pci_mmioaddr));
2458 #endif // BX_SUPPORT_PCI
2460 /////////////////////////////////////////////////////////////////////////
2462 // Bitblt.
2464 /////////////////////////////////////////////////////////////////////////
2466 void bx_svga_cirrus_c::svga_reset_bitblt(void)
2468 BX_CIRRUS_THIS control.reg[0x31] &= ~(CIRRUS_BLT_START|CIRRUS_BLT_BUSY|CIRRUS_BLT_FIFOUSED);
2469 BX_CIRRUS_THIS bitblt.rop_handler = NULL;
2470 BX_CIRRUS_THIS bitblt.src = NULL;
2471 BX_CIRRUS_THIS bitblt.dst = NULL;
2472 BX_CIRRUS_THIS bitblt.memsrc_ptr = NULL;
2473 BX_CIRRUS_THIS bitblt.memsrc_endptr = NULL;
2474 BX_CIRRUS_THIS bitblt.memsrc_needed = 0;
2475 BX_CIRRUS_THIS bitblt.memdst_ptr = NULL;
2476 BX_CIRRUS_THIS bitblt.memdst_endptr = NULL;
2477 BX_CIRRUS_THIS bitblt.memdst_needed = 0;
2480 void bx_svga_cirrus_c::svga_bitblt()
2482 Bit16u tmp16;
2483 Bit32u tmp32;
2484 Bit32u dstaddr;
2485 Bit32u srcaddr;
2486 Bit32u offset;
2488 ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x20],tmp16);
2489 BX_CIRRUS_THIS bitblt.bltwidth = ((int)tmp16 & (int)0x1fff) + 1;
2490 ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x22],tmp16);
2491 BX_CIRRUS_THIS bitblt.bltheight = ((int)tmp16 & (int)0x1fff) + 1;
2492 ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x24],tmp16);
2493 BX_CIRRUS_THIS bitblt.dstpitch = (int)tmp16 & (int)0x1fff;
2494 ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x26],tmp16);
2495 BX_CIRRUS_THIS bitblt.srcpitch = (int)tmp16 & (int)0x1fff;
2496 ReadHostDWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x28],tmp32);
2497 dstaddr = tmp32 & (BX_CIRRUS_THIS s.memsize - 1);
2498 ReadHostDWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x2c],tmp32);
2499 srcaddr = tmp32 & (BX_CIRRUS_THIS s.memsize - 1);
2500 BX_CIRRUS_THIS bitblt.srcaddr = srcaddr;
2501 BX_CIRRUS_THIS bitblt.bltmode = BX_CIRRUS_THIS control.reg[0x30];
2502 BX_CIRRUS_THIS bitblt.bltmodeext = BX_CIRRUS_THIS control.reg[0x33];
2503 BX_CIRRUS_THIS bitblt.bltrop = BX_CIRRUS_THIS control.reg[0x32];
2504 offset = dstaddr - (BX_CIRRUS_THIS disp_ptr - BX_CIRRUS_THIS s.memory);
2505 BX_CIRRUS_THIS redraw.x = (offset % BX_CIRRUS_THIS bitblt.dstpitch) / (BX_CIRRUS_THIS svga_bpp >> 3);
2506 BX_CIRRUS_THIS redraw.y = offset / BX_CIRRUS_THIS bitblt.dstpitch;
2507 BX_CIRRUS_THIS redraw.w = BX_CIRRUS_THIS bitblt.bltwidth / (BX_CIRRUS_THIS svga_bpp >> 3);
2508 BX_CIRRUS_THIS redraw.h = BX_CIRRUS_THIS bitblt.bltheight;
2510 BX_DEBUG(("BLT: src:0x%08x,dst 0x%08x,block %ux%u,mode 0x%02x,ROP 0x%02x",
2511 (unsigned)srcaddr,(unsigned)dstaddr,
2512 (unsigned)BX_CIRRUS_THIS bitblt.bltwidth,(unsigned)BX_CIRRUS_THIS bitblt.bltheight,
2513 (unsigned)BX_CIRRUS_THIS bitblt.bltmode,(unsigned)BX_CIRRUS_THIS bitblt.bltrop));
2514 BX_DEBUG(("BLT: srcpitch:0x%08x,dstpitch 0x%08x,modeext 0x%02x,writemask 0x%02x",
2515 (unsigned)BX_CIRRUS_THIS bitblt.srcpitch,
2516 (unsigned)BX_CIRRUS_THIS bitblt.dstpitch,
2517 (unsigned)BX_CIRRUS_THIS bitblt.bltmodeext,
2518 BX_CIRRUS_THIS control.reg[0x2f]));
2520 switch (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
2521 case CIRRUS_BLTMODE_PIXELWIDTH8:
2522 BX_CIRRUS_THIS bitblt.pixelwidth = 1;
2523 break;
2524 case CIRRUS_BLTMODE_PIXELWIDTH16:
2525 BX_CIRRUS_THIS bitblt.pixelwidth = 2;
2526 break;
2527 case CIRRUS_BLTMODE_PIXELWIDTH24:
2528 BX_CIRRUS_THIS bitblt.pixelwidth = 3;
2529 break;
2530 case CIRRUS_BLTMODE_PIXELWIDTH32:
2531 BX_CIRRUS_THIS bitblt.pixelwidth = 4;
2532 break;
2533 default:
2534 BX_PANIC(("unknown pixel width"));
2535 goto ignoreblt;
2538 BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
2540 if ((BX_CIRRUS_THIS bitblt.bltmode & (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_MEMSYSDEST))
2541 == (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_MEMSYSDEST)) {
2542 BX_ERROR(("BLT: memory-to-memory copy is requested, ROP %02x",
2543 (unsigned)BX_CIRRUS_THIS bitblt.bltrop));
2544 goto ignoreblt;
2547 if ((BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
2548 (BX_CIRRUS_THIS bitblt.bltmode & (CIRRUS_BLTMODE_MEMSYSDEST |
2549 CIRRUS_BLTMODE_TRANSPARENTCOMP |
2550 CIRRUS_BLTMODE_PATTERNCOPY |
2551 CIRRUS_BLTMODE_COLOREXPAND)) ==
2552 (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
2553 BX_CIRRUS_THIS bitblt.rop_handler = svga_get_fwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop);
2554 BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS s.memory + dstaddr;
2555 svga_solidfill();
2556 } else {
2558 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_BACKWARDS) {
2559 BX_CIRRUS_THIS bitblt.dstpitch = -BX_CIRRUS_THIS bitblt.dstpitch;
2560 BX_CIRRUS_THIS bitblt.srcpitch = -BX_CIRRUS_THIS bitblt.srcpitch;
2561 BX_CIRRUS_THIS bitblt.rop_handler = svga_get_bkwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop);
2562 BX_CIRRUS_THIS redraw.x -= BX_CIRRUS_THIS redraw.w;
2563 BX_CIRRUS_THIS redraw.y -= BX_CIRRUS_THIS redraw.h;
2564 } else {
2565 BX_CIRRUS_THIS bitblt.rop_handler = svga_get_fwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop);
2568 BX_DEBUG(("BLT redraw: x = %d, y = %d, w = %d, h = %d", BX_CIRRUS_THIS redraw.x,
2569 BX_CIRRUS_THIS redraw.y, BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h));
2571 // setup bitblt engine.
2572 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_MEMSYSSRC) {
2573 svga_setup_bitblt_cputovideo(dstaddr,srcaddr);
2575 else if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_MEMSYSDEST) {
2576 svga_setup_bitblt_videotocpu(dstaddr,srcaddr);
2578 else {
2579 svga_setup_bitblt_videotovideo(dstaddr,srcaddr);
2581 return;
2584 ignoreblt:
2585 svga_reset_bitblt();
2588 void bx_svga_cirrus_c::svga_setup_bitblt_cputovideo(Bit32u dstaddr,Bit32u srcaddr)
2590 Bit16u w;
2592 BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
2594 BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS s.memory + dstaddr;
2595 BX_CIRRUS_THIS bitblt.src = NULL;
2597 BX_CIRRUS_THIS bitblt.memsrc_ptr = &BX_CIRRUS_THIS bitblt.memsrc[0];
2598 BX_CIRRUS_THIS bitblt.memsrc_endptr = &BX_CIRRUS_THIS bitblt.memsrc[0];
2600 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) {
2601 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) {
2602 BX_CIRRUS_THIS bitblt.srcpitch = 8;
2603 } else {
2604 BX_CIRRUS_THIS bitblt.srcpitch = 8 * 8 * BX_CIRRUS_THIS bitblt.pixelwidth;
2606 BX_CIRRUS_THIS bitblt.memsrc_needed = BX_CIRRUS_THIS bitblt.srcpitch;
2607 BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_memsrc_static;
2608 } else {
2609 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) {
2610 w = BX_CIRRUS_THIS bitblt.bltwidth / BX_CIRRUS_THIS bitblt.pixelwidth;
2611 if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) {
2612 BX_CIRRUS_THIS bitblt.srcpitch = (w + 31) >> 5;
2613 } else {
2614 BX_CIRRUS_THIS bitblt.srcpitch = (w + 7) >> 3;
2616 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
2617 BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_colorexpand_transp_memsrc_static;
2618 } else {
2619 BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_memsrc_static;
2621 } else {
2622 BX_CIRRUS_THIS bitblt.srcpitch = (BX_CIRRUS_THIS bitblt.bltwidth + 3) & (~3);
2623 BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_memsrc_static;
2625 BX_CIRRUS_THIS bitblt.memsrc_needed =
2626 BX_CIRRUS_THIS bitblt.srcpitch * BX_CIRRUS_THIS bitblt.bltheight;
2628 BX_CIRRUS_THIS bitblt.memsrc_endptr += BX_CIRRUS_THIS bitblt.srcpitch;
2631 void bx_svga_cirrus_c::svga_setup_bitblt_videotocpu(Bit32u dstaddr,Bit32u srcaddr)
2633 BX_ERROR(("BLT: MEMSYSDEST is not implemented"));
2635 BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_MEMSYSDEST;
2637 #if 0
2638 BX_CIRRUS_THIS bitblt.dst = NULL;
2639 BX_CIRRUS_THIS bitblt.src = BX_CIRRUS_THIS s.memory + srcaddr;
2641 BX_CIRRUS_THIS bitblt.memdst_ptr = &BX_CIRRUS_THIS bitblt.memdst[0];
2642 BX_CIRRUS_THIS bitblt.memdst_endptr = &BX_CIRRUS_THIS bitblt.memdst[0];
2644 BX_CIRRUS_THIS bitblt.memdst_needed =
2645 BX_CIRRUS_THIS bitblt.bltwidth * BX_CIRRUS_THIS bitblt.bltheight;
2646 BX_CIRRUS_THIS bitblt.memdst_needed = (BX_CIRRUS_THIS bitblt.memdst_needed + 3) & (~3);
2648 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) {
2649 BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_memdst_static;
2651 else {
2652 BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_memdst_static;
2654 #endif
2657 void bx_svga_cirrus_c::svga_setup_bitblt_videotovideo(Bit32u dstaddr,Bit32u srcaddr)
2659 BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS s.memory + dstaddr;
2661 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) {
2662 BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_static;
2663 BX_CIRRUS_THIS bitblt.src = BX_CIRRUS_THIS s.memory + (srcaddr & ~0x07);
2664 } else {
2665 BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_static;
2666 BX_CIRRUS_THIS bitblt.src = BX_CIRRUS_THIS s.memory + srcaddr;
2669 (*BX_CIRRUS_THIS bitblt.bitblt_ptr)();
2670 svga_reset_bitblt();
2671 BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y,
2672 BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h);
2675 void bx_svga_cirrus_c::svga_colorexpand(Bit8u *dst,const Bit8u *src,int count,int pixelwidth)
2677 BX_DEBUG(("svga_cirrus: COLOR EXPAND"));
2679 switch (pixelwidth) {
2680 case 1:
2681 svga_colorexpand_8(dst,src,count);
2682 break;
2683 case 2:
2684 svga_colorexpand_16(dst,src,count);
2685 break;
2686 case 3:
2687 svga_colorexpand_24(dst,src,count);
2688 break;
2689 case 4:
2690 svga_colorexpand_32(dst,src,count);
2691 break;
2692 default:
2693 BX_PANIC(("COLOREXPAND: unknown pixelwidth %u",(unsigned)pixelwidth));
2694 break;
2698 #if !BX_USE_CIRRUS_SMF
2699 void bx_svga_cirrus_c::svga_colorexpand_8_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count)
2701 ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_8(dst,src,count);
2704 void bx_svga_cirrus_c::svga_colorexpand_16_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count)
2706 ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_16(dst,src,count);
2709 void bx_svga_cirrus_c::svga_colorexpand_24_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count)
2711 ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_24(dst,src,count);
2714 void bx_svga_cirrus_c::svga_colorexpand_32_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count)
2716 ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_32(dst,src,count);
2719 #endif // BX_USE_CIRRUS_SMF
2721 void bx_svga_cirrus_c::svga_colorexpand_8(Bit8u *dst,const Bit8u *src,int count)
2723 Bit8u colors[2];
2724 unsigned bits;
2725 unsigned bitmask;
2727 colors[0] = BX_CIRRUS_THIS control.shadow_reg0;
2728 colors[1] = BX_CIRRUS_THIS control.shadow_reg1;
2730 bitmask = 0x80;
2731 bits = *src++;
2732 for (int x = 0; x < count; x++) {
2733 if ((bitmask & 0xff) == 0) {
2734 bitmask = 0x80;
2735 bits = *src++;
2737 *dst++ = colors[!!(bits & bitmask)];
2738 bitmask >>= 1;
2742 void bx_svga_cirrus_c::svga_colorexpand_16(Bit8u *dst,const Bit8u *src,int count)
2744 Bit8u colors[2][2];
2745 unsigned bits;
2746 unsigned bitmask;
2747 unsigned index;
2749 colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0;
2750 colors[0][1] = BX_CIRRUS_THIS control.reg[0x10];
2751 colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1;
2752 colors[1][1] = BX_CIRRUS_THIS control.reg[0x11];
2754 bitmask = 0x80;
2755 bits = *src++;
2756 for (int x = 0; x < count; x++) {
2757 if ((bitmask & 0xff) == 0) {
2758 bitmask = 0x80;
2759 bits = *src++;
2761 index = !!(bits & bitmask);
2762 *dst++ = colors[index][0];
2763 *dst++ = colors[index][1];
2764 bitmask >>= 1;
2768 void bx_svga_cirrus_c::svga_colorexpand_24(Bit8u *dst,const Bit8u *src,int count)
2770 Bit8u colors[2][3];
2771 unsigned bits;
2772 unsigned bitmask;
2773 unsigned index;
2775 colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0;
2776 colors[0][1] = BX_CIRRUS_THIS control.reg[0x10];
2777 colors[0][2] = BX_CIRRUS_THIS control.reg[0x12];
2778 colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1;
2779 colors[1][1] = BX_CIRRUS_THIS control.reg[0x11];
2780 colors[1][2] = BX_CIRRUS_THIS control.reg[0x13];
2782 bitmask = 0x80;
2783 bits = *src++;
2784 for (int x = 0; x < count; x++) {
2785 if ((bitmask & 0xff) == 0) {
2786 bitmask = 0x80;
2787 bits = *src++;
2789 index = !!(bits & bitmask);
2790 *dst++ = colors[index][0];
2791 *dst++ = colors[index][1];
2792 *dst++ = colors[index][2];
2793 bitmask >>= 1;
2797 void bx_svga_cirrus_c::svga_colorexpand_32(Bit8u *dst,const Bit8u *src,int count)
2799 Bit8u colors[2][4];
2800 unsigned bits;
2801 unsigned bitmask;
2802 unsigned index;
2804 colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0;
2805 colors[0][1] = BX_CIRRUS_THIS control.reg[0x10];
2806 colors[0][2] = BX_CIRRUS_THIS control.reg[0x12];
2807 colors[0][3] = BX_CIRRUS_THIS control.reg[0x14];
2808 colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1;
2809 colors[1][1] = BX_CIRRUS_THIS control.reg[0x11];
2810 colors[1][2] = BX_CIRRUS_THIS control.reg[0x13];
2811 colors[1][3] = BX_CIRRUS_THIS control.reg[0x15];
2813 bitmask = 0x80;
2814 bits = *src++;
2815 for (int x = 0; x < count; x++) {
2816 if ((bitmask & 0xff) == 0) {
2817 bitmask = 0x80;
2818 bits = *src++;
2820 index = !!(bits & bitmask);
2821 *dst++ = colors[index][0];
2822 *dst++ = colors[index][1];
2823 *dst++ = colors[index][2];
2824 *dst++ = colors[index][3];
2825 bitmask >>= 1;
2829 #if !BX_USE_CIRRUS_SMF
2830 void bx_svga_cirrus_c::svga_patterncopy_static(void *this_ptr)
2832 ((bx_svga_cirrus_c *)this_ptr)->svga_patterncopy();
2835 void bx_svga_cirrus_c::svga_simplebitblt_static(void *this_ptr)
2837 ((bx_svga_cirrus_c *)this_ptr)->svga_simplebitblt();
2840 void bx_svga_cirrus_c::svga_solidfill_static(void *this_ptr)
2842 ((bx_svga_cirrus_c *)this_ptr)->svga_solidfill();
2845 void bx_svga_cirrus_c::svga_patterncopy_memsrc_static(void *this_ptr)
2847 ((bx_svga_cirrus_c *)this_ptr)->svga_patterncopy_memsrc();
2850 void bx_svga_cirrus_c::svga_simplebitblt_memsrc_static(void *this_ptr)
2852 ((bx_svga_cirrus_c *)this_ptr)->svga_simplebitblt_memsrc();
2855 void bx_svga_cirrus_c::svga_colorexpand_transp_memsrc_static(void *this_ptr)
2857 ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_transp_memsrc();
2860 #endif // !BX_USE_CIRRUS_SMF
2862 void bx_svga_cirrus_c::svga_patterncopy()
2864 Bit8u color[4];
2865 Bit8u work_colorexp[256];
2866 Bit8u *src, *dst;
2867 Bit8u *dstc, *srcc, *src2;
2868 int x, y, pattern_x, pattern_y, srcskipleft;
2869 int patternbytes = 8 * BX_CIRRUS_THIS bitblt.pixelwidth;
2870 int pattern_pitch = patternbytes;
2871 int bltbytes = BX_CIRRUS_THIS bitblt.bltwidth;
2872 unsigned bits, bits_xor, bitmask;
2874 if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) {
2875 pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f;
2876 srcskipleft = pattern_x / 3;
2877 } else {
2878 srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07;
2879 pattern_x = srcskipleft * BX_CIRRUS_THIS bitblt.pixelwidth;
2881 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) {
2882 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
2883 if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
2884 color[0] = BX_CIRRUS_THIS control.shadow_reg0;
2885 color[1] = BX_CIRRUS_THIS control.reg[0x10];
2886 color[2] = BX_CIRRUS_THIS control.reg[0x12];
2887 color[3] = BX_CIRRUS_THIS control.reg[0x14];
2888 bits_xor = 0xff;
2889 } else {
2890 color[0] = BX_CIRRUS_THIS control.shadow_reg1;
2891 color[1] = BX_CIRRUS_THIS control.reg[0x11];
2892 color[2] = BX_CIRRUS_THIS control.reg[0x13];
2893 color[3] = BX_CIRRUS_THIS control.reg[0x15];
2894 bits_xor = 0x00;
2897 pattern_y = BX_CIRRUS_THIS bitblt.srcaddr & 0x07;
2898 for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) {
2899 dst = BX_CIRRUS_THIS bitblt.dst + pattern_x;
2900 bitmask = 0x80 >> srcskipleft;
2901 bits = BX_CIRRUS_THIS bitblt.src[pattern_y] ^ bits_xor;
2902 for (x = pattern_x; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) {
2903 if ((bitmask & 0xff) == 0) {
2904 bitmask = 0x80;
2905 bits = BX_CIRRUS_THIS bitblt.src[pattern_y] ^ bits_xor;
2907 if (bits & bitmask) {
2908 (*BX_CIRRUS_THIS bitblt.rop_handler)(
2909 dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1);
2911 dst += BX_CIRRUS_THIS bitblt.pixelwidth;
2912 bitmask >>= 1;
2914 pattern_y = (pattern_y + 1) & 7;
2915 BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch;
2917 return;
2918 } else {
2919 svga_colorexpand(work_colorexp,BX_CIRRUS_THIS bitblt.src,8*8,BX_CIRRUS_THIS bitblt.pixelwidth);
2920 BX_CIRRUS_THIS bitblt.src = work_colorexp;
2921 BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_COLOREXPAND;
2923 } else {
2924 if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) {
2925 pattern_pitch = 32;
2928 if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_PATTERNCOPY) {
2929 BX_ERROR(("PATTERNCOPY: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode));
2930 return;
2933 BX_DEBUG(("svga_cirrus: PATTERN COPY"));
2934 dst = BX_CIRRUS_THIS bitblt.dst;
2935 pattern_y = BX_CIRRUS_THIS bitblt.srcaddr & 0x07;
2936 src = (Bit8u *)BX_CIRRUS_THIS bitblt.src;
2937 for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) {
2938 srcc = src + pattern_y * pattern_pitch;
2939 dstc = dst + pattern_x;
2940 for (x = pattern_x; x < bltbytes; x += BX_CIRRUS_THIS bitblt.pixelwidth) {
2941 src2 = srcc + (x % patternbytes);
2942 (*BX_CIRRUS_THIS bitblt.rop_handler)(
2943 dstc, src2, 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1);
2944 dstc += BX_CIRRUS_THIS bitblt.pixelwidth;
2946 pattern_y = (pattern_y + 1) & 7;
2947 dst += BX_CIRRUS_THIS bitblt.dstpitch;
2951 void bx_svga_cirrus_c::svga_simplebitblt()
2953 Bit8u color[4];
2954 Bit8u work_colorexp[2048];
2955 Bit16u w, x, y;
2956 Bit8u *dst;
2957 unsigned bits, bits_xor, bitmask;
2958 int pattern_x, srcskipleft;
2960 if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) {
2961 pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f;
2962 srcskipleft = pattern_x / 3;
2963 } else {
2964 srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07;
2965 pattern_x = srcskipleft * BX_CIRRUS_THIS bitblt.pixelwidth;
2967 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) {
2968 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
2969 if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
2970 color[0] = BX_CIRRUS_THIS control.shadow_reg0;
2971 color[1] = BX_CIRRUS_THIS control.reg[0x10];
2972 color[2] = BX_CIRRUS_THIS control.reg[0x12];
2973 color[3] = BX_CIRRUS_THIS control.reg[0x14];
2974 bits_xor = 0xff;
2975 } else {
2976 color[0] = BX_CIRRUS_THIS control.shadow_reg1;
2977 color[1] = BX_CIRRUS_THIS control.reg[0x11];
2978 color[2] = BX_CIRRUS_THIS control.reg[0x13];
2979 color[3] = BX_CIRRUS_THIS control.reg[0x15];
2980 bits_xor = 0x00;
2983 for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) {
2984 dst = BX_CIRRUS_THIS bitblt.dst + pattern_x;
2985 bitmask = 0x80 >> srcskipleft;
2986 bits = *BX_CIRRUS_THIS bitblt.src++ ^ bits_xor;
2987 for (x = pattern_x; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) {
2988 if ((bitmask & 0xff) == 0) {
2989 bitmask = 0x80;
2990 bits = *BX_CIRRUS_THIS bitblt.src++ ^ bits_xor;
2992 if (bits & bitmask) {
2993 (*BX_CIRRUS_THIS bitblt.rop_handler)(
2994 dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1);
2996 dst += BX_CIRRUS_THIS bitblt.pixelwidth;
2997 bitmask >>= 1;
2999 BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch;
3001 return;
3002 } else {
3003 w = BX_CIRRUS_THIS bitblt.bltwidth / BX_CIRRUS_THIS bitblt.pixelwidth;
3004 for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) {
3005 svga_colorexpand(work_colorexp,BX_CIRRUS_THIS bitblt.src, w,
3006 BX_CIRRUS_THIS bitblt.pixelwidth);
3007 dst = BX_CIRRUS_THIS bitblt.dst + pattern_x;
3008 (*BX_CIRRUS_THIS bitblt.rop_handler)(
3009 dst, work_colorexp + pattern_x, 0, 0,
3010 BX_CIRRUS_THIS bitblt.bltwidth - pattern_x, 1);
3011 BX_CIRRUS_THIS bitblt.src += ((w + 7) >> 3);
3012 BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch;
3014 return;
3017 if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_BACKWARDS) {
3018 BX_ERROR(("SIMPLE BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode));
3019 return;
3022 BX_DEBUG(("svga_cirrus: BITBLT"));
3023 (*BX_CIRRUS_THIS bitblt.rop_handler)(
3024 BX_CIRRUS_THIS bitblt.dst, BX_CIRRUS_THIS bitblt.src,
3025 BX_CIRRUS_THIS bitblt.dstpitch, BX_CIRRUS_THIS bitblt.srcpitch,
3026 BX_CIRRUS_THIS bitblt.bltwidth, BX_CIRRUS_THIS bitblt.bltheight);
3029 void bx_svga_cirrus_c::svga_solidfill()
3031 Bit8u color[4];
3032 int x, y;
3033 Bit8u *dst;
3035 BX_DEBUG(("BLT: SOLIDFILL"));
3037 color[0] = BX_CIRRUS_THIS control.shadow_reg1;
3038 color[1] = BX_CIRRUS_THIS control.reg[0x11];
3039 color[2] = BX_CIRRUS_THIS control.reg[0x13];
3040 color[3] = BX_CIRRUS_THIS control.reg[0x15];
3042 for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) {
3043 dst = BX_CIRRUS_THIS bitblt.dst;
3044 for (x = 0; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) {
3045 (*BX_CIRRUS_THIS bitblt.rop_handler)(
3046 dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1);
3047 dst += BX_CIRRUS_THIS bitblt.pixelwidth;
3049 BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch;
3051 BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y,
3052 BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h);
3055 void bx_svga_cirrus_c::svga_patterncopy_memsrc()
3057 BX_INFO(("svga_patterncopy_memsrc() - not tested"));
3059 BX_CIRRUS_THIS bitblt.src = &BX_CIRRUS_THIS bitblt.memsrc[0];
3060 svga_patterncopy();
3061 BX_CIRRUS_THIS bitblt.memsrc_needed = 0;
3062 BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y,
3063 BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h);
3066 void bx_svga_cirrus_c::svga_simplebitblt_memsrc()
3068 Bit8u *srcptr = &BX_CIRRUS_THIS bitblt.memsrc[0];
3069 Bit8u work_colorexp[2048];
3070 Bit16u w;
3071 int pattern_x;
3073 BX_DEBUG(("svga_cirrus: BLT, cpu-to-video"));
3075 if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) {
3076 pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f;
3077 } else {
3078 pattern_x = (BX_CIRRUS_THIS control.reg[0x2f] & 0x07) * BX_CIRRUS_THIS bitblt.pixelwidth;
3080 if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) {
3081 if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_COLOREXPAND) {
3082 BX_ERROR(("cpu-to-video BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode));
3083 return;
3086 w = BX_CIRRUS_THIS bitblt.bltwidth / BX_CIRRUS_THIS bitblt.pixelwidth;
3087 svga_colorexpand(work_colorexp,srcptr,w,BX_CIRRUS_THIS bitblt.pixelwidth);
3088 (*BX_CIRRUS_THIS bitblt.rop_handler)(
3089 BX_CIRRUS_THIS bitblt.dst + pattern_x, work_colorexp + pattern_x, 0, 0,
3090 BX_CIRRUS_THIS bitblt.bltwidth - pattern_x, 1);
3091 } else {
3092 if (BX_CIRRUS_THIS bitblt.bltmode != 0) {
3093 BX_ERROR(("cpu-to-video BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode));
3094 return;
3096 (*BX_CIRRUS_THIS bitblt.rop_handler)(
3097 BX_CIRRUS_THIS bitblt.dst, srcptr, 0, 0,
3098 BX_CIRRUS_THIS bitblt.bltwidth, 1);
3102 void bx_svga_cirrus_c::svga_colorexpand_transp_memsrc()
3104 Bit8u *src = &BX_CIRRUS_THIS bitblt.memsrc[0];
3105 Bit8u color[4];
3106 int x, pattern_x, srcskipleft;
3107 Bit8u *dst;
3108 unsigned bits, bits_xor, bitmask;
3110 BX_DEBUG(("BLT, cpu-to-video, transparent"));
3112 if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) {
3113 pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f;
3114 srcskipleft = pattern_x / 3;
3115 } else {
3116 srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07;
3117 pattern_x = srcskipleft * BX_CIRRUS_THIS bitblt.pixelwidth;
3119 if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
3120 color[0] = BX_CIRRUS_THIS control.shadow_reg0;
3121 color[1] = BX_CIRRUS_THIS control.reg[0x10];
3122 color[2] = BX_CIRRUS_THIS control.reg[0x12];
3123 color[3] = BX_CIRRUS_THIS control.reg[0x14];
3124 bits_xor = 0xff;
3125 } else {
3126 color[0] = BX_CIRRUS_THIS control.shadow_reg1;
3127 color[1] = BX_CIRRUS_THIS control.reg[0x11];
3128 color[2] = BX_CIRRUS_THIS control.reg[0x13];
3129 color[3] = BX_CIRRUS_THIS control.reg[0x15];
3130 bits_xor = 0x00;
3133 dst = BX_CIRRUS_THIS bitblt.dst + pattern_x;
3134 bitmask = 0x80 >> srcskipleft;
3135 bits = *src++;
3136 for (x = pattern_x; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) {
3137 if ((bitmask & 0xff) == 0) {
3138 bitmask = 0x80;
3139 bits = *src++ ^ bits_xor;
3141 if (bits & bitmask) {
3142 (*BX_CIRRUS_THIS bitblt.rop_handler)(
3143 dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1);
3145 dst += BX_CIRRUS_THIS bitblt.pixelwidth;
3146 bitmask >>= 1;
3150 bx_bool // true if finished, false otherwise
3151 bx_svga_cirrus_c::svga_asyncbitblt_next()
3153 int count;
3154 int avail;
3156 if (BX_CIRRUS_THIS bitblt.bitblt_ptr == NULL) {
3157 BX_PANIC(("svga_asyncbitblt_next: unexpected call"));
3158 goto cleanup;
3161 if (BX_CIRRUS_THIS bitblt.memdst_needed > 0) {
3162 BX_CIRRUS_THIS bitblt.memdst_needed -= BX_CIRRUS_THIS bitblt.memdst_ptr - &BX_CIRRUS_THIS bitblt.memdst[0];
3163 avail = BX_MIN(CIRRUS_BLT_CACHESIZE, BX_CIRRUS_THIS bitblt.memdst_needed);
3164 BX_CIRRUS_THIS bitblt.memdst_ptr = &BX_CIRRUS_THIS bitblt.memdst[0];
3165 BX_CIRRUS_THIS bitblt.memdst_endptr = &BX_CIRRUS_THIS bitblt.memdst[avail];
3167 if (BX_CIRRUS_THIS bitblt.memsrc_needed <= 0 &&
3168 BX_CIRRUS_THIS bitblt.memdst_needed <= 0) {
3169 goto cleanup;
3173 (*BX_CIRRUS_THIS bitblt.bitblt_ptr)();
3175 if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) {
3176 BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch;
3177 BX_CIRRUS_THIS bitblt.memsrc_needed -= BX_CIRRUS_THIS bitblt.srcpitch;
3178 if (BX_CIRRUS_THIS bitblt.memsrc_needed <= 0) {
3179 BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y,
3180 BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h);
3181 if (BX_CIRRUS_THIS bitblt.memdst_needed <= 0) {
3182 goto cleanup;
3184 } else {
3185 count = BX_CIRRUS_THIS bitblt.memsrc_endptr - BX_CIRRUS_THIS bitblt.memsrc_ptr;
3186 memmove(&BX_CIRRUS_THIS bitblt.memsrc[0], BX_CIRRUS_THIS bitblt.memsrc_ptr, count);
3187 BX_CIRRUS_THIS bitblt.memsrc_ptr = &BX_CIRRUS_THIS bitblt.memsrc[count];
3191 return false;
3193 cleanup:
3194 svga_reset_bitblt();
3195 return true;
3198 /////////////////////////////////////////////////////////////////////////
3200 // Raster operations.
3202 /////////////////////////////////////////////////////////////////////////
3204 #define IMPLEMENT_FORWARD_BITBLT(name,opline) \
3205 static void bitblt_rop_fwd_##name( \
3206 Bit8u *dst,const Bit8u *src, \
3207 int dstpitch,int srcpitch, \
3208 int bltwidth,int bltheight) \
3210 int x,y; \
3211 dstpitch -= bltwidth; \
3212 srcpitch -= bltwidth; \
3213 for (y = 0; y < bltheight; y++) { \
3214 for (x = 0; x < bltwidth; x++) { \
3215 opline; \
3216 dst++; \
3217 src++; \
3219 dst += dstpitch; \
3220 src += srcpitch; \
3224 #define IMPLEMENT_BACKWARD_BITBLT(name,opline) \
3225 static void bitblt_rop_bkwd_##name( \
3226 Bit8u *dst,const Bit8u *src, \
3227 int dstpitch,int srcpitch, \
3228 int bltwidth,int bltheight) \
3230 int x,y; \
3231 dstpitch += bltwidth; \
3232 srcpitch += bltwidth; \
3233 for (y = 0; y < bltheight; y++) { \
3234 for (x = 0; x < bltwidth; x++) { \
3235 opline; \
3236 dst--; \
3237 src--; \
3239 dst += dstpitch; \
3240 src += srcpitch; \
3244 IMPLEMENT_FORWARD_BITBLT(0, *dst = 0)
3245 IMPLEMENT_FORWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst))
3246 IMPLEMENT_FORWARD_BITBLT(nop, (void)0)
3247 IMPLEMENT_FORWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
3248 IMPLEMENT_FORWARD_BITBLT(notdst, *dst = ~(*dst))
3249 IMPLEMENT_FORWARD_BITBLT(src, *dst = *src)
3250 IMPLEMENT_FORWARD_BITBLT(1, *dst = 0xff)
3251 IMPLEMENT_FORWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
3252 IMPLEMENT_FORWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
3253 IMPLEMENT_FORWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst))
3254 IMPLEMENT_FORWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
3255 IMPLEMENT_FORWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
3256 IMPLEMENT_FORWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
3257 IMPLEMENT_FORWARD_BITBLT(notsrc, *dst = (~(*src)))
3258 IMPLEMENT_FORWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
3259 IMPLEMENT_FORWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
3261 IMPLEMENT_BACKWARD_BITBLT(0, *dst = 0)
3262 IMPLEMENT_BACKWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst))
3263 IMPLEMENT_BACKWARD_BITBLT(nop, (void)0)
3264 IMPLEMENT_BACKWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
3265 IMPLEMENT_BACKWARD_BITBLT(notdst, *dst = ~(*dst))
3266 IMPLEMENT_BACKWARD_BITBLT(src, *dst = *src)
3267 IMPLEMENT_BACKWARD_BITBLT(1, *dst = 0xff)
3268 IMPLEMENT_BACKWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
3269 IMPLEMENT_BACKWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
3270 IMPLEMENT_BACKWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst))
3271 IMPLEMENT_BACKWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
3272 IMPLEMENT_BACKWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
3273 IMPLEMENT_BACKWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
3274 IMPLEMENT_BACKWARD_BITBLT(notsrc, *dst = (~(*src)))
3275 IMPLEMENT_BACKWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
3276 IMPLEMENT_BACKWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
3278 bx_cirrus_bitblt_rop_t bx_svga_cirrus_c::svga_get_fwd_rop_handler(Bit8u rop)
3280 bx_cirrus_bitblt_rop_t rop_handler = bitblt_rop_fwd_nop;
3282 switch (rop)
3284 case CIRRUS_ROP_0:
3285 rop_handler = bitblt_rop_fwd_0;
3286 break;
3287 case CIRRUS_ROP_SRC_AND_DST:
3288 rop_handler = bitblt_rop_fwd_src_and_dst;
3289 break;
3290 case CIRRUS_ROP_NOP:
3291 rop_handler = bitblt_rop_fwd_nop;
3292 break;
3293 case CIRRUS_ROP_SRC_AND_NOTDST:
3294 rop_handler = bitblt_rop_fwd_src_and_notdst;
3295 break;
3296 case CIRRUS_ROP_NOTDST:
3297 rop_handler = bitblt_rop_fwd_notdst;
3298 break;
3299 case CIRRUS_ROP_SRC:
3300 rop_handler = bitblt_rop_fwd_src;
3301 break;
3302 case CIRRUS_ROP_1:
3303 rop_handler = bitblt_rop_fwd_1;
3304 break;
3305 case CIRRUS_ROP_NOTSRC_AND_DST:
3306 rop_handler = bitblt_rop_fwd_notsrc_and_dst;
3307 break;
3308 case CIRRUS_ROP_SRC_XOR_DST:
3309 rop_handler = bitblt_rop_fwd_src_xor_dst;
3310 break;
3311 case CIRRUS_ROP_SRC_OR_DST:
3312 rop_handler = bitblt_rop_fwd_src_or_dst;
3313 break;
3314 case CIRRUS_ROP_NOTSRC_OR_NOTDST:
3315 rop_handler = bitblt_rop_fwd_notsrc_or_notdst;
3316 break;
3317 case CIRRUS_ROP_SRC_NOTXOR_DST:
3318 rop_handler = bitblt_rop_fwd_src_notxor_dst;
3319 break;
3320 case CIRRUS_ROP_SRC_OR_NOTDST:
3321 rop_handler = bitblt_rop_fwd_src_or_notdst;
3322 break;
3323 case CIRRUS_ROP_NOTSRC:
3324 rop_handler = bitblt_rop_fwd_notsrc;
3325 break;
3326 case CIRRUS_ROP_NOTSRC_OR_DST:
3327 rop_handler = bitblt_rop_fwd_notsrc_or_dst;
3328 break;
3329 case CIRRUS_ROP_NOTSRC_AND_NOTDST:
3330 rop_handler = bitblt_rop_fwd_notsrc_and_notdst;
3331 break;
3332 default:
3333 BX_ERROR(("unknown ROP %02x",rop));
3334 break;
3337 return rop_handler;
3340 bx_cirrus_bitblt_rop_t bx_svga_cirrus_c::svga_get_bkwd_rop_handler(Bit8u rop)
3342 bx_cirrus_bitblt_rop_t rop_handler = bitblt_rop_bkwd_nop;
3344 switch (rop)
3346 case CIRRUS_ROP_0:
3347 rop_handler = bitblt_rop_bkwd_0;
3348 break;
3349 case CIRRUS_ROP_SRC_AND_DST:
3350 rop_handler = bitblt_rop_bkwd_src_and_dst;
3351 break;
3352 case CIRRUS_ROP_NOP:
3353 rop_handler = bitblt_rop_bkwd_nop;
3354 break;
3355 case CIRRUS_ROP_SRC_AND_NOTDST:
3356 rop_handler = bitblt_rop_bkwd_src_and_notdst;
3357 break;
3358 case CIRRUS_ROP_NOTDST:
3359 rop_handler = bitblt_rop_bkwd_notdst;
3360 break;
3361 case CIRRUS_ROP_SRC:
3362 rop_handler = bitblt_rop_bkwd_src;
3363 break;
3364 case CIRRUS_ROP_1:
3365 rop_handler = bitblt_rop_bkwd_1;
3366 break;
3367 case CIRRUS_ROP_NOTSRC_AND_DST:
3368 rop_handler = bitblt_rop_bkwd_notsrc_and_dst;
3369 break;
3370 case CIRRUS_ROP_SRC_XOR_DST:
3371 rop_handler = bitblt_rop_bkwd_src_xor_dst;
3372 break;
3373 case CIRRUS_ROP_SRC_OR_DST:
3374 rop_handler = bitblt_rop_bkwd_src_or_dst;
3375 break;
3376 case CIRRUS_ROP_NOTSRC_OR_NOTDST:
3377 rop_handler = bitblt_rop_bkwd_notsrc_or_notdst;
3378 break;
3379 case CIRRUS_ROP_SRC_NOTXOR_DST:
3380 rop_handler = bitblt_rop_bkwd_src_notxor_dst;
3381 break;
3382 case CIRRUS_ROP_SRC_OR_NOTDST:
3383 rop_handler = bitblt_rop_bkwd_src_or_notdst;
3384 break;
3385 case CIRRUS_ROP_NOTSRC:
3386 rop_handler = bitblt_rop_bkwd_notsrc;
3387 break;
3388 case CIRRUS_ROP_NOTSRC_OR_DST:
3389 rop_handler = bitblt_rop_bkwd_notsrc_or_dst;
3390 break;
3391 case CIRRUS_ROP_NOTSRC_AND_NOTDST:
3392 rop_handler = bitblt_rop_bkwd_notsrc_and_notdst;
3393 break;
3394 default:
3395 BX_ERROR(("unknown ROP %02x",rop));
3396 break;
3399 return rop_handler;
3402 #endif // BX_SUPPORT_CLGD54XX