]> git.proxmox.com Git - mirror_qemu.git/commitdiff
char device support
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 14 Jul 2004 17:28:13 +0000 (17:28 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 14 Jul 2004 17:28:13 +0000 (17:28 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1023 c046a42c-6fe2-441c-8c8c-71466251a162

hw/pc.c
hw/ppc_chrp.c
hw/ppc_prep.c
hw/serial.c
vl.c
vl.h

diff --git a/hw/pc.c b/hw/pc.c
index 11b28279218629980e04ec6b94b69e4eba01aa3e..0fd7b87b26a960e388bfd0db675b87b7e717a0d0 100644 (file)
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -324,7 +324,7 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device,
              const char *initrd_filename)
 {
     char buf[1024];
-    int ret, linux_boot, initrd_size, i, nb_nics1, fd;
+    int ret, linux_boot, initrd_size, i, nb_nics1;
     unsigned long bios_offset, vga_bios_offset;
     int bios_size, isa_bios_size;
     PCIBus *pci_bus;
@@ -471,8 +471,7 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device,
     pic_init();
     pit = pit_init(0x40, 0);
 
-    fd = serial_open_device();
-    serial_init(0x3f8, 4, fd);
+    serial_init(0x3f8, 4, serial_hd);
 
     if (pci_enabled) {
         for(i = 0; i < nb_nics; i++) {
index 93835322fb78147068d00385d3f7119319735152..f532fe101926381f8a0bdbc9f4baeffc2faf1856 100644 (file)
@@ -126,7 +126,7 @@ void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
     openpic_t *openpic;
     m48t59_t *nvram;
     int PPC_io_memory;
-    int ret, linux_boot, i, fd;
+    int ret, linux_boot, i;
     unsigned long bios_offset;
     uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
     PCIBus *pci_bus;
@@ -200,8 +200,7 @@ void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
     pic_init();
 
     /* XXX: use Mac Serial port */
-    fd = serial_open_device();
-    serial_init(0x3f8, 4, fd);
+    serial_init(0x3f8, 4, serial_hd);
 
     for(i = 0; i < nb_nics; i++) {
         pci_ne2000_init(pci_bus, &nd_table[i]);
index 88dcac838dae18b5a7054da0a77fc04bb34616d3..eeb5a36095a55fbd5ea601b8ce575fe46a495765 100644 (file)
@@ -415,7 +415,7 @@ void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
     char buf[1024];
     m48t59_t *nvram;
     int PPC_io_memory;
-    int ret, linux_boot, i, nb_nics1, fd;
+    int ret, linux_boot, i, nb_nics1;
     unsigned long bios_offset;
     uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
     PCIBus *pci_bus;
@@ -492,8 +492,7 @@ void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
     pic_init();
     //    pit = pit_init(0x40, 0);
 
-    fd = serial_open_device();
-    serial_init(0x3f8, 4, fd);
+    serial_init(0x3f8, 4, serial_hd);
     nb_nics1 = nb_nics;
     if (nb_nics1 > NE2000_NB_MAX)
         nb_nics1 = NE2000_NB_MAX;
index 3cf43f4d163ce1d3a06bbe45ddc26af2c57b50f2..0fc1ccb9d0d8c367c9b9ede803c88b75dce39c72 100644 (file)
@@ -84,7 +84,7 @@ struct SerialState {
        it can be reset while reading iir */
     int thr_ipending;
     int irq;
-    int out_fd;
+    CharDriverState *chr;
 };
 
 static void serial_update_irq(SerialState *s)
@@ -107,7 +107,6 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
     SerialState *s = opaque;
     unsigned char ch;
-    int ret;
     
     addr &= 7;
 #ifdef DEBUG_SERIAL
@@ -122,13 +121,8 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
             s->thr_ipending = 0;
             s->lsr &= ~UART_LSR_THRE;
             serial_update_irq(s);
-
-            if (s->out_fd >= 0) {
-                ch = val;
-                do {
-                    ret = write(s->out_fd, &ch, 1);
-                } while (ret != 1);
-            }
+            ch = val;
+            qemu_chr_write(s->chr, &ch, 1);
             s->thr_ipending = 1;
             s->lsr |= UART_LSR_THRE;
             s->lsr |= UART_LSR_TEMT;
@@ -223,19 +217,19 @@ static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
     return ret;
 }
 
-int serial_can_receive(SerialState *s)
+static int serial_can_receive(SerialState *s)
 {
     return !(s->lsr & UART_LSR_DR);
 }
 
-void serial_receive_byte(SerialState *s, int ch)
+static void serial_receive_byte(SerialState *s, int ch)
 {
     s->rbr = ch;
     s->lsr |= UART_LSR_DR;
     serial_update_irq(s);
 }
 
-void serial_receive_break(SerialState *s)
+static void serial_receive_break(SerialState *s)
 {
     s->rbr = 0;
     s->lsr |= UART_LSR_BI | UART_LSR_DR;
@@ -254,8 +248,15 @@ static void serial_receive1(void *opaque, const uint8_t *buf, int size)
     serial_receive_byte(s, buf[0]);
 }
 
+static void serial_event(void *opaque, int event)
+{
+    SerialState *s = opaque;
+    if (event == CHR_EVENT_BREAK)
+        serial_receive_break(s);
+}
+
 /* If fd is zero, it means that the serial device uses the console */
-SerialState *serial_init(int base, int irq, int fd)
+SerialState *serial_init(int base, int irq, CharDriverState *chr)
 {
     SerialState *s;
 
@@ -268,16 +269,8 @@ SerialState *serial_init(int base, int irq, int fd)
 
     register_ioport_write(base, 8, 1, serial_ioport_write, s);
     register_ioport_read(base, 8, 1, serial_ioport_read, s);
-
-    if (fd < 0) {
-        /* no associated device */
-        s->out_fd = -1;
-    } else if (fd != 0) {
-        qemu_add_fd_read_handler(fd, serial_can_receive1, serial_receive1, s);
-        s->out_fd = fd;
-    } else {
-        serial_console = s;
-        s->out_fd = 1;
-    }
+    s->chr = chr;
+    qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s);
+    qemu_chr_add_event_handler(chr, serial_event);
     return s;
 }
diff --git a/vl.c b/vl.c
index 81782b08552dba22a268d906df68300240357861..3d64188b681aef6403749478bf599e65b19c04cf 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -128,7 +128,6 @@ static char network_script[1024];
 int pit_min_timer_count = 0;
 int nb_nics;
 NetDriverState nd_table[MAX_NICS];
-SerialState *serial_console;
 QEMUTimer *gui_timer;
 int vm_running;
 int audio_enabled = 0;
@@ -139,6 +138,7 @@ int cirrus_vga_enabled = 1;
 int graphic_width = 800;
 int graphic_height = 600;
 int graphic_depth = 15;
+TextConsole *vga_console;
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -298,6 +298,22 @@ char *pstrcat(char *buf, int buf_size, const char *s)
     return buf;
 }
 
+int strstart(const char *str, const char *val, const char **ptr)
+{
+    const char *p, *q;
+    p = str;
+    q = val;
+    while (*q != '\0') {
+        if (*p != *q)
+            return 0;
+        p++;
+        q++;
+    }
+    if (ptr)
+        *ptr = p;
+    return 1;
+}
+
 /* return the size or -1 if error */
 int get_image_size(const char *filename)
 {
@@ -949,42 +965,273 @@ void quit_timers(void)
 }
 
 /***********************************************************/
-/* serial device */
+/* character device */
 
-#ifdef _WIN32
+int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
+{
+    return s->chr_write(s, buf, len);
+}
 
-int serial_open_device(void)
+void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
 {
-    return -1;
+    char buf[4096];
+    va_list ap;
+    va_start(ap, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, ap);
+    qemu_chr_write(s, buf, strlen(buf));
+    va_end(ap);
 }
 
-#else
+void qemu_chr_add_read_handler(CharDriverState *s, 
+                               IOCanRWHandler *fd_can_read, 
+                               IOReadHandler *fd_read, void *opaque)
+{
+    s->chr_add_read_handler(s, fd_can_read, fd_read, opaque);
+}
+             
+void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event)
+{
+    s->chr_event = chr_event;
+}
 
-int serial_open_device(void)
+static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 {
-    if (serial_console == NULL && nographic) {
-        /* use console for serial port */
-        return 0;
+    return len;
+}
+
+static void null_chr_add_read_handler(CharDriverState *chr, 
+                                    IOCanRWHandler *fd_can_read, 
+                                    IOReadHandler *fd_read, void *opaque)
+{
+}
+
+CharDriverState *qemu_chr_open_null(void)
+{
+    CharDriverState *chr;
+
+    chr = qemu_mallocz(sizeof(CharDriverState));
+    if (!chr)
+        return NULL;
+    chr->chr_write = null_chr_write;
+    chr->chr_add_read_handler = null_chr_add_read_handler;
+    return chr;
+}
+
+#ifndef _WIN32
+
+typedef struct {
+    int fd_in, fd_out;
+    /* for nographic stdio only */
+    IOCanRWHandler *fd_can_read; 
+    IOReadHandler *fd_read;
+    void *fd_opaque;
+} FDCharDriver;
+
+#define STDIO_MAX_CLIENTS 2
+
+static int stdio_nb_clients;
+static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
+
+static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    FDCharDriver *s = chr->opaque;
+    return write(s->fd_out, buf, len);
+}
+
+static void fd_chr_add_read_handler(CharDriverState *chr, 
+                                    IOCanRWHandler *fd_can_read, 
+                                    IOReadHandler *fd_read, void *opaque)
+{
+    FDCharDriver *s = chr->opaque;
+
+    if (nographic && s->fd_in == 0) {
+        s->fd_can_read = fd_can_read;
+        s->fd_read = fd_read;
+        s->fd_opaque = opaque;
     } else {
-#if 0
-        char slave_name[1024];
-        int master_fd, slave_fd;
-        
-        /* Not satisfying */
-        if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) {
-            fprintf(stderr, "warning: could not create pseudo terminal for serial port\n");
-            return -1;
+        qemu_add_fd_read_handler(s->fd_in, fd_can_read, fd_read, opaque);
+    }
+}
+
+/* open a character device to a unix fd */
+CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
+{
+    CharDriverState *chr;
+    FDCharDriver *s;
+
+    chr = qemu_mallocz(sizeof(CharDriverState));
+    if (!chr)
+        return NULL;
+    s = qemu_mallocz(sizeof(FDCharDriver));
+    if (!s) {
+        free(chr);
+        return NULL;
+    }
+    s->fd_in = fd_in;
+    s->fd_out = fd_out;
+    chr->opaque = s;
+    chr->chr_write = fd_chr_write;
+    chr->chr_add_read_handler = fd_chr_add_read_handler;
+    return chr;
+}
+
+/* for STDIO, we handle the case where several clients use it
+   (nographic mode) */
+
+#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
+
+static int term_got_escape, client_index;
+
+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 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;
+        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 TERM_ESCAPE:
+            goto send_char;
+        }
+    } else if (ch == TERM_ESCAPE) {
+        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;
+            buf[0] = ch;
+            /* XXX: should queue the char if the device is not
+               ready */
+            if (s->fd_can_read(s->fd_opaque) > 0) 
+                s->fd_read(s->fd_opaque, buf, 1);
         }
