aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/cirrus_vga.c3
-rw-r--r--hw/jazz_led.c20
-rw-r--r--hw/omap_lcdc.c2
-rw-r--r--hw/pl110.c2
-rw-r--r--hw/pxa2xx_lcd.c2
-rw-r--r--hw/ssd0303.c2
-rw-r--r--hw/ssd0323.c2
-rw-r--r--hw/tcx.c5
-rw-r--r--hw/vga.c169
-rw-r--r--hw/vga_int.h1
-rw-r--r--hw/vmware_vga.c11
11 files changed, 206 insertions, 13 deletions
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 59bfdff56b..07e52b0c22 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3257,7 +3257,8 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
ds, vga_ram_base, vga_ram_offset, vga_ram_size);
cirrus_init_common(s, device_id, 1);
- graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
+ graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump,
+ s->text_update, s);
s->pci_dev = (PCIDevice *)d;
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index a0eea26b5a..d547138b94 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -285,6 +285,22 @@ static void jazz_led_screen_dump(void *opaque, const char *filename)
printf("jazz_led_screen_dump() not implemented\n");
}
+static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
+{
+ LedState *s = opaque;
+ char buf[2];
+
+ dpy_cursor(s->ds, -1, -1);
+ dpy_resize(s->ds, 2, 1);
+
+ /* TODO: draw the segments */
+ snprintf(buf, 2, "%02hhx\n", s->segments);
+ console_write_ch(chardata++, 0x00200100 | buf[0]);
+ console_write_ch(chardata++, 0x00200100 | buf[1]);
+
+ dpy_update(s->ds, 0, 0, 2, 1);
+}
+
void jazz_led_init(DisplayState *ds, target_phys_addr_t base)
{
LedState *s;
@@ -301,5 +317,7 @@ void jazz_led_init(DisplayState *ds, target_phys_addr_t base)
io = cpu_register_io_memory(0, led_read, led_write, s);
cpu_register_physical_memory(s->base, 1, io);
- graphic_console_init(ds, jazz_led_update_display, jazz_led_invalidate_display, jazz_led_screen_dump, s);
+ graphic_console_init(ds, jazz_led_update_display,
+ jazz_led_invalidate_display, jazz_led_screen_dump,
+ jazz_led_text_update, s);
}
diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c
index c79d244c1f..42174f7e0a 100644
--- a/hw/omap_lcdc.c
+++ b/hw/omap_lcdc.c
@@ -495,7 +495,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(target_phys_addr_t base, qemu_irq irq,
cpu_register_physical_memory(s->base, 0x100, iomemtype);
graphic_console_init(ds, omap_update_display,
- omap_invalidate_display, omap_screen_dump, s);
+ omap_invalidate_display, omap_screen_dump, NULL, s);
return s;
}
diff --git a/hw/pl110.c b/hw/pl110.c
index e5b2b2363b..7f450851a1 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -426,7 +426,7 @@ void *pl110_init(DisplayState *ds, uint32_t base, qemu_irq irq,
s->versatile = versatile;
s->irq = irq;
graphic_console_init(ds, pl110_update_display, pl110_invalidate_display,
- NULL, s);
+ NULL, NULL, s);
/* ??? Save/restore. */
return s;
}
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 5855435302..7203a3fb68 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -1002,7 +1002,7 @@ struct pxa2xx_lcdc_s *pxa2xx_lcdc_init(target_phys_addr_t base, qemu_irq irq,
cpu_register_physical_memory(base, 0x00100000, iomemtype);
graphic_console_init(ds, pxa2xx_update_display,
- pxa2xx_invalidate_display, pxa2xx_screen_dump, s);
+ pxa2xx_invalidate_display, pxa2xx_screen_dump, NULL, s);
switch (s->ds->depth) {
case 0:
diff --git a/hw/ssd0303.c b/hw/ssd0303.c
index 383a6232b5..daa92924a6 100644
--- a/hw/ssd0303.c
+++ b/hw/ssd0303.c
@@ -270,6 +270,6 @@ void ssd0303_init(DisplayState *ds, i2c_bus *bus, int address)
s->i2c.recv = ssd0303_recv;
s->i2c.send = ssd0303_send;
graphic_console_init(ds, ssd0303_update_display, ssd0303_invalidate_display,
- NULL, s);
+ NULL, NULL, s);
dpy_resize(s->ds, 96 * MAGNIFY, 16 * MAGNIFY);
}
diff --git a/hw/ssd0323.c b/hw/ssd0323.c
index 4706b05f4a..e2e619f076 100644
--- a/hw/ssd0323.c
+++ b/hw/ssd0323.c
@@ -280,7 +280,7 @@ void *ssd0323_init(DisplayState *ds, qemu_irq *cmd_p)
s = (ssd0323_state *)qemu_mallocz(sizeof(ssd0323_state));
s->ds = ds;
graphic_console_init(ds, ssd0323_update_display, ssd0323_invalidate_display,
- NULL, s);
+ NULL, NULL, s);
dpy_resize(s->ds, 128 * MAGNIFY, 64 * MAGNIFY);
s->col_end = 63;
s->row_end = 79;
diff --git a/hw/tcx.c b/hw/tcx.c
index afafa2aa25..f6d3d4c1c1 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -537,12 +537,13 @@ void tcx_init(DisplayState *ds, target_phys_addr_t addr, uint8_t *vram_base,
s->cplane_offset = vram_offset;
cpu_register_physical_memory(addr + 0x0a000000ULL, size, vram_offset);
graphic_console_init(s->ds, tcx24_update_display,
- tcx24_invalidate_display, tcx24_screen_dump, s);
+ tcx24_invalidate_display,
+ tcx24_screen_dump, NULL, s);
} else {
cpu_register_physical_memory(addr + 0x00300000ULL, TCX_THC_NREGS_8,
dummy_memory);
graphic_console_init(s->ds, tcx_update_display, tcx_invalidate_display,
- tcx_screen_dump, s);
+ tcx_screen_dump, NULL, s);
}
// NetBSD writes here even with 8-bit display
cpu_register_physical_memory(addr + 0x00301000ULL, TCX_THC_NREGS_24,
diff --git a/hw/vga.c b/hw/vga.c
index 70b7c6d451..99a31735a7 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1660,6 +1660,165 @@ static void vga_reset(VGAState *s)
s->graphic_mode = -1; /* force full update */
}
+#define TEXTMODE_X(x) ((x) % width)
+#define TEXTMODE_Y(x) ((x) / width)
+#define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
+ ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
+/* relay text rendering to the display driver
+ * instead of doing a full vga_update_display() */
+static void vga_update_text(void *opaque, console_ch_t *chardata)
+{
+ VGAState *s = (VGAState *) opaque;
+ int graphic_mode, i, cursor_offset, cursor_visible;
+ int cw, cheight, width, height, size, c_min, c_max;
+ uint32_t *src;
+ console_ch_t *dst, val;
+ char msg_buffer[80];
+ int full_update;
+ full_update = 0;
+
+ if (!(s->ar_index & 0x20)) {
+ graphic_mode = GMODE_BLANK;
+ } else {
+ graphic_mode = s->gr[6] & 1;
+ }
+ if (graphic_mode != s->graphic_mode) {
+ s->graphic_mode = graphic_mode;
+ full_update = 1;
+ }
+ if (s->last_width == -1) {
+ s->last_width = 0;
+ full_update = 1;
+ }
+
+ switch (graphic_mode) {
+ case GMODE_TEXT:
+ /* TODO: update palette */
+ full_update |= update_basic_params(s);
+
+ /* total width & height */
+ cheight = (s->cr[9] & 0x1f) + 1;
+ cw = 8;
+ if (!(s->sr[1] & 0x01))
+ cw = 9;
+ if (s->sr[1] & 0x08)
+ cw = 16; /* NOTE: no 18 pixel wide */
+ width = (s->cr[0x01] + 1);
+ if (s->cr[0x06] == 100) {
+ /* ugly hack for CGA 160x100x16 - explain me the logic */
+ height = 100;
+ } else {
+ height = s->cr[0x12] |
+ ((s->cr[0x07] & 0x02) << 7) |
+ ((s->cr[0x07] & 0x40) << 3);
+ height = (height + 1) / cheight;
+ }
+
+ size = (height * width);
+ if (size > CH_ATTR_SIZE) {
+ if (!full_update)
+ return;
+
+ sprintf(msg_buffer, "%i x %i Text mode", width, height);
+ break;
+ }
+
+ if (width != s->last_width || height != s->last_height ||
+ cw != s->last_cw || cheight != s->last_ch) {
+ s->last_scr_width = width * cw;
+ s->last_scr_height = height * cheight;
+ dpy_resize(s->ds, width, height);
+ s->last_width = width;
+ s->last_height = height;
+ s->last_ch = cheight;
+ s->last_cw = cw;
+ full_update = 1;
+ }
+
+ /* Update "hardware" cursor */
+ cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
+ if (cursor_offset != s->cursor_offset ||
+ s->cr[0xa] != s->cursor_start ||
+ s->cr[0xb] != s->cursor_end || full_update) {
+ cursor_visible = !(s->cr[0xa] & 0x20);
+ if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
+ dpy_cursor(s->ds,
+ TEXTMODE_X(cursor_offset),
+ TEXTMODE_Y(cursor_offset));
+ else
+ dpy_cursor(s->ds, -1, -1);
+ s->cursor_offset = cursor_offset;
+ s->cursor_start = s->cr[0xa];
+ s->cursor_end = s->cr[0xb];
+ }
+
+ src = (uint32_t *) s->vram_ptr + s->start_addr;
+ dst = chardata;
+
+ if (full_update) {
+ for (i = 0; i < size; src ++, dst ++, i ++)
+ console_write_ch(dst, VMEM2CHTYPE(*src));
+
+ dpy_update(s->ds, 0, 0, width, height);
+ } else {
+ c_max = 0;
+
+ for (i = 0; i < size; src ++, dst ++, i ++) {
+ console_write_ch(&val, VMEM2CHTYPE(*src));
+ if (*dst != val) {
+ *dst = val;
+ c_max = i;
+ break;
+ }
+ }
+ c_min = i;
+ for (; i < size; src ++, dst ++, i ++) {
+ console_write_ch(&val, VMEM2CHTYPE(*src));
+ if (*dst != val) {
+ *dst = val;
+ c_max = i;
+ }
+ }
+
+ if (c_min <= c_max) {
+ i = TEXTMODE_Y(c_min);
+ dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
+ }
+ }
+
+ return;
+ case GMODE_GRAPH:
+ if (!full_update)
+ return;
+
+ s->get_resolution(s, &width, &height);
+ sprintf(msg_buffer, "%i x %i Graphic mode", width, height);
+ break;
+ case GMODE_BLANK:
+ default:
+ if (!full_update)
+ return;
+
+ sprintf(msg_buffer, "VGA Blank mode");
+ break;
+ }
+
+ /* Display a message */
+ dpy_cursor(s->ds, -1, -1);
+ dpy_resize(s->ds, 60, 3);
+
+ for (dst = chardata, i = 0; i < 60 * 3; i ++)
+ console_write_ch(dst ++, ' ');
+
+ size = strlen(msg_buffer);
+ width = (60 - size) / 2;
+ dst = chardata + 60 + width;
+ for (i = 0; i < size; i ++)
+ console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
+
+ dpy_update(s->ds, 0, 0, 60, 3);
+}
+
static CPUReadMemoryFunc *vga_mem_read[3] = {
vga_mem_readb,
vga_mem_readw,
@@ -1830,6 +1989,7 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
s->update = vga_update_display;
s->invalidate = vga_invalidate_display;
s->screen_dump = vga_screen_dump;
+ s->text_update = vga_update_text;
}
/* used by both ISA and PCI */
@@ -1971,7 +2131,8 @@ int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
vga_init(s);
- graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
+ graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump,
+ s->text_update, s);
#ifdef CONFIG_BOCHS_VBE
/* XXX: use optimized standard vga accesses */
@@ -1995,7 +2156,8 @@ int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
vga_mm_init(s, vram_base, ctrl_base, it_shift);
- graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
+ graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump,
+ s->text_update, s);
#ifdef CONFIG_BOCHS_VBE
/* XXX: use optimized standard vga accesses */
@@ -2023,7 +2185,8 @@ int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
vga_init(s);
- graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
+ graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump,
+ s->text_update, s);
s->pci_dev = &d->dev;
diff --git a/hw/vga_int.h b/hw/vga_int.h
index a94162d332..5d11a7ac46 100644
--- a/hw/vga_int.h
+++ b/hw/vga_int.h
@@ -139,6 +139,7 @@
vga_hw_update_ptr update; \
vga_hw_invalidate_ptr invalidate; \
vga_hw_screen_dump_ptr screen_dump; \
+ vga_hw_text_update_ptr text_update; \
/* hardware mouse cursor support */ \
uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; \
void (*cursor_invalidate)(struct VGAState *s); \
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index bd96e6ba85..2b4c59d448 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -949,6 +949,14 @@ static void vmsvga_screen_dump(void *opaque, const char *filename)
}
}
+static void vmsvga_text_update(void *opaque, console_ch_t *chardata)
+{
+ struct vmsvga_state_s *s = (struct vmsvga_state_s *) opaque;
+
+ if (s->text_update)
+ s->text_update(opaque, chardata);
+}
+
#ifdef DIRECT_VRAM
static uint32_t vmsvga_vram_readb(void *opaque, target_phys_addr_t addr)
{
@@ -1101,7 +1109,8 @@ static void vmsvga_init(struct vmsvga_state_s *s, DisplayState *ds,
iomemtype);
graphic_console_init(ds, vmsvga_update_display,
- vmsvga_invalidate_display, vmsvga_screen_dump, s);
+ vmsvga_invalidate_display, vmsvga_screen_dump,
+ vmsvga_text_update, s);
#ifdef EMBED_STDVGA
vga_common_init((VGAState *) s, ds,