diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/cirrus_vga.c | 3 | ||||
-rw-r--r-- | hw/jazz_led.c | 20 | ||||
-rw-r--r-- | hw/omap_lcdc.c | 2 | ||||
-rw-r--r-- | hw/pl110.c | 2 | ||||
-rw-r--r-- | hw/pxa2xx_lcd.c | 2 | ||||
-rw-r--r-- | hw/ssd0303.c | 2 | ||||
-rw-r--r-- | hw/ssd0323.c | 2 | ||||
-rw-r--r-- | hw/tcx.c | 5 | ||||
-rw-r--r-- | hw/vga.c | 169 | ||||
-rw-r--r-- | hw/vga_int.h | 1 | ||||
-rw-r--r-- | hw/vmware_vga.c | 11 |
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; @@ -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, @@ -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, |