-        fprintf(stderr, "Serial port redirected to %s\n", slave_name);
-        return master_fd;
-#else
-        return -1;
-#endif
     }
 }
 
+static int stdio_can_read(void *opaque)
+{
+    /* XXX: not strictly correct */
+    return 1;
+}
+
+static void stdio_read(void *opaque, const uint8_t *buf, int size)
+{
+    int i;
+    for(i = 0; i < size; i++)
+        stdio_received_byte(buf[i]);
+}
+
+CharDriverState *qemu_chr_open_stdio(void)
+{
+    CharDriverState *chr;
+
+    if (nographic) {
+        if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
+            return NULL;
+        chr = qemu_chr_open_fd(0, 1);
+        if (stdio_nb_clients == 0)
+            qemu_add_fd_read_handler(0, stdio_can_read, stdio_read, 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;
+    return chr;
+}
+
+#if defined(__linux__)
+CharDriverState *qemu_chr_open_pty(void)
+{
+    char slave_name[1024];
+    int master_fd, slave_fd;
+    
+    /* Not satisfying */
+    if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) {
+        return NULL;
+    }
+    fprintf(stderr, "char device redirected to %s\n", slave_name);
+    return qemu_chr_open_fd(master_fd, master_fd);
+}
+#else
+CharDriverState *qemu_chr_open_pty(void)
+{
+    return NULL;
+}
 #endif
 
+#endif /* !defined(_WIN32) */
+
+CharDriverState *qemu_chr_open(const char *filename)
+{
+    if (!strcmp(filename, "vc")) {
+        return text_console_init(&display_state);
+    } else if (!strcmp(filename, "null")) {
+        return qemu_chr_open_null();
+    } else 
+#ifndef _WIN32
+    if (!strcmp(filename, "pty")) {
+        return qemu_chr_open_pty();
+    } else if (!strcmp(filename, "stdio")) {
+        return qemu_chr_open_stdio();
+    } else 
+#endif
+    {
+        return NULL;
+    }
+}
+
 /***********************************************************/
 /* Linux network device redirectors */
 
@@ -2106,6 +2353,8 @@ void help(void)
            "-initrd file    use 'file' as initial ram disk\n"
            "\n"
            "Debug/Expert options:\n"
+           "-monitor dev    redirect the monitor to char device 'dev'\n"
+           "-serial dev     redirect the serial port to char device 'dev'\n"
            "-S              freeze CPU at startup (use 'c' to start execution)\n"
            "-s              wait gdb connection to port %d\n"
            "-p port         change gdb connection port\n"
@@ -2121,7 +2370,13 @@ void help(void)
            "                (default is CL-GD5446 PCI VGA)\n"
 #endif
            "\n"
-           "During emulation, use C-a h to get terminal commands:\n",
+           "During emulation, the following keys are useful:\n"
+           "ctrl-shift-f    toggle full screen\n"
+           "ctrl-shift-Fn   switch to virtual console 'n'\n"
+           "ctrl-shift      toggle mouse and keyboard grab\n"
+           "\n"
+           "When using -nographic, press 'ctrl-a h' to get some help.\n"
+           ,
 #ifdef CONFIG_SOFTMMU
            "qemu",
 #else
@@ -2131,7 +2386,6 @@ void help(void)
            DEFAULT_NETWORK_SCRIPT,
            DEFAULT_GDBSTUB_PORT,
            "/tmp/qemu.log");
