? qemu.diffs
Index: qemu-char.h
===================================================================
RCS file: /sources/qemu/qemu/qemu-char.h,v
retrieving revision 1.2
diff -u -p -r1.2 qemu-char.h
--- qemu-char.h	18 Nov 2007 01:44:36 -0000	1.2
+++ qemu-char.h	20 Nov 2007 12:50:38 -0000
@@ -40,6 +40,7 @@ struct CharDriverState {
     void *handler_opaque;
     void (*chr_send_event)(struct CharDriverState *chr, int event);
     void (*chr_close)(struct CharDriverState *chr);
+    void (*chr_accept_input)(struct CharDriverState *chr);
     void *opaque;
     int focus;
     QEMUBH *bh;
@@ -59,6 +60,7 @@ int qemu_chr_ioctl(CharDriverState *s, i
 void qemu_chr_reset(CharDriverState *s);
 int qemu_chr_can_read(CharDriverState *s);
 void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len);
+void qemu_chr_accept_input(CharDriverState *s);
 
 /* async I/O support */
 
Index: vl.c
===================================================================
RCS file: /sources/qemu/qemu/vl.c,v
retrieving revision 1.369
diff -u -p -r1.369 vl.c
--- vl.c	19 Nov 2007 01:05:22 -0000	1.369
+++ vl.c	20 Nov 2007 12:50:40 -0000
@@ -1595,6 +1595,11 @@ void qemu_chr_read(CharDriverState *s, u
     s->chr_read(s->handler_opaque, buf, len);
 }
 
+void qemu_chr_accept_input(CharDriverState *s)
+{
+    if (s->chr_accept_input)
+	s->chr_accept_input (s);
+}
 
 void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
 {
@@ -1646,12 +1651,17 @@ static CharDriverState *qemu_chr_open_nu
 static int term_timestamps;
 static int64_t term_timestamps_start;
 #define MAX_MUX 4
+#define MUX_BUFFER_SIZE 32	/* Must be a power of 2.  */
+#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1)
 typedef struct {
     IOCanRWHandler *chr_can_read[MAX_MUX];
     IOReadHandler *chr_read[MAX_MUX];
     IOEventHandler *chr_event[MAX_MUX];
     void *ext_opaque[MAX_MUX];
     CharDriverState *drv;
+    unsigned char buffer[MUX_BUFFER_SIZE];
+    int prod;
+    int cons;
     int mux_cnt;
     int term_got_escape;
     int max_size;
@@ -1780,12 +1790,28 @@ static int mux_proc_byte(CharDriverState
     return 0;
 }
 
+static void mux_chr_accept_input(CharDriverState *chr)
+{
+    int m = chr->focus;
+    MuxDriver *d = chr->opaque;
+
+    while (d->prod != d->cons
+	   && d->chr_can_read[m]
+	   && d->chr_can_read[m](d->ext_opaque[m])) {
+	d->chr_read[m](d->ext_opaque[m],
+		       &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1);
+    }
+}
+
 static int mux_chr_can_read(void *opaque)
 {
     CharDriverState *chr = opaque;
     MuxDriver *d = chr->opaque;
+
+    if ((d->prod - d->cons) < MUX_BUFFER_SIZE)
+	return 1;
     if (d->chr_can_read[chr->focus])
-       return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]);
+	return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]);
     return 0;
 }
 
@@ -1793,10 +1819,20 @@ static void mux_chr_read(void *opaque, c
 {
     CharDriverState *chr = opaque;
     MuxDriver *d = chr->opaque;
+    int m = chr->focus;
     int i;
+
+    mux_chr_accept_input (opaque);
+
     for(i = 0; i < size; i++)
-        if (mux_proc_byte(chr, d, buf[i]))
-            d->chr_read[chr->focus](d->ext_opaque[chr->focus], &buf[i], 1);
+        if (mux_proc_byte(chr, d, buf[i])) {
+	    if (d->prod == d->cons
+		&& d->chr_can_read[m]
+		&& d->chr_can_read[m](d->ext_opaque[m]))
+		d->chr_read[m](d->ext_opaque[m], &buf[i], 1);
+	    else
+		d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i];
+	}
 }
 
 static void mux_chr_event(void *opaque, int event)
@@ -1851,6 +1887,7 @@ static CharDriverState *qemu_chr_open_mu
     chr->focus = -1;
     chr->chr_write = mux_chr_write;
     chr->chr_update_read_handler = mux_chr_update_read_handler;
+    chr->chr_accept_input = mux_chr_accept_input;
     return chr;
 }
 
Index: hw/mcf_uart.c
===================================================================
RCS file: /sources/qemu/qemu/hw/mcf_uart.c,v
retrieving revision 1.3
diff -u -p -r1.3 mcf_uart.c
--- hw/mcf_uart.c	17 Nov 2007 17:14:43 -0000	1.3
+++ hw/mcf_uart.c	20 Nov 2007 12:50:40 -0000
@@ -88,6 +88,7 @@ uint32_t mcf_uart_read(void *opaque, tar
             if (s->fifo_len == 0)
                 s->sr &= ~MCF_UART_RxRDY;
             mcf_uart_update(s);
+	    qemu_chr_accept_input (s->chr);
             return val;
         }
     case 0x10:
Index: hw/pl011.c
===================================================================
RCS file: /sources/qemu/qemu/hw/pl011.c,v
retrieving revision 1.10
diff -u -p -r1.10 pl011.c
--- hw/pl011.c	17 Nov 2007 17:14:45 -0000	1.10
+++ hw/pl011.c	20 Nov 2007 12:50:40 -0000
@@ -78,6 +78,7 @@ static uint32_t pl011_read(void *opaque,
         if (s->read_count == s->read_trigger - 1)
             s->int_level &= ~ PL011_INT_RX;
         pl011_update(s);
+	qemu_chr_accept_input (s->chr);
         return c;
     case 1: /* UARTCR */
         return 0;
Index: hw/slavio_serial.c
===================================================================
RCS file: /sources/qemu/qemu/hw/slavio_serial.c,v
retrieving revision 1.26
diff -u -p -r1.26 slavio_serial.c
--- hw/slavio_serial.c	17 Nov 2007 17:14:48 -0000	1.26
+++ hw/slavio_serial.c	20 Nov 2007 12:50:41 -0000
@@ -475,6 +475,7 @@ static uint32_t slavio_serial_mem_readb(
         else
             ret = s->rx;
         SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret);
+	qemu_chr_accept_input (s->chr);
         return ret;
     default:
         break;
