unsigned int r, g, b, color;
switch(ds->depth) {
-#if 0
case 8:
r = (rgba >> 16) & 0xff;
g = (rgba >> 8) & 0xff;
b = (rgba) & 0xff;
- color = (rgb_to_index[r] * 6 * 6) +
- (rgb_to_index[g] * 6) +
- (rgb_to_index[b]);
+ color = ((r >> 5) << 5 | (g >> 5) << 2 | (b >> 6));
break;
-#endif
case 15:
r = (rgba >> 16) & 0xff;
g = (rgba >> 8) & 0xff;
c++;
}
}
- free(s->cells);
+ qemu_free(s->cells);
s->cells = cells;
}
return !active_console->text_console;
}
+void set_color_table(DisplayState *ds)
+{
+ int i, j;
+ for(j = 0; j < 2; j++) {
+ for(i = 0; i < 8; i++) {
+ color_table[j][i] =
+ col_expand(ds, vga_get_color(ds, color_table_rgb[j][i]));
+ }
+ }
+}
+
CharDriverState *text_console_init(DisplayState *ds)
{
CharDriverState *chr;
TextConsole *s;
- int i,j;
static int color_inited;
chr = qemu_mallocz(sizeof(CharDriverState));
if (!color_inited) {
color_inited = 1;
- for(j = 0; j < 2; j++) {
- for(i = 0; i < 8; i++) {
- color_table[j][i] = col_expand(s->ds,
- vga_get_color(s->ds, color_table_rgb[j][i]));
- }
- }
+ set_color_table(ds);
}
s->y_displayed = 0;
s->y_base = 0;
*/
#include "vl.h"
#include "vga_int.h"
+#ifndef _WIN32
+#include <sys/mman.h>
+#endif
/*
* TODO:
int last_hw_cursor_y_end;
int real_vram_size; /* XXX: suppress that */
CPUWriteMemoryFunc **cirrus_linear_write;
+ unsigned long map_addr;
+ unsigned long map_end;
} CirrusVGAState;
typedef struct PCICirrusVGAState {
static uint8_t rop_to_index[256];
+void *shared_vram;
+
/***************************************
*
* prototypes.
static void cirrus_bitblt_reset(CirrusVGAState *s);
static void cirrus_update_memory_access(CirrusVGAState *s);
+static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val);
/***************************************
*
off_cur_end = off_cur + bytesperline;
off_cur &= TARGET_PAGE_MASK;
while (off_cur < off_cur_end) {
- cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
+ cpu_physical_memory_set_dirty(s->vram_offset +
+ (off_cur & s->cirrus_addr_mask));
off_cur += TARGET_PAGE_SIZE;
}
off_begin += off_pitch;
case 0x31: // BLT STATUS/START
cirrus_write_bitblt(s, reg_value);
break;
+
+ // Extension to allow BIOS to clear 16K VRAM bank in one operation
+ case 0xFE:
+ s->gr[reg_index] = reg_value; // Lower byte of value to be written
+ break;
+ case 0xFF: {
+ target_phys_addr_t addr;
+ for (addr = 0xa0000; addr < 0xa4000; addr += 2)
+ cirrus_vga_mem_writew(s, addr, (reg_value << 8) | s->gr[0xFE]);
+ }
+ break;
default:
#ifdef DEBUG_CIRRUS
printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
cirrus_linear_bitblt_writel,
};
+static void *set_vram_mapping(unsigned long begin, unsigned long end)
+{
+ xen_pfn_t *extent_start = NULL;
+ unsigned long nr_extents;
+ void *vram_pointer = NULL;
+ int i;
+
+ /* align begin and end address */
+ begin = begin & TARGET_PAGE_MASK;
+ end = begin + VGA_RAM_SIZE;
+ end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK;
+ nr_extents = (end - begin) >> TARGET_PAGE_BITS;
+
+ extent_start = malloc(sizeof(xen_pfn_t) * nr_extents);
+ if (extent_start == NULL) {
+ fprintf(stderr, "Failed malloc on set_vram_mapping\n");
+ return NULL;
+ }
+
+ memset(extent_start, 0, sizeof(xen_pfn_t) * nr_extents);
+
+ for (i = 0; i < nr_extents; i++)
+ extent_start[i] = (begin + i * TARGET_PAGE_SIZE) >> TARGET_PAGE_BITS;
+
+ if (set_mm_mapping(xc_handle, domid, nr_extents, 0, extent_start) < 0) {
+ fprintf(logfile, "Failed set_mm_mapping\n");
+ free(extent_start);
+ return NULL;
+ }
+
+ (void)xc_domain_pin_memory_cacheattr(
+ xc_handle, domid,
+ begin >> TARGET_PAGE_BITS,
+ end >> TARGET_PAGE_BITS,
+ XEN_DOMCTL_MEM_CACHEATTR_WB);
+
+ vram_pointer = xc_map_foreign_pages(xc_handle, domid,
+ PROT_READ|PROT_WRITE,
+ extent_start, nr_extents);
+ if (vram_pointer == NULL) {
+ fprintf(logfile, "xc_map_foreign_batch vgaram returned error %d\n",
+ errno);
+ free(extent_start);
+ return NULL;
+ }
+
+ memset(vram_pointer, 0, nr_extents * TARGET_PAGE_SIZE);
+
+#ifdef CONFIG_STUBDOM
+ xenfb_pv_display_start(vram_pointer);
+#endif
+
+ free(extent_start);
+
+ return vram_pointer;
+}
+
+static int unset_vram_mapping(unsigned long begin, unsigned long end,
+ void *mapping)
+{
+ xen_pfn_t *extent_start = NULL;
+ unsigned long nr_extents;
+ int i;
+
+ /* align begin and end address */
+
+ end = begin + VGA_RAM_SIZE;
+ begin = begin & TARGET_PAGE_MASK;
+ end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK;
+ nr_extents = (end - begin) >> TARGET_PAGE_BITS;
+
+ extent_start = malloc(sizeof(xen_pfn_t) * nr_extents);
+
+ if (extent_start == NULL) {
+ fprintf(stderr, "Failed malloc on set_mm_mapping\n");
+ return -1;
+ }
+
+ /* Drop our own references to the vram pages */
+ munmap(mapping, nr_extents * TARGET_PAGE_SIZE);
+
+ /* Now drop the guest's mappings */
+ memset(extent_start, 0, sizeof(xen_pfn_t) * nr_extents);
+ for (i = 0; i < nr_extents; i++)
+ extent_start[i] = (begin + (i * TARGET_PAGE_SIZE)) >> TARGET_PAGE_BITS;
+ unset_mm_mapping(xc_handle, domid, nr_extents, 0, extent_start);
+
+ free(extent_start);
+
+ return 0;
+}
+
/* Compute the memory access functions */
static void cirrus_update_memory_access(CirrusVGAState *s)
{
mode = s->gr[0x05] & 0x7;
if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
+ if (s->lfb_addr && s->lfb_end && !s->map_addr) {
+ void *vram_pointer, *old_vram;
+
+ vram_pointer = set_vram_mapping(s->lfb_addr,
+ s->lfb_end);
+ if (!vram_pointer)
+ fprintf(stderr, "NULL vram_pointer\n");
+ else {
+ old_vram = vga_update_vram((VGAState *)s, vram_pointer,
+ VGA_RAM_SIZE);
+ qemu_free(old_vram);
+ }
+ s->map_addr = s->lfb_addr;
+ s->map_end = s->lfb_end;
+ }
s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
s->cirrus_linear_write[1] = cirrus_linear_mem_writew;
s->cirrus_linear_write[2] = cirrus_linear_mem_writel;
} else {
generic_io:
+ if (s->lfb_addr && s->lfb_end && s->map_addr) {
+ void *old_vram;
+
+ old_vram = vga_update_vram((VGAState *)s, NULL, VGA_RAM_SIZE);
+
+ unset_vram_mapping(s->lfb_addr,
+ s->lfb_end,
+ old_vram);
+
+ s->map_addr = s->map_end = 0;
+ }
s->cirrus_linear_write[0] = cirrus_linear_writeb;
s->cirrus_linear_write[1] = cirrus_linear_writew;
s->cirrus_linear_write[2] = cirrus_linear_writel;
cirrus_mmio_writel,
};
+void cirrus_stop_acc(CirrusVGAState *s)
+{
+ if (s->map_addr){
+ int error;
+ s->map_addr = 0;
+ error = unset_vram_mapping(s->lfb_addr,
+ s->lfb_end, s->vram_ptr);
+ fprintf(stderr, "cirrus_stop_acc:unset_vram_mapping.\n");
+ }
+}
+
+void cirrus_restart_acc(CirrusVGAState *s)
+{
+ if (s->lfb_addr && s->lfb_end) {
+ void *vram_pointer, *old_vram;
+ fprintf(stderr, "cirrus_vga_load:re-enable vga acc.lfb_addr=0x%lx, lfb_end=0x%lx.\n",
+ s->lfb_addr, s->lfb_end);
+ vram_pointer = set_vram_mapping(s->lfb_addr ,s->lfb_end);
+ if (!vram_pointer){
+ fprintf(stderr, "cirrus_vga_load:NULL vram_pointer\n");
+ } else {
+ old_vram = vga_update_vram((VGAState *)s, vram_pointer,
+ VGA_RAM_SIZE);
+ qemu_free(old_vram);
+ s->map_addr = s->lfb_addr;
+ s->map_end = s->lfb_end;
+ }
+ }
+}
+
/* load/save state */
static void cirrus_vga_save(QEMUFile *f, void *opaque)
{
CirrusVGAState *s = opaque;
+ uint8_t vga_acc;
if (s->pci_dev)
pci_device_save(s->pci_dev, f);
qemu_put_be32s(f, &s->hw_cursor_y);
/* XXX: we do not save the bitblt state - we assume we do not save
the state when the blitter is active */
+
+ vga_acc = (!!s->map_addr);
+ qemu_put_8s(f, &vga_acc);
+ qemu_put_be64s(f, (uint64_t*)&s->lfb_addr);
+ qemu_put_be64s(f, (uint64_t*)&s->lfb_end);
+ qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE);
}
static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
{
CirrusVGAState *s = opaque;
+ uint8_t vga_acc = 0;
int ret;
if (version_id > 2)
qemu_get_be32s(f, &s->hw_cursor_x);
qemu_get_be32s(f, &s->hw_cursor_y);
+ qemu_get_8s(f, &vga_acc);
+ qemu_get_be64s(f, (uint64_t*)&s->lfb_addr);
+ qemu_get_be64s(f, (uint64_t*)&s->lfb_end);
+ qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE);
+ if (vga_acc){
+ cirrus_restart_acc(s);
+ }
+
/* force refresh */
s->graphic_mode = -1;
cirrus_update_bank_ptr(s, 0);
/* XXX: add byte swapping apertures */
cpu_register_physical_memory(addr, s->vram_size,
s->cirrus_linear_io_addr);
+ s->lfb_addr = addr;
+ s->lfb_end = addr + VGA_RAM_SIZE;
+
+ if (s->map_addr && (s->lfb_addr != s->map_addr) &&
+ (s->lfb_end != s->map_end))
+ fprintf(logfile, "cirrus vga map change while on lfb mode\n");
+
cpu_register_physical_memory(addr + 0x1000000, 0x400000,
s->cirrus_linear_bitblt_io_addr);
}
pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
+ pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
+ pci_conf[0x2d] = 0x58;
+ pci_conf[0x2e] = 0x01; /* subsystem device */
+ pci_conf[0x2f] = 0x00;
/* setup VGA */
s = &d->cirrus_vga;
* THE SOFTWARE.
*/
+#define get_base(p, s, b) do { \
+ if ((p) >= (s)->vram_ptr && (p) < (s)->vram_ptr + (s)->vram_size) \
+ (b) = (s)->vram_ptr; \
+ else if ((p) >= &(s)->cirrus_bltbuf[0] && \
+ (p) < &(s)->cirrus_bltbuf[CIRRUS_BLTBUFSIZE]) \
+ (b) = &(s)->cirrus_bltbuf[0]; \
+ else \
+ return; \
+} while(0)
+
+#define m(x) ((x) & s->cirrus_addr_mask)
+
static void
glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
+ uint8_t *dst_,const uint8_t *src_,
int dstpitch,int srcpitch,
int bltwidth,int bltheight)
{
int x,y;
+ uint32_t dst, src;
+ uint8_t *dst_base, *src_base;
+ get_base(dst_, s, dst_base);
+ get_base(src_, s, src_base);
+ dst = dst_ - dst_base;
+ src = src_ - src_base;
dstpitch -= bltwidth;
srcpitch -= bltwidth;
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
- ROP_OP(*dst, *src);
+ ROP_OP(*(dst_base + m(dst)), *(src_base + m(src)));
dst++;
src++;
}
static void
glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
- uint8_t *dst,const uint8_t *src,
+ uint8_t *dst_,const uint8_t *src_,
int dstpitch,int srcpitch,
int bltwidth,int bltheight)
{
int x,y;
+ uint32_t dst, src;
+ uint8_t *dst_base, *src_base;
+ get_base(dst_, s, dst_base);
+ get_base(src_, s, src_base);
+ dst = dst_ - dst_base;
+ src = src_ - src_base;
dstpitch += bltwidth;
srcpitch += bltwidth;
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
- ROP_OP(*dst, *src);
+ ROP_OP(*(dst_base + m(dst)), *(src_base + m(src)));
dst--;
src--;
}
#undef ROP_NAME
#undef ROP_OP
+
+#undef get_base
+#undef m
*/
#if DEPTH == 8
-#define PUTPIXEL() ROP_OP(d[0], col)
+#define PUTPIXEL() ROP_OP((dst_base + m(d))[0], col)
#elif DEPTH == 16
-#define PUTPIXEL() ROP_OP(((uint16_t *)d)[0], col);
+#define PUTPIXEL() ROP_OP(((uint16_t *)(dst_base + m(d)))[0], col);
#elif DEPTH == 24
-#define PUTPIXEL() ROP_OP(d[0], col); \
- ROP_OP(d[1], (col >> 8)); \
- ROP_OP(d[2], (col >> 16))
+#define PUTPIXEL() ROP_OP((dst_base + m(d))[0], col); \
+ ROP_OP((dst_base + m(d))[1], (col >> 8)); \
+ ROP_OP((dst_base + m(d))[2], (col >> 16))
#elif DEPTH == 32
-#define PUTPIXEL() ROP_OP(((uint32_t *)d)[0], col)
+#define PUTPIXEL() ROP_OP(((uint32_t *)(dst_base + m(d)))[0], col)
#else
#error unsupported DEPTH
#endif
static void
glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
+ (CirrusVGAState * s, uint8_t * dst_,
+ const uint8_t * src_,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
- uint8_t *d;
+ uint8_t *dst_base, *src_base;
+ uint32_t src, dst;
+ uint32_t d;
int x, y, pattern_y, pattern_pitch, pattern_x;
unsigned int col;
- const uint8_t *src1;
+ uint32_t src1;
#if DEPTH == 24
int skipleft = s->gr[0x2f] & 0x1f;
#else
int skipleft = (s->gr[0x2f] & 0x07) * (DEPTH / 8);
#endif
+ get_base(dst_, s, dst_base);
+ get_base(src_, s, src_base);
+ dst = dst_ - dst_base;
+ src = src_ - src_base;
#if DEPTH == 8
pattern_pitch = 8;
#elif DEPTH == 16
src1 = src + pattern_y * pattern_pitch;
for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
#if DEPTH == 8
- col = src1[pattern_x];
+ col = *(src_base + m(src1 + pattern_x));
pattern_x = (pattern_x + 1) & 7;
#elif DEPTH == 16
- col = ((uint16_t *)(src1 + pattern_x))[0];
+ col = *(uint16_t *)(src_base + m(src1 + pattern_x));
pattern_x = (pattern_x + 2) & 15;
#elif DEPTH == 24
{
- const uint8_t *src2 = src1 + pattern_x * 3;
+ const uint8_t *src2 = src_base + m(src1 + pattern_x * 3);
col = src2[0] | (src2[1] << 8) | (src2[2] << 16);
pattern_x = (pattern_x + 1) & 7;
}
#else
- col = ((uint32_t *)(src1 + pattern_x))[0];
+ col = *(uint32_t *)(src_base + m(src1 + pattern_x));
pattern_x = (pattern_x + 4) & 31;
#endif
PUTPIXEL();
/* NOTE: srcpitch is ignored */
static void
glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
+ (CirrusVGAState * s, uint8_t * dst_,
+ const uint8_t * src_,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
- uint8_t *d;
+ uint8_t *dst_base, *src_base;
+ uint32_t src, dst;
+ uint32_t d;
int x, y;
unsigned bits, bits_xor;
unsigned int col;
int dstskipleft = srcskipleft * (DEPTH / 8);
#endif
+ get_base(dst_, s, dst_base);
+ get_base(src_, s, src_base);
+ dst = dst_ - dst_base;
+ src = src_ - src_base;
if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
bits_xor = 0xff;
col = s->cirrus_blt_bgcol;
for(y = 0; y < bltheight; y++) {
bitmask = 0x80 >> srcskipleft;
- bits = *src++ ^ bits_xor;
+ bits = *(src_base + m(src++)) ^ bits_xor;
d = dst + dstskipleft;
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
- bits = *src++ ^ bits_xor;
+ bits = *(src_base + m(src++)) ^ bits_xor;
}
index = (bits & bitmask);
if (index) {
static void
glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
+ (CirrusVGAState * s, uint8_t * dst_,
+ const uint8_t * src_,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
+ uint8_t *dst_base, *src_base;
+ uint32_t src, dst;
uint32_t colors[2];
- uint8_t *d;
+ uint32_t d;
int x, y;
unsigned bits;
unsigned int col;
int srcskipleft = s->gr[0x2f] & 0x07;
int dstskipleft = srcskipleft * (DEPTH / 8);
+ get_base(dst_, s, dst_base);
+ get_base(src_, s, src_base);
+ dst = dst_ - dst_base;
+ src = src_ - src_base;
colors[0] = s->cirrus_blt_bgcol;
colors[1] = s->cirrus_blt_fgcol;
for(y = 0; y < bltheight; y++) {
bitmask = 0x80 >> srcskipleft;
- bits = *src++;
+ bits = *(src_base + m(src++));
d = dst + dstskipleft;
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
- bits = *src++;
+ bits = *(src_base + m(src++));
}
col = colors[!!(bits & bitmask)];
PUTPIXEL();
static void
glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
+ (CirrusVGAState * s, uint8_t * dst_,
+ const uint8_t * src_,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
- uint8_t *d;
+ uint8_t *dst_base, *src_base;
+ uint32_t src, dst;
+ uint32_t d;
int x, y, bitpos, pattern_y;
unsigned int bits, bits_xor;
unsigned int col;
int dstskipleft = srcskipleft * (DEPTH / 8);
#endif
+ get_base(dst_, s, dst_base);
+ get_base(src_, s, src_base);
+ dst = dst_ - dst_base;
+ src = src_ - src_base;
if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
bits_xor = 0xff;
col = s->cirrus_blt_bgcol;
pattern_y = s->cirrus_blt_srcaddr & 7;
for(y = 0; y < bltheight; y++) {
- bits = src[pattern_y] ^ bits_xor;
+ bits = *(src_base + m(src + pattern_y)) ^ bits_xor;
bitpos = 7 - srcskipleft;
d = dst + dstskipleft;
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
static void
glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
- (CirrusVGAState * s, uint8_t * dst,
- const uint8_t * src,
+ (CirrusVGAState * s, uint8_t * dst_,
+ const uint8_t * src_,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
+ uint8_t *dst_base, *src_base;
+ uint32_t src, dst;
uint32_t colors[2];
- uint8_t *d;
+ uint32_t d;
int x, y, bitpos, pattern_y;
unsigned int bits;
unsigned int col;
int srcskipleft = s->gr[0x2f] & 0x07;
int dstskipleft = srcskipleft * (DEPTH / 8);
+ get_base(dst_, s, dst_base);
+ get_base(src_, s, src_base);
+ dst = dst_ - dst_base;
+ src = src_ - src_base;
colors[0] = s->cirrus_blt_bgcol;
colors[1] = s->cirrus_blt_fgcol;
pattern_y = s->cirrus_blt_srcaddr & 7;
for(y = 0; y < bltheight; y++) {
- bits = src[pattern_y];
+ bits = *(src_base + m(src + pattern_y));
bitpos = 7 - srcskipleft;
d = dst + dstskipleft;
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
static void
glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
(CirrusVGAState *s,
- uint8_t *dst, int dst_pitch,
+ uint8_t *dst_, int dst_pitch,
int width, int height)
{
- uint8_t *d, *d1;
+ uint8_t *dst_base;
+ uint32_t dst;
+ uint32_t d, d1;
uint32_t col;
int x, y;
+ get_base(dst_, s, dst_base);
+ dst = dst_ - dst_base;
col = s->cirrus_blt_fgcol;
d1 = dst;
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
+typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
+
+static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS];
+
/*
* Text mode update
* Missing:
vga_draw_glyph8_func *vga_draw_glyph8;
vga_draw_glyph9_func *vga_draw_glyph9;
+ /* Disable dirty bit tracking */
+ xc_hvm_track_dirty_vram(xc_handle, domid, 0, 0, NULL);
+
+ if (s->ds->dpy_colourdepth != NULL && s->ds->depth != 0)
+ s->ds->dpy_colourdepth(s->ds, 0);
+ s->rgb_to_pixel =
+ rgb_to_pixel_dup_table[get_depth_index(s->ds)];
+
full_update |= update_palette16(s);
palette = s->last_palette;
cw != s->last_cw || cheight != s->last_ch) {
s->last_scr_width = width * cw;
s->last_scr_height = height * cheight;
- dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
+ dpy_resize(s->ds, s->last_scr_width, s->last_scr_height, s->last_scr_width * (s->ds->depth / 8));
s->last_width = width;
s->last_height = height;
s->last_ch = cheight;
vga_draw_line32_32bgr,
};
-typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
-
static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
rgb_to_pixel8_dup,
rgb_to_pixel15_dup,
}
}
+static inline int cmp_vram(VGAState *s, int offset, int n)
+{
+ long *vp, *sp;
+
+ if (s->vram_shadow == NULL)
+ return 1;
+ vp = (long *)(s->vram_ptr + offset);
+ sp = (long *)(s->vram_shadow + offset);
+ while ((n -= sizeof(*vp)) >= 0) {
+ if (*vp++ != *sp++) {
+ memcpy(sp - 1, vp - 1, n + sizeof(*vp));
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#ifdef USE_SSE2
+
+#include <signal.h>
+#include <setjmp.h>
+#include <emmintrin.h>
+
+int sse2_ok = 1;
+
+static inline unsigned int cpuid_edx(unsigned int op)
+{
+ unsigned int eax, edx;
+
+#ifdef __x86_64__
+#define __bx "rbx"
+#else
+#define __bx "ebx"
+#endif
+ __asm__("push %%"__bx"; cpuid; pop %%"__bx
+ : "=a" (eax), "=d" (edx)
+ : "0" (op)
+ : "cx");
+#undef __bx
+
+ return edx;
+}
+
+jmp_buf sse_jbuf;
+
+void intr(int sig)
+{
+ sse2_ok = 0;
+ longjmp(sse_jbuf, 1);
+}
+
+void check_sse2(void)
+{
+ /* Check 1: What does CPUID say? */
+ if ((cpuid_edx(1) & 0x4000000) == 0) {
+ sse2_ok = 0;
+ return;
+ }
+
+ /* Check 2: Can we use SSE2 in anger? */
+ signal(SIGILL, intr);
+ if (setjmp(sse_jbuf) == 0)
+ __asm__("xorps %xmm0,%xmm0\n");
+}
+
+int vram_dirty(VGAState *s, int offset, int n)
+{
+ __m128i *sp, *vp;
+
+ if (s->vram_shadow == NULL)
+ return 1;
+ if (sse2_ok == 0)
+ return cmp_vram(s, offset, n);
+ vp = (__m128i *)(s->vram_ptr + offset);
+ sp = (__m128i *)(s->vram_shadow + offset);
+ while ((n -= sizeof(*vp)) >= 0) {
+ if (_mm_movemask_epi8(_mm_cmpeq_epi8(*sp, *vp)) != 0xffff) {
+ while (n >= 0) {
+ _mm_store_si128(sp++, _mm_load_si128(vp++));
+ n -= sizeof(*vp);
+ }
+ return 1;
+ }
+ sp++;
+ vp++;
+ }
+ return 0;
+}
+#else /* !USE_SSE2 */
+int vram_dirty(VGAState *s, int offset, int n)
+{
+ return cmp_vram(s, offset, n);
+}
+
+void check_sse2(void)
+{
+}
+#endif /* !USE_SSE2 */
+
/*
* graphic modes
*/
static void vga_draw_graphic(VGAState *s, int full_update)
{
- int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
- int width, height, shift_control, line_offset, page0, page1, bwidth;
+ int y1, y, update, linesize, y_start, double_scan, mask, depth;
+ int width, height, shift_control, line_offset, bwidth, ds_depth, bits;
+ ram_addr_t page0, page1;
int disp_width, multi_scan, multi_run;
uint8_t *d;
uint32_t v, addr1, addr;
vga_draw_line_func *vga_draw_line;
-
+ ram_addr_t page_min, page_max;
+
full_update |= update_basic_params(s);
s->get_resolution(s, &width, &height);
disp_width = width;
+ ds_depth = s->ds->depth;
+ depth = s->get_bpp(s);
+ if (s->ds->dpy_colourdepth != NULL &&
+ (ds_depth != depth || !s->ds->shared_buf))
+ s->ds->dpy_colourdepth(s->ds, depth);
+ if (ds_depth != s->ds->depth) full_update = 1;
+
+ s->rgb_to_pixel =
+ rgb_to_pixel_dup_table[get_depth_index(s->ds)];
+
shift_control = (s->gr[0x05] >> 5) & 3;
double_scan = (s->cr[0x09] >> 7);
if (shift_control != 1) {
} else {
v = VGA_DRAW_LINE4;
}
+ bits = 4;
} else if (shift_control == 1) {
full_update |= update_palette16(s);
if (s->sr[0x01] & 8) {
} else {
v = VGA_DRAW_LINE2;
}
+ bits = 4;
} else {
switch(s->get_bpp(s)) {
default:
case 0:
full_update |= update_palette256(s);
v = VGA_DRAW_LINE8D2;
+ bits = 4;
break;
case 8:
full_update |= update_palette256(s);
v = VGA_DRAW_LINE8;
+ bits = 8;
break;
case 15:
v = VGA_DRAW_LINE15;
+ bits = 16;
break;
case 16:
v = VGA_DRAW_LINE16;
+ bits = 16;
break;
case 24:
v = VGA_DRAW_LINE24;
+ bits = 24;
break;
case 32:
v = VGA_DRAW_LINE32;
+ bits = 32;
break;
}
}
- vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
- if (disp_width != s->last_width ||
+ vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
+ if (s->line_offset != s->last_line_offset ||
+ disp_width != s->last_width ||
height != s->last_height) {
- dpy_resize(s->ds, disp_width, height);
+ dpy_resize(s->ds, disp_width, height, s->line_offset);
s->last_scr_width = disp_width;
s->last_scr_height = height;
s->last_width = disp_width;
s->last_height = height;
+ s->last_line_offset = s->line_offset;
full_update = 1;
}
- if (s->cursor_invalidate)
+ if (s->ds->shared_buf && (full_update || s->ds->data != s->vram_ptr + (s->start_addr * 4)))
+ s->ds->dpy_setdata(s->ds, s->vram_ptr + (s->start_addr * 4));
+ if (!s->ds->shared_buf && s->cursor_invalidate)
s->cursor_invalidate(s);
line_offset = s->line_offset;
printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
#endif
+
+ y = 0;
+
+ if (height - 1 > s->line_compare || multi_run || (s->cr[0x17] & 3) != 3
+ || !s->lfb_addr) {
+ /* Tricky things happen, disable dirty bit tracking */
+ xc_hvm_track_dirty_vram(xc_handle, domid, 0, 0, NULL);
+
+ for ( ; y < s->vram_size; y += TARGET_PAGE_SIZE)
+ if (vram_dirty(s, y, TARGET_PAGE_SIZE))
+ cpu_physical_memory_set_dirty(s->vram_offset + y);
+ } else {
+ /* Tricky things won't have any effect, i.e. we are in the very simple
+ * (and very usual) case of a linear buffer. */
+ unsigned long end;
+
+ for ( ; y < ((s->start_addr * 4) & TARGET_PAGE_MASK); y += TARGET_PAGE_SIZE)
+ /* We will not read that anyway. */
+ cpu_physical_memory_set_dirty(s->vram_offset + y);
+
+ if (y < (s->start_addr * 4)) {
+ /* start address not aligned on a page, track dirtyness by hand. */
+ if (vram_dirty(s, y, TARGET_PAGE_SIZE))
+ cpu_physical_memory_set_dirty(s->vram_offset + y);
+ y += TARGET_PAGE_SIZE;
+ }
+
+ /* use page table dirty bit tracking for the inner of the LFB */
+ end = s->start_addr * 4 + height * line_offset;
+ {
+ unsigned long npages = ((end & TARGET_PAGE_MASK) - y) / TARGET_PAGE_SIZE;
+ const int width = sizeof(unsigned long) * 8;
+ unsigned long bitmap[(npages + width - 1) / width];
+ int err;
+
+ if (!(err = xc_hvm_track_dirty_vram(xc_handle, domid,
+ (s->lfb_addr + y) / TARGET_PAGE_SIZE, npages, bitmap))) {
+ int i, j;
+ for (i = 0; i < sizeof(bitmap) / sizeof(*bitmap); i++) {
+ unsigned long map = bitmap[i];
+ for (j = i * width; map && j < npages; map >>= 1, j++)
+ if (map & 1)
+ cpu_physical_memory_set_dirty(s->vram_offset + y
+ + j * TARGET_PAGE_SIZE);
+ }
+ y += npages * TARGET_PAGE_SIZE;
+ } else {
+ /* ENODATA just means we have changed mode and will succeed
+ * next time */
+ if (err != -ENODATA)
+ fprintf(stderr, "track_dirty_vram(%lx, %lx) failed (%d)\n", s->lfb_addr + y, npages, err);
+ }
+ }
+
+ for ( ; y < s->vram_size && y < end; y += TARGET_PAGE_SIZE)
+ /* failed or end address not aligned on a page, track dirtyness by
+ * hand. */
+ if (vram_dirty(s, y, TARGET_PAGE_SIZE))
+ cpu_physical_memory_set_dirty(s->vram_offset + y);
+
+ for ( ; y < s->vram_size; y += TARGET_PAGE_SIZE)
+ /* We will not read that anyway. */
+ cpu_physical_memory_set_dirty(s->vram_offset + y);
+ }
+
addr1 = (s->start_addr * 4);
- bwidth = width * 4;
+ bwidth = (width * bits + 7) / 8;
y_start = -1;
- page_min = 0x7fffffff;
- page_max = -1;
+ page_min = 0;
+ page_max = 0;
d = s->ds->data;
linesize = s->ds->linesize;
y1 = 0;
if (update) {
if (y_start < 0)
y_start = y;
- if (page0 < page_min)
+ if (page_min == 0 || page0 < page_min)
page_min = page0;
- if (page1 > page_max)
+ if (page_max == 0 || page1 > page_max)
page_max = page1;
- vga_draw_line(s, d, s->vram_ptr + addr, width);
- if (s->cursor_draw_line)
- s->cursor_draw_line(s, d, y);
+ if (!s->ds->shared_buf) {
+ vga_draw_line(s, d, s->vram_ptr + addr, width);
+ if (s->cursor_draw_line)
+ s->cursor_draw_line(s, d, y);
+ }
} else {
if (y_start >= 0) {
/* flush to display */
return;
if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
return;
+
+ /* Disable dirty bit tracking */
+ xc_hvm_track_dirty_vram(xc_handle, domid, 0, 0, NULL);
+
+ s->rgb_to_pixel =
+ rgb_to_pixel_dup_table[get_depth_index(s->ds)];
if (s->ds->depth == 8)
val = s->rgb_to_pixel(0, 0, 0);
else
if (s->ds->depth == 0) {
/* nothing to do */
} else {
- s->rgb_to_pixel =
- rgb_to_pixel_dup_table[get_depth_index(s->ds)];
-
full_update = 0;
if (!(s->ar_index & 0x20)) {
graphic_mode = GMODE_BLANK;
static void vga_save(QEMUFile *f, void *opaque)
{
VGAState *s = opaque;
+ uint32_t vram_size;
+#ifdef CONFIG_BOCHS_VBE
int i;
+#endif
if (s->pci_dev)
pci_device_save(s->pci_dev, f);
#else
qemu_put_byte(f, 0);
#endif
+ vram_size = s->vram_size;
+ qemu_put_be32s(f, &vram_size);
+ qemu_put_buffer(f, s->vram_ptr, s->vram_size);
}
static int vga_load(QEMUFile *f, void *opaque, int version_id)
{
VGAState *s = opaque;
- int is_vbe, i, ret;
+ int is_vbe, ret;
+ uint32_t vram_size;
+#ifdef CONFIG_BOCHS_VBE
+ int i;
+#endif
- if (version_id > 2)
+ if (version_id > 3)
return -EINVAL;
if (s->pci_dev && version_id >= 2) {
if (is_vbe)
return -EINVAL;
#endif
+ if (version_id >= 3) {
+ /* people who restore old images may be lucky ... */
+ qemu_get_be32s(f, &vram_size);
+ if (vram_size != s->vram_size)
+ return -EINVAL;
+ qemu_get_buffer(f, s->vram_ptr, s->vram_size);
+ }
/* force refresh */
s->graphic_mode = -1;
}
}
+/* do the same job as vgabios before vgabios get ready - yeah */
+void vga_bios_init(VGAState *s)
+{
+ uint8_t palette_model[192] = {
+ 0, 0, 0, 0, 0, 170, 0, 170,
+ 0, 0, 170, 170, 170, 0, 0, 170,
+ 0, 170, 170, 85, 0, 170, 170, 170,
+ 85, 85, 85, 85, 85, 255, 85, 255,
+ 85, 85, 255, 255, 255, 85, 85, 255,
+ 85, 255, 255, 255, 85, 255, 255, 255,
+ 0, 21, 0, 0, 21, 42, 0, 63,
+ 0, 0, 63, 42, 42, 21, 0, 42,
+ 21, 42, 42, 63, 0, 42, 63, 42,
+ 0, 21, 21, 0, 21, 63, 0, 63,
+ 21, 0, 63, 63, 42, 21, 21, 42,
+ 21, 63, 42, 63, 21, 42, 63, 63,
+ 21, 0, 0, 21, 0, 42, 21, 42,
+ 0, 21, 42, 42, 63, 0, 0, 63,
+ 0, 42, 63, 42, 0, 63, 42, 42,
+ 21, 0, 21, 21, 0, 63, 21, 42,
+ 21, 21, 42, 63, 63, 0, 21, 63,
+ 0, 63, 63, 42, 21, 63, 42, 63,
+ 21, 21, 0, 21, 21, 42, 21, 63,
+ 0, 21, 63, 42, 63, 21, 0, 63,
+ 21, 42, 63, 63, 0, 63, 63, 42,
+ 21, 21, 21, 21, 21, 63, 21, 63,
+ 21, 21, 63, 63, 63, 21, 21, 63,
+ 21, 63, 63, 63, 21, 63, 63, 63
+ };
+
+ s->latch = 0;
+
+ s->sr_index = 3;
+ s->sr[0] = 3;
+ s->sr[1] = 0;
+ s->sr[2] = 3;
+ s->sr[3] = 0;
+ s->sr[4] = 2;
+ s->sr[5] = 0;
+ s->sr[6] = 0;
+ s->sr[7] = 0;
+
+ s->gr_index = 5;
+ s->gr[0] = 0;
+ s->gr[1] = 0;
+ s->gr[2] = 0;
+ s->gr[3] = 0;
+ s->gr[4] = 0;
+ s->gr[5] = 16;
+ s->gr[6] = 14;
+ s->gr[7] = 15;
+ s->gr[8] = 255;
+
+ /* changed by out 0x03c0 */
+ s->ar_index = 32;
+ s->ar[0] = 0;
+ s->ar[1] = 1;
+ s->ar[2] = 2;
+ s->ar[3] = 3;
+ s->ar[4] = 4;
+ s->ar[5] = 5;
+ s->ar[6] = 6;
+ s->ar[7] = 7;
+ s->ar[8] = 8;
+ s->ar[9] = 9;
+ s->ar[10] = 10;
+ s->ar[11] = 11;
+ s->ar[12] = 12;
+ s->ar[13] = 13;
+ s->ar[14] = 14;
+ s->ar[15] = 15;
+ s->ar[16] = 12;
+ s->ar[17] = 0;
+ s->ar[18] = 15;
+ s->ar[19] = 8;
+ s->ar[20] = 0;
+
+ s->ar_flip_flop = 1;
+
+ s->cr_index = 15;
+ s->cr[0] = 95;
+ s->cr[1] = 79;
+ s->cr[2] = 80;
+ s->cr[3] = 130;
+ s->cr[4] = 85;
+ s->cr[5] = 129;
+ s->cr[6] = 191;
+ s->cr[7] = 31;
+ s->cr[8] = 0;
+ s->cr[9] = 79;
+ s->cr[10] = 14;
+ s->cr[11] = 15;
+ s->cr[12] = 0;
+ s->cr[13] = 0;
+ s->cr[14] = 5;
+ s->cr[15] = 160;
+ s->cr[16] = 156;
+ s->cr[17] = 142;
+ s->cr[18] = 143;
+ s->cr[19] = 40;
+ s->cr[20] = 31;
+ s->cr[21] = 150;
+ s->cr[22] = 185;
+ s->cr[23] = 163;
+ s->cr[24] = 255;
+
+ s->msr = 103;
+ s->fcr = 0;
+ s->st00 = 0;
+ s->st01 = 0;
+
+ /* dac_* & palette will be initialized by os through out 0x03c8 &
+ * out 0c03c9(1:3) */
+ s->dac_state = 0;
+ s->dac_sub_index = 0;
+ s->dac_read_index = 0;
+ s->dac_write_index = 16;
+ s->dac_cache[0] = 255;
+ s->dac_cache[1] = 255;
+ s->dac_cache[2] = 255;
+
+ /* palette */
+ memcpy(s->palette, palette_model, 192);
+
+ s->bank_offset = 0;
+ s->graphic_mode = -1;
+
+ /* TODO: add vbe support if enabled */
+}
+
+/* when used on xen environment, the vga_ram_base is not used */
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
unsigned long vga_ram_offset, int vga_ram_size)
{
vga_reset(s);
- s->vram_ptr = vga_ram_base;
+ check_sse2();
+ s->vram_shadow = qemu_malloc(vga_ram_size+TARGET_PAGE_SIZE+1);
+ if (s->vram_shadow == NULL)
+ fprintf(stderr, "Cannot allocate %d bytes for VRAM shadow, "
+ "mouse will be slow\n", vga_ram_size);
+ s->vram_shadow = (uint8_t *)((long)(s->vram_shadow + TARGET_PAGE_SIZE - 1)
+ & ~(TARGET_PAGE_SIZE - 1));
+
+ /* Video RAM must be 128-bit aligned for SSE optimizations later */
+ /* and page-aligned for PVFB memory sharing */
+ s->vram_ptr = s->vram_alloc = qemu_memalign(TARGET_PAGE_SIZE, vga_ram_size);
+
s->vram_offset = vga_ram_offset;
s->vram_size = vga_ram_size;
s->ds = ds;
+ ds->palette = s->last_palette;
s->get_bpp = vga_get_bpp;
s->get_offsets = vga_get_offsets;
s->get_resolution = vga_get_resolution;
graphic_console_init(s->ds, vga_update_display, vga_invalidate_display,
vga_screen_dump, s);
+
+ vga_bios_init(s);
}
/* used by both ISA and PCI */
{
int vga_io_memory;
- register_savevm("vga", 0, 2, vga_save, vga_load, s);
+ register_savevm("vga", 0, 3, vga_save, vga_load, s);
register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
return 0;
}
+void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size)
+{
+ uint8_t *old_pointer;
+
+ if (s->vram_size != vga_ram_size) {
+ fprintf(stderr, "No support to change vga_ram_size\n");
+ return NULL;
+ }
+
+ if (!vga_ram_base) {
+ vga_ram_base = qemu_memalign(TARGET_PAGE_SIZE, vga_ram_size + TARGET_PAGE_SIZE + 1);
+ if (!vga_ram_base) {
+ fprintf(stderr, "reallocate error\n");
+ return NULL;
+ }
+ }
+
+ /* XXX lock needed? */
+ old_pointer = s->vram_alloc;
+ s->vram_alloc = vga_ram_base;
+ vga_ram_base = (uint8_t *)((long)(vga_ram_base + 15) & ~15L);
+ memcpy(vga_ram_base, s->vram_ptr, vga_ram_size);
+ s->vram_ptr = vga_ram_base;
+
+ return old_pointer;
+}
+
/********************************************************/
/* vga screen dump */
{
}
-static void vga_save_dpy_resize(DisplayState *s, int w, int h)
+static void vga_save_dpy_resize(DisplayState *s, int w, int h, int linesize)
{
s->linesize = w * 4;
s->data = qemu_malloc(h * s->linesize);
#define ST01_DISP_ENABLE 0x01
/* bochs VBE support */
-#define CONFIG_BOCHS_VBE
+//#define CONFIG_BOCHS_VBE
#define VBE_DISPI_MAX_XRES 1600
#define VBE_DISPI_MAX_YRES 1200
#define VGA_MAX_HEIGHT 2048
#define VGA_STATE_COMMON \
+ uint8_t *vram_alloc; \
uint8_t *vram_ptr; \
+ uint8_t *vram_shadow; \
unsigned long vram_offset; \
unsigned int vram_size; \
unsigned long bios_offset; \
unsigned int bios_size; \
+ unsigned long lfb_addr; \
+ unsigned long lfb_end; \
PCIDevice *pci_dev; \
uint32_t latch; \
uint8_t sr_index; \
uint32_t line_compare; \
uint32_t start_addr; \
uint32_t plane_updated; \
+ uint32_t last_line_offset; \
uint8_t last_cw, last_ch; \
uint32_t last_width, last_height; /* in chars or pixels */ \
uint32_t last_scr_width, last_scr_height; /* in pixels */ \
unsigned int color0, unsigned int color1,
unsigned int color_xor);
+void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size);
extern const uint8_t sr_mask[8];
extern const uint8_t gr_mask[16];