-    term_print_help();
 #ifndef CONFIG_SOFTMMU
     printf("\n"
            "NOTE: this version of QEMU is faster but it needs slightly patched OSes to\n"
@@ -2184,6 +2438,8 @@ enum {
     QEMU_OPTION_cirrusvga,
     QEMU_OPTION_g,
     QEMU_OPTION_std_vga,
+    QEMU_OPTION_monitor,
+    QEMU_OPTION_serial,
 };
 
 typedef struct QEMUOption {
@@ -2235,7 +2491,9 @@ const QEMUOption qemu_options[] = {
     { "localtime", 0, QEMU_OPTION_localtime },
     { "isa", 0, QEMU_OPTION_isa },
     { "std-vga", 0, QEMU_OPTION_std_vga },
-
+    { "monitor", 1, QEMU_OPTION_monitor },
+    { "serial", 1, QEMU_OPTION_serial },
+    
     /* temporary options */
     { "pci", 0, QEMU_OPTION_pci },
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
@@ -2273,6 +2531,9 @@ int main(int argc, char **argv)
     int net_if_type, nb_tun_fds, tun_fds[MAX_NICS];
     int optind;
     const char *r, *optarg;
+    CharDriverState *monitor_hd;
+    char monitor_device[128];
+    char serial_device[128];
 
 #if !defined(CONFIG_SOFTMMU)
     /* we never want that malloc() uses mmap() */
@@ -2297,6 +2558,8 @@ int main(int argc, char **argv)
     kernel_cmdline = "";
     has_cdrom = 1;
     cyls = heads = secs = 0;
+    pstrcpy(monitor_device, sizeof(monitor_device), "vc");
+    pstrcpy(serial_device, sizeof(serial_device), "vc");
 
     nb_tun_fds = 0;
     net_if_type = -1;
@@ -2308,7 +2571,7 @@ int main(int argc, char **argv)
     macaddr[3] = 0x12;
     macaddr[4] = 0x34;
     macaddr[5] = 0x56;
-
+    
     optind = 1;
     for(;;) {
         if (optind >= argc)
@@ -2375,6 +2638,8 @@ int main(int argc, char **argv)
                 }
                 break;
             case QEMU_OPTION_nographic:
+                pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
+                pstrcpy(serial_device, sizeof(serial_device), "stdio");
                 nographic = 1;
                 break;
             case QEMU_OPTION_kernel:
@@ -2561,6 +2826,12 @@ int main(int argc, char **argv)
                     graphic_depth = depth;
                 }
                 break;
+            case QEMU_OPTION_monitor:
+                pstrcpy(monitor_device, sizeof(monitor_device), optarg);
+                break;
+            case QEMU_OPTION_serial:
+                pstrcpy(serial_device, sizeof(serial_device), optarg);
+                break;
             }
         }
     }
