Index: qemu/vl.c =================================================================== --- qemu.orig/vl.c +++ qemu/vl.c @@ -1112,8 +1112,36 @@ typedef struct { static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { MuxDriver *d = chr->opaque; - len = d->drv->chr_write(d->drv, buf, len); - return len; + int ret; + if (!term_timestamps) { + ret = d->drv->chr_write(d->drv, buf, len); + } else { + int i; + + ret = 0; + for(i = 0; i < len; i++) { + ret += d->drv->chr_write(d->drv, buf+i, 1); + if (buf[i] == '\n') { + char buf1[64]; + int64_t ti; + int secs; + + ti = get_clock(); + if (term_timestamps_start == -1) + term_timestamps_start = ti; + ti -= term_timestamps_start; + secs = ti / 1000000000; + snprintf(buf1, sizeof(buf1), + "[%02d:%02d:%02d.%03d] ", + secs / 3600, + (secs / 60) % 60, + secs % 60, + (int)((ti / 1000000) % 1000)); + d->drv->chr_write(d->drv, buf1, strlen(buf1)); + } + } + } + return ret; } static char *mux_help[] = { @@ -1180,9 +1208,9 @@ static int mux_proc_byte(CharDriverState break; case 'c': /* Switch to the next registered device */ - d->idx++; - if (d->idx >= d->mux_cnt) - d->idx = 0; + chr->focus++; + if (chr->focus >= d->mux_cnt) + chr->focus = 0; break; case 't': term_timestamps = !term_timestamps; @@ -1202,7 +1230,7 @@ static int mux_chr_fd_can_read(void *opa { CharDriverState *chr = opaque; MuxDriver *d = chr->opaque; - return d->fd_can_read[d->idx](d->ext_opaque[d->idx]); + return d->fd_can_read[chr->focus](d->ext_opaque[chr->focus]); } static void mux_chr_fd_read(void *opaque, const uint8_t *buf, int size) @@ -1212,7 +1240,7 @@ static void mux_chr_fd_read(void *opaque int i; for(i = 0; i < size; i++) if (mux_proc_byte(chr, d, buf[i])) - d->fd_read[d->idx](d->ext_opaque[d->idx], &buf[i], 1); + d->fd_read[chr->focus](d->ext_opaque[chr->focus], &buf[i], 1); } static void mux_chr_add_read_handler(CharDriverState *chr, @@ -1233,7 +1261,7 @@ static void mux_chr_add_read_handler(Cha d->drv->chr_add_read_handler(d->drv, mux_chr_fd_can_read, mux_chr_fd_read, chr); - d->idx = d->mux_cnt; + chr->focus = d->mux_cnt; d->mux_cnt++; } @@ -1253,7 +1281,7 @@ CharDriverState *qemu_chr_open_mux(CharD chr->opaque = d; d->drv = drv; - d->idx = -1; + chr->focus = -1; chr->chr_write = mux_chr_write; chr->chr_add_read_handler = mux_chr_add_read_handler; return chr; @@ -1354,10 +1382,8 @@ typedef struct { int max_size; } FDCharDriver; -#define STDIO_MAX_CLIENTS 2 - -static int stdio_nb_clients; -static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS]; +#define STDIO_MAX_CLIENTS 1 +static int stdio_nb_clients = 0; static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { @@ -1458,155 +1484,40 @@ CharDriverState *qemu_chr_open_pipe(cons #define TERM_FIFO_MAX_SIZE 1 -static int term_got_escape, client_index; static uint8_t term_fifo[TERM_FIFO_MAX_SIZE]; static int term_fifo_size; -void term_print_help(void) -{ - printf("\n" - "C-a h print this help\n" - "C-a x exit emulator\n" - "C-a s save disk data back to file (if -snapshot)\n" - "C-a b send break (magic sysrq)\n" - "C-a t toggle console timestamps\n" - "C-a c switch between console and monitor\n" - "C-a C-a send C-a\n" - ); -} - -/* called when a char is received */ -static void stdio_received_byte(int ch) -{ - if (term_got_escape) { - term_got_escape = 0; - if (ch == term_escape_char) - goto send_char; - switch(ch) { - case 'h': - term_print_help(); - break; - case 'x': - exit(0); - break; - case 's': - { - int i; - for (i = 0; i < MAX_DISKS; i++) { - if (bs_table[i]) - bdrv_commit(bs_table[i]); - } - } - break; - case 'b': - if (client_index < stdio_nb_clients) { - CharDriverState *chr; - FDCharDriver *s; - - chr = stdio_clients[client_index]; - s = chr->opaque; - chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK); - } - break; - case 'c': - client_index++; - if (client_index >= stdio_nb_clients) - client_index = 0; - if (client_index == 0) { - /* send a new line in the monitor to get the prompt */ - ch = '\r'; - goto send_char; - } - break; - case 't': - term_timestamps = !term_timestamps; - term_timestamps_start = -1; - break; - } - } else if (ch == term_escape_char) { - term_got_escape = 1; - } else { - send_char: - if (client_index < stdio_nb_clients) { - uint8_t buf[1]; - CharDriverState *chr; - FDCharDriver *s; - - chr = stdio_clients[client_index]; - s = chr->opaque; - if (s->fd_can_read(s->fd_opaque) > 0) { - buf[0] = ch; - s->fd_read(s->fd_opaque, buf, 1); - } else if (term_fifo_size == 0) { - term_fifo[term_fifo_size++] = ch; - } - } - } -} - static int stdio_read_poll(void *opaque) { - CharDriverState *chr; - FDCharDriver *s; + CharDriverState *chr = opaque; + FDCharDriver *s = chr->opaque; - if (client_index < stdio_nb_clients) { - chr = stdio_clients[client_index]; - s = chr->opaque; - /* try to flush the queue if needed */ - if (term_fifo_size != 0 && s->fd_can_read(s->fd_opaque) > 0) { - s->fd_read(s->fd_opaque, term_fifo, 1); - term_fifo_size = 0; - } - /* see if we can absorb more chars */ - if (term_fifo_size == 0) - return 1; - else - return 0; - } else { - return 1; + /* try to flush the queue if needed */ + if (term_fifo_size != 0 && s->fd_can_read(s->fd_opaque) > 0) { + s->fd_read(s->fd_opaque, term_fifo, 1); + term_fifo_size = 0; } + /* see if we can absorb more chars */ + if (term_fifo_size == 0) + return 1; + else + return 0; } static void stdio_read(void *opaque) { int size; uint8_t buf[1]; - - size = read(0, buf, 1); - if (size > 0) - stdio_received_byte(buf[0]); -} - -static int stdio_write(CharDriverState *chr, const uint8_t *buf, int len) -{ + CharDriverState *chr = opaque; FDCharDriver *s = chr->opaque; - if (!term_timestamps) { - return unix_write(s->fd_out, buf, len); - } else { - int i; - char buf1[64]; - for(i = 0; i < len; i++) { - unix_write(s->fd_out, buf + i, 1); - if (buf[i] == '\n') { - int64_t ti; - int secs; - - ti = get_clock(); - if (term_timestamps_start == -1) - term_timestamps_start = ti; - ti -= term_timestamps_start; - secs = ti / 1000000000; - snprintf(buf1, sizeof(buf1), - "[%02d:%02d:%02d.%03d] ", - secs / 3600, - (secs / 60) % 60, - secs % 60, - (int)((ti / 1000000) % 1000)); - unix_write(s->fd_out, buf1, strlen(buf1)); - } + size = read(0, buf, 1); + if (size > 0) { + if (s->fd_can_read(s->fd_opaque) > 0) { + s->fd_read(s->fd_opaque, buf, 1); + } else if (term_fifo_size == 0) { + term_fifo[term_fifo_size++] = buf[0]; } - return len; } } @@ -1651,24 +1562,13 @@ CharDriverState *qemu_chr_open_stdio(voi { CharDriverState *chr; - if (nographic) { - if (stdio_nb_clients >= STDIO_MAX_CLIENTS) - return NULL; - chr = qemu_chr_open_fd(0, 1); - chr->chr_write = stdio_write; - if (stdio_nb_clients == 0) - qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL); - client_index = stdio_nb_clients; - } else { - if (stdio_nb_clients != 0) - return NULL; - chr = qemu_chr_open_fd(0, 1); - } - stdio_clients[stdio_nb_clients++] = chr; - if (stdio_nb_clients == 1) { - /* set the terminal in raw mode */ - term_init(); - } + if (stdio_nb_clients >= STDIO_MAX_CLIENTS) + return NULL; + chr = qemu_chr_open_fd(0, 1); + qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr); + stdio_nb_clients++; + term_init(); + return chr; } @@ -5961,8 +5861,8 @@ int main(int argc, char **argv) } break; case QEMU_OPTION_nographic: - pstrcpy(monitor_device, sizeof(monitor_device), "stdio"); pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio"); + pstrcpy(monitor_device, sizeof(monitor_device), "stdio"); nographic = 1; break; case QEMU_OPTION_kernel: @@ -6328,10 +6228,20 @@ int main(int argc, char **argv) #endif } - for (i = 0; i < MAX_SERIAL_PORTS; i++) - if (!strncmp(serial_devices[i],"mon:",4)) - break; - if (i >= MAX_SERIAL_PORTS) { + /* Maintain compatibility with multiple stdio monitors */ + if (!strcmp(monitor_device,"stdio")) { + for (i = 0; i < MAX_SERIAL_PORTS; i++) { + if (!strcmp(serial_devices[i],"mon:stdio")) { + monitor_device[0] = '\0'; + break; + } else if (!strcmp(serial_devices[i],"stdio")) { + monitor_device[0] = '\0'; + pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "mon:stdio"); + break; + } + } + } + if (monitor_device[0] != '\0') { monitor_hd = qemu_chr_open(monitor_device); if (!monitor_hd) { fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device); Index: qemu/monitor.c =================================================================== --- qemu.orig/monitor.c +++ qemu/monitor.c @@ -54,7 +54,8 @@ typedef struct term_cmd_t { const char *help; } term_cmd_t; -static CharDriverState *monitor_hd; +#define MAX_MON 4 +static CharDriverState *monitor_hd[MAX_MON]; static term_cmd_t term_cmds[]; static term_cmd_t info_cmds[]; @@ -68,8 +69,11 @@ CPUState *mon_cpu = NULL; void term_flush(void) { + int i; if (term_outbuf_index > 0) { - qemu_chr_write(monitor_hd, term_outbuf, term_outbuf_index); + for (i = 0; i < MAX_MON; i++) + if (monitor_hd[i] && monitor_hd[i]->focus == 0) + qemu_chr_write(monitor_hd[i], term_outbuf, term_outbuf_index); term_outbuf_index = 0; } } @@ -2295,9 +2299,24 @@ static void monitor_start_input(void) readline_start("(qemu) ", 0, monitor_handle_command1, NULL); } +static int is_first_init = 1; + void monitor_init(CharDriverState *hd, int show_banner) { - monitor_hd = hd; + int i; + + if (is_first_init) { + for (i = 0; i < MAX_MON; i++) { + monitor_hd[i] = NULL; + } + is_first_init = 0; + } + for (i = 0; i < MAX_MON; i++) { + if (monitor_hd[i] == NULL) { + monitor_hd[i] = hd; + break; + } + } if (show_banner) { term_printf("QEMU %s monitor - type 'help' for more information\n", QEMU_VERSION); @@ -2321,8 +2340,12 @@ static void monitor_readline_cb(void *op void monitor_readline(const char *prompt, int is_password, char *buf, int buf_size) { + int i; + if (is_password) { - qemu_chr_send_event(monitor_hd, CHR_EVENT_FOCUS); + for (i = 0; i < MAX_MON; i++) + if (monitor_hd[i] && monitor_hd[i]->focus == 0) + qemu_chr_send_event(monitor_hd[i], CHR_EVENT_FOCUS); } readline_start(prompt, is_password, monitor_readline_cb, NULL); monitor_readline_buf = buf; Index: qemu/vl.h =================================================================== --- qemu.orig/vl.h +++ qemu/vl.h @@ -270,6 +270,7 @@ typedef struct CharDriverState { void (*chr_close)(struct CharDriverState *chr); void *opaque; void *event_opaque; + int focus; } CharDriverState; void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);