X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/6ea314d91439741e95772dfbab98b4135e04bebb..99918cec1968b94c8ac3afe51b2a34e5c78c81b3:/console.c diff --git a/console.c b/console.c index 9bbef593b9..6a463f5918 100644 --- a/console.c +++ b/console.c @@ -115,6 +115,7 @@ typedef enum { /* ??? This is mis-named. It is used for both text and graphical consoles. */ struct TextConsole { + int index; console_type_t console_type; DisplayState *ds; /* Graphic console state. */ @@ -137,6 +138,7 @@ struct TextConsole { TextAttributes t_attrib; /* currently active text attributes */ TextCell *cells; int text_x[2], text_y[2], cursor_invalidate; + int echo; int update_x0; int update_y0; @@ -154,6 +156,7 @@ struct TextConsole { QEMUTimer *kbd_timer; }; +static DisplayState *display_state; static TextConsole *active_console; static TextConsole *consoles[MAX_CONSOLES]; static int nb_consoles = 0; @@ -166,21 +169,32 @@ void vga_hw_update(void) void vga_hw_invalidate(void) { - if (active_console->hw_invalidate) + if (active_console && active_console->hw_invalidate) active_console->hw_invalidate(active_console->hw); } void vga_hw_screen_dump(const char *filename) { TextConsole *previous_active_console; + bool cswitch; previous_active_console = active_console; - active_console = consoles[0]; + cswitch = previous_active_console && previous_active_console->index != 0; + /* There is currently no way of specifying which screen we want to dump, so always dump the first one. */ - if (consoles[0]->hw_screen_dump) - consoles[0]->hw_screen_dump(consoles[0]->hw, filename); - active_console = previous_active_console; + if (cswitch) { + console_select(0); + } + if (consoles[0] && consoles[0]->hw_screen_dump) { + consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch); + } else { + error_report("screen dump not implemented"); + } + + if (cswitch) { + console_select(previous_active_console->index); + } } void vga_hw_text_update(console_ch_t *chardata) @@ -341,6 +355,7 @@ static const uint32_t dmask4[4] = { static uint32_t color_table[2][8]; +#ifndef CONFIG_CURSES enum color_names { COLOR_BLACK = 0, COLOR_RED = 1, @@ -351,6 +366,7 @@ enum color_names { COLOR_CYAN = 6, COLOR_WHITE = 7 }; +#endif static const uint32_t color_table_rgb[2][8] = { { /* dark */ @@ -459,7 +475,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, font_data = *font_ptr++; if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) { - font_data = 0xFFFF; + font_data = 0xFF; } ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol; ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; @@ -472,7 +488,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, font_data = *font_ptr++; if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) { - font_data = 0xFFFF; + font_data = 0xFF; } ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol; ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol; @@ -485,7 +501,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, for(i = 0; i < FONT_HEIGHT; i++) { font_data = *font_ptr++; if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) { - font_data = 0xFFFF; + font_data = 0xFF; } ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; @@ -514,7 +530,7 @@ static void text_console_resize(TextConsole *s) if (s->width < w1) w1 = s->width; - cells = qemu_malloc(s->width * s->total_height * sizeof(TextCell)); + cells = g_malloc(s->width * s->total_height * sizeof(TextCell)); for(y = 0; y < s->total_height; y++) { c = &cells[y * s->width]; if (w1 > 0) { @@ -529,7 +545,7 @@ static void text_console_resize(TextConsole *s) c++; } } - qemu_free(s->cells); + g_free(s->cells); s->cells = cells; } @@ -828,7 +844,6 @@ static void console_clear_xy(TextConsole *s, int x, int y) TextCell *c = &s->cells[y1 * s->width + x]; c->ch = ' '; c->t_attrib = s->t_attrib_default; - c++; update_xy(s, x, y); } @@ -1002,16 +1017,17 @@ static void console_putchar(TextConsole *s, int ch) console_clear_xy(s, x, y); } } - break; + break; } + break; case 'K': switch (s->esc_params[0]) { case 0: - /* clear to eol */ - for(x = s->x; x < s->width; x++) { + /* clear to eol */ + for(x = s->x; x < s->width; x++) { console_clear_xy(s, x, s->y); - } - break; + } + break; case 1: /* clear from beginning of line */ for (x = 0; x <= s->x; x++) { @@ -1023,12 +1039,12 @@ static void console_putchar(TextConsole *s, int ch) for(x = 0; x < s->width; x++) { console_clear_xy(s, x, s->y); } - break; - } + break; + } break; case 'm': - console_handle_escape(s); - break; + console_handle_escape(s); + break; case 'n': /* report cursor position */ /* TODO: send ESC[row;colR */ @@ -1060,8 +1076,10 @@ void console_select(unsigned int index) if (index >= MAX_CONSOLES) return; - active_console->g_width = ds_get_width(active_console->ds); - active_console->g_height = ds_get_height(active_console->ds); + if (active_console) { + active_console->g_width = ds_get_width(active_console->ds); + active_console->g_height = ds_get_height(active_console->ds); + } s = consoles[index]; if (s) { DisplayState *ds = s->ds; @@ -1099,40 +1117,25 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len) return len; } -static void console_send_event(CharDriverState *chr, int event) -{ - TextConsole *s = chr->opaque; - int i; - - if (event == CHR_EVENT_FOCUS) { - for(i = 0; i < nb_consoles; i++) { - if (consoles[i] == s) { - console_select(i); - break; - } - } - } -} - static void kbd_send_chars(void *opaque) { TextConsole *s = opaque; int len; uint8_t buf[16]; - len = qemu_chr_can_read(s->chr); + len = qemu_chr_be_can_write(s->chr); if (len > s->out_fifo.count) len = s->out_fifo.count; if (len > 0) { if (len > sizeof(buf)) len = sizeof(buf); qemu_fifo_read(&s->out_fifo, buf, len); - qemu_chr_read(s->chr, buf, len); + qemu_chr_be_write(s->chr, buf, len); } /* characters are pending: we send them a bit later (XXX: horrible, should change char device API) */ if (s->out_fifo.count > 0) { - qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1); + qemu_mod_timer(s->kbd_timer, qemu_get_clock_ms(rt_clock) + 1); } } @@ -1175,8 +1178,14 @@ void kbd_put_keysym(int keysym) *q++ = '\033'; *q++ = '['; *q++ = keysym & 0xff; + } else if (s->echo && (keysym == '\r' || keysym == '\n')) { + console_puts(s->chr, (const uint8_t *) "\r", 1); + *q++ = '\n'; } else { - *q++ = keysym; + *q++ = keysym; + } + if (s->echo) { + console_puts(s->chr, buf, q - buf); } if (s->chr->chr_read) { qemu_fifo_write(&s->out_fifo, buf, q - buf); @@ -1243,7 +1252,7 @@ static TextConsole *new_console(DisplayState *ds, console_type_t console_type) if (nb_consoles >= MAX_CONSOLES) return NULL; - s = qemu_mallocz(sizeof(TextConsole)); + s = g_malloc0(sizeof(TextConsole)); if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) && (console_type == GRAPHIC_CONSOLE))) { active_console = s; @@ -1251,6 +1260,7 @@ static TextConsole *new_console(DisplayState *ds, console_type_t console_type) s->ds = ds; s->console_type = console_type; if (console_type != GRAPHIC_CONSOLE) { + s->index = nb_consoles; consoles[nb_consoles++] = s; } else { /* HACK: Put graphical consoles before text consoles. */ @@ -1258,13 +1268,135 @@ static TextConsole *new_console(DisplayState *ds, console_type_t console_type) if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE) break; consoles[i] = consoles[i - 1]; + consoles[i]->index = i; } + s->index = i; consoles[i] = s; nb_consoles++; } return s; } +static DisplaySurface* defaultallocator_create_displaysurface(int width, int height) +{ + DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface)); + + int linesize = width * 4; + qemu_alloc_display(surface, width, height, linesize, + qemu_default_pixelformat(32), 0); + return surface; +} + +static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface, + int width, int height) +{ + int linesize = width * 4; + qemu_alloc_display(surface, width, height, linesize, + qemu_default_pixelformat(32), 0); + return surface; +} + +void qemu_alloc_display(DisplaySurface *surface, int width, int height, + int linesize, PixelFormat pf, int newflags) +{ + void *data; + surface->width = width; + surface->height = height; + surface->linesize = linesize; + surface->pf = pf; + if (surface->flags & QEMU_ALLOCATED_FLAG) { + data = g_realloc(surface->data, + surface->linesize * surface->height); + } else { + data = g_malloc(surface->linesize * surface->height); + } + surface->data = (uint8_t *)data; + surface->flags = newflags | QEMU_ALLOCATED_FLAG; +#ifdef HOST_WORDS_BIGENDIAN + surface->flags |= QEMU_BIG_ENDIAN_FLAG; +#endif +} + +DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, + int linesize, uint8_t *data) +{ + DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface)); + + surface->width = width; + surface->height = height; + surface->linesize = linesize; + surface->pf = qemu_default_pixelformat(bpp); +#ifdef HOST_WORDS_BIGENDIAN + surface->flags = QEMU_BIG_ENDIAN_FLAG; +#endif + surface->data = data; + + return surface; +} + +static void defaultallocator_free_displaysurface(DisplaySurface *surface) +{ + if (surface == NULL) + return; + if (surface->flags & QEMU_ALLOCATED_FLAG) + g_free(surface->data); + g_free(surface); +} + +static struct DisplayAllocator default_allocator = { + defaultallocator_create_displaysurface, + defaultallocator_resize_displaysurface, + defaultallocator_free_displaysurface +}; + +static void dumb_display_init(void) +{ + DisplayState *ds = g_malloc0(sizeof(DisplayState)); + int width = 640; + int height = 480; + + ds->allocator = &default_allocator; + if (is_fixedsize_console()) { + width = active_console->g_width; + height = active_console->g_height; + } + ds->surface = qemu_create_displaysurface(ds, width, height); + register_displaystate(ds); +} + +/***********************************************************/ +/* register display */ + +void register_displaystate(DisplayState *ds) +{ + DisplayState **s; + s = &display_state; + while (*s != NULL) + s = &(*s)->next; + ds->next = NULL; + *s = ds; +} + +DisplayState *get_displaystate(void) +{ + if (!display_state) { + dumb_display_init (); + } + return display_state; +} + +DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da) +{ + if(ds->allocator == &default_allocator) { + DisplaySurface *surf; + surf = da->create_displaysurface(ds_get_width(ds), ds_get_height(ds)); + defaultallocator_free_displaysurface(ds->surface); + ds->surface = surf; + ds->allocator = da; + } + return ds->allocator; +} + DisplayState *graphic_console_init(vga_hw_update_ptr update, vga_hw_invalidate_ptr invalidate, vga_hw_screen_dump_ptr screen_dump, @@ -1274,14 +1406,14 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update, TextConsole *s; DisplayState *ds; - ds = (DisplayState *) qemu_mallocz(sizeof(DisplayState)); + ds = (DisplayState *) g_malloc0(sizeof(DisplayState)); ds->allocator = &default_allocator; ds->surface = qemu_create_displaysurface(ds, 640, 480); s = new_console(ds, GRAPHIC_CONSOLE); if (s == NULL) { qemu_free_displaysurface(ds); - qemu_free(ds); + g_free(ds); return NULL; } s->hw_update = update; @@ -1315,45 +1447,25 @@ void console_color_init(DisplayState *ds) } } -static int n_text_consoles; -static CharDriverState *text_consoles[128]; -static QemuOpts *text_console_opts[128]; +static void text_console_set_echo(CharDriverState *chr, bool echo) +{ + TextConsole *s = chr->opaque; + + s->echo = echo; +} -static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpts *opts) +static void text_console_do_init(CharDriverState *chr, DisplayState *ds) { TextConsole *s; - unsigned width; - unsigned height; static int color_inited; - width = qemu_opt_get_number(opts, "width", 0); - if (width == 0) - width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH; + s = chr->opaque; - height = qemu_opt_get_number(opts, "height", 0); - if (height == 0) - height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT; - - if (width == 0 || height == 0) { - s = new_console(ds, TEXT_CONSOLE); - width = ds_get_width(s->ds); - height = ds_get_height(s->ds); - } else { - s = new_console(ds, TEXT_CONSOLE_FIXED_SIZE); - } - - if (!s) { - free(chr); - return; - } - chr->opaque = s; chr->chr_write = console_puts; - chr->chr_send_event = console_send_event; - s->chr = chr; s->out_fifo.buf = s->out_fifo_buf; s->out_fifo.buf_size = sizeof(s->out_fifo_buf); - s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s); + s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s); s->ds = ds; if (!color_inited) { @@ -1365,8 +1477,10 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpt s->total_height = DEFAULT_BACKSCROLL; s->x = 0; s->y = 0; - s->g_width = width; - s->g_height = height; + if (s->console_type == TEXT_CONSOLE) { + s->g_width = ds_get_width(s->ds); + s->g_height = ds_get_height(s->ds); + } s->hw_invalidate = text_console_invalidate; s->hw_text_update = text_console_update; @@ -1384,7 +1498,17 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpt s->t_attrib = s->t_attrib_default; text_console_resize(s); - qemu_chr_reset(chr); + if (chr->label) { + char msg[128]; + int len; + + s->t_attrib.bgcol = COLOR_BLUE; + len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label); + console_puts(chr, (uint8_t*)msg, len); + s->t_attrib = s->t_attrib_default; + } + + qemu_chr_generic_open(chr); if (chr->init) chr->init(chr); } @@ -1392,17 +1516,36 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpt CharDriverState *text_console_init(QemuOpts *opts) { CharDriverState *chr; + TextConsole *s; + unsigned width; + unsigned height; - chr = qemu_mallocz(sizeof(CharDriverState)); + chr = g_malloc0(sizeof(CharDriverState)); - if (n_text_consoles == 128) { - fprintf(stderr, "Too many text consoles\n"); - exit(1); + width = qemu_opt_get_number(opts, "width", 0); + if (width == 0) + width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH; + + height = qemu_opt_get_number(opts, "height", 0); + if (height == 0) + height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT; + + if (width == 0 || height == 0) { + s = new_console(NULL, TEXT_CONSOLE); + } else { + s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE); + } + + if (!s) { + g_free(chr); + return NULL; } - text_consoles[n_text_consoles] = chr; - text_console_opts[n_text_consoles] = opts; - n_text_consoles++; + s->chr = chr; + s->g_width = width; + s->g_height = height; + chr->opaque = s; + chr->chr_set_echo = text_console_set_echo; return chr; } @@ -1410,13 +1553,11 @@ void text_consoles_set_display(DisplayState *ds) { int i; - for (i = 0; i < n_text_consoles; i++) { - text_console_do_init(text_consoles[i], ds, text_console_opts[i]); - qemu_opts_del(text_console_opts[i]); - text_console_opts[i] = NULL; + for (i = 0; i < nb_consoles; i++) { + if (consoles[i]->console_type != GRAPHIC_CONSOLE) { + text_console_do_init(consoles[i]->chr, ds); + } } - - n_text_consoles = 0; } void qemu_console_resize(DisplayState *ds, int width, int height) @@ -1500,6 +1641,22 @@ PixelFormat qemu_default_pixelformat(int bpp) pf.depth = bpp == 32 ? 24 : bpp; switch (bpp) { + case 15: + pf.bits_per_pixel = 16; + pf.bytes_per_pixel = 2; + pf.rmask = 0x00007c00; + pf.gmask = 0x000003E0; + pf.bmask = 0x0000001F; + pf.rmax = 31; + pf.gmax = 31; + pf.bmax = 31; + pf.rshift = 10; + pf.gshift = 5; + pf.bshift = 0; + pf.rbits = 5; + pf.gbits = 5; + pf.bbits = 5; + break; case 16: pf.rmask = 0x0000F800; pf.gmask = 0x000007E0; @@ -1527,6 +1684,7 @@ PixelFormat qemu_default_pixelformat(int bpp) pf.rbits = 8; pf.gbits = 8; pf.bbits = 8; + break; case 32: pf.rmask = 0x00FF0000; pf.gmask = 0x0000FF00; @@ -1549,67 +1707,3 @@ PixelFormat qemu_default_pixelformat(int bpp) } return pf; } - -DisplaySurface* defaultallocator_create_displaysurface(int width, int height) -{ - DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface)); - - surface->width = width; - surface->height = height; - surface->linesize = width * 4; - surface->pf = qemu_default_pixelformat(32); -#ifdef HOST_WORDS_BIGENDIAN - surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG; -#else - surface->flags = QEMU_ALLOCATED_FLAG; -#endif - surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height); - - return surface; -} - -DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface, - int width, int height) -{ - surface->width = width; - surface->height = height; - surface->linesize = width * 4; - surface->pf = qemu_default_pixelformat(32); - if (surface->flags & QEMU_ALLOCATED_FLAG) - surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height); - else - surface->data = (uint8_t*) qemu_malloc(surface->linesize * surface->height); -#ifdef HOST_WORDS_BIGENDIAN - surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG; -#else - surface->flags = QEMU_ALLOCATED_FLAG; -#endif - - return surface; -} - -DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, - int linesize, uint8_t *data) -{ - DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface)); - - surface->width = width; - surface->height = height; - surface->linesize = linesize; - surface->pf = qemu_default_pixelformat(bpp); -#ifdef HOST_WORDS_BIGENDIAN - surface->flags = QEMU_BIG_ENDIAN_FLAG; -#endif - surface->data = data; - - return surface; -} - -void defaultallocator_free_displaysurface(DisplaySurface *surface) -{ - if (surface == NULL) - return; - if (surface->flags & QEMU_ALLOCATED_FLAG) - qemu_free(surface->data); - qemu_free(surface); -}