@@ -2750,6 +3021,24 @@ int main(int argc, char **argv)
 #endif
     }
 
+    vga_console = graphic_console_init(ds);
+    
+    monitor_hd = qemu_chr_open(monitor_device);
+    if (!monitor_hd) {
+        fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
+        exit(1);
+    }
+    monitor_init(monitor_hd, !nographic);
+
+    serial_hd = qemu_chr_open(serial_device);
+    if (!serial_hd) {
+        fprintf(stderr, "qemu: could not open serial device '%s'\n", serial_device);
+        exit(1);
+    }
+    if (!strcmp(serial_device, "vc"))
+        qemu_chr_printf(serial_hd, "serial0 console\n");
+    
+
     /* setup cpu signal handlers for MMU / self modifying code handling */
 #if !defined(CONFIG_SOFTMMU)
     
@@ -2805,10 +3094,6 @@ int main(int argc, char **argv)
             kernel_filename, kernel_cmdline, initrd_filename);
 #endif
 
-    /* launched after the device init so that it can display or not a
-       banner */
-    monitor_init();
-
     gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
     qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));
 
diff --git a/vl.h b/vl.h
index 15004c01043399c210bc7dc7eb6d2cf721cb3911..a37981a500abed6a6b351f55b1f9126ad3809dab 100644 (file)
--- a/vl.h
+++ b/vl.h
@@ -215,8 +215,7 @@ extern const char *bios_dir;
 
 void pstrcpy(char *buf, int buf_size, const char *str);
 char *pstrcat(char *buf, int buf_size, const char *s);
-
-int serial_open_device(void);
+int strstart(const char *str, const char *val, const char **ptr);
 
 extern int vm_running;
 
@@ -265,6 +264,31 @@ void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque);
 void kbd_put_keycode(int keycode);
 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
 
+/* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
+   constants) */
+#define QEMU_KEY_ESC1(c) ((c) | 0xe100)
+#define QEMU_KEY_BACKSPACE  0x007f
+#define QEMU_KEY_UP         QEMU_KEY_ESC1('A')
+#define QEMU_KEY_DOWN       QEMU_KEY_ESC1('B')
+#define QEMU_KEY_RIGHT      QEMU_KEY_ESC1('C')
+#define QEMU_KEY_LEFT       QEMU_KEY_ESC1('D')
+#define QEMU_KEY_HOME       QEMU_KEY_ESC1(1)
+#define QEMU_KEY_END        QEMU_KEY_ESC1(4)
+#define QEMU_KEY_PAGEUP     QEMU_KEY_ESC1(5)
+#define QEMU_KEY_PAGEDOWN   QEMU_KEY_ESC1(6)
+#define QEMU_KEY_DELETE     QEMU_KEY_ESC1(3)
+
+#define QEMU_KEY_CTRL_UP         0xe400
+#define QEMU_KEY_CTRL_DOWN       0xe401
+#define QEMU_KEY_CTRL_LEFT       0xe402
+#define QEMU_KEY_CTRL_RIGHT      0xe403
+#define QEMU_KEY_CTRL_HOME       0xe404
+#define QEMU_KEY_CTRL_END        0xe405
+#define QEMU_KEY_CTRL_PAGEUP     0xe406
+#define QEMU_KEY_CTRL_PAGEDOWN   0xe407
+
+void kbd_put_keysym(int keysym);
+
 /* async I/O support */
 
 typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
@@ -274,6 +298,42 @@ int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read,
                              IOReadHandler *fd_read, void *opaque);
 void qemu_del_fd_read_handler(int fd);
 
+/* character device */
+
+#define CHR_EVENT_BREAK 0 /* serial break char */
+
+typedef void IOEventHandler(void *opaque, int event);
+
+typedef struct CharDriverState {
+    int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
+    void (*chr_add_read_handler)(struct CharDriverState *s, 
+                                 IOCanRWHandler *fd_can_read, 
+                                 IOReadHandler *fd_read, void *opaque);
+    IOEventHandler *chr_event;
+    void *opaque;
+} CharDriverState;
+
+void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
+int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
+void qemu_chr_add_read_handler(CharDriverState *s, 
+                               IOCanRWHandler *fd_can_read, 
+                               IOReadHandler *fd_read, void *opaque);
+void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event);
+                               
+CharDriverState *serial_hd;
+
+/* consoles */
+
+typedef struct DisplayState DisplayState;
+typedef struct TextConsole TextConsole;
+
+extern TextConsole *vga_console;
+
+TextConsole *graphic_console_init(DisplayState *ds);
+int is_active_console(TextConsole *s);
+CharDriverState *text_console_init(DisplayState *ds);
+void console_select(unsigned int index);
+
 /* network redirectors support */
 
 #define MAX_NICS 8
@@ -437,6 +497,7 @@ void bdrv_set_change_cb(BlockDriverState *bs,
 
 void bdrv_info(void);
 BlockDriverState *bdrv_find(const char *name);
+void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque);
 
 /* ISA bus */
 
@@ -534,14 +595,16 @@ openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus);
 
 #define VGA_RAM_SIZE (4096 * 1024)
 
-typedef struct DisplayState {
+struct DisplayState {
     uint8_t *data;
     int linesize;
     int depth;
+    int width;
+    int height;
     void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
     void (*dpy_resize)(struct DisplayState *s, int w, int h);
     void (*dpy_refresh)(struct DisplayState *s);
-} DisplayState;
+};
 
 static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
 {
@@ -644,13 +707,7 @@ void rtc_set_date(RTCState *s, const struct tm *tm);
 /* serial.c */
 
 typedef struct SerialState SerialState;
-
-extern SerialState *serial_console;
-
-SerialState *serial_init(int base, int irq, int fd);
-int serial_can_receive(SerialState *s);
-void serial_receive_byte(SerialState *s, int ch);
-void serial_receive_break(SerialState *s);
+SerialState *serial_init(int base, int irq, CharDriverState *chr);
 
 /* i8259.c */
 
@@ -767,7 +824,7 @@ extern ADBBusState adb_bus;
 int cuda_init(openpic_t *openpic, int irq);
 
 /* monitor.c */
-void monitor_init(void);
+void monitor_init(CharDriverState *hd, int show_banner);
 void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
 void term_flush(void);
 void term_print_help(void);