]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Add input buffer to mux chr (patch by Tristan Gingold).
authorbalrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 25 Nov 2007 00:55:06 +0000 (00:55 +0000)
committerbalrog <balrog@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 25 Nov 2007 00:55:06 +0000 (00:55 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3735 c046a42c-6fe2-441c-8c8c-71466251a162

hw/mcf_uart.c
hw/pl011.c
hw/serial.c
hw/slavio_serial.c
qemu-char.h
vl.c

index 01973a02fd58023d3af5aad9f05d456f4c4b2a0f..a65cc772c27d2dc25a88e9cb19bcbc8e961c6206 100644 (file)
@@ -88,6 +88,7 @@ uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr)
             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 91c52cc318cbcbc6ce072b9bebc29880ff7998d2..9d8c6a3f58670d5b2f1e7aee225a440864cd3517 100644 (file)
@@ -78,6 +78,7 @@ static uint32_t pl011_read(void *opaque, target_phys_addr_t offset)
         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 c5d9db5fa2ba3c4d6e75882c09feb05d5017c4bf..b1bd0ff36c4c9fd2d7d62298e5bfafb61d6d9735 100644 (file)
@@ -223,6 +223,7 @@ static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
             ret = s->rbr;
             s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
             serial_update_irq(s);
+            qemu_chr_accept_input(s->chr);
         }
         break;
     case 1:
index 534a438a19c101eea937389b76dbd39207195463..9a8e34015359cb60c3bb4f754ac4476aa5a83b9d 100644 (file)
@@ -475,6 +475,7 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
         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;
index 5a36a3683195397e84fb1505bdd59d1f02b457aa..29de03df58cff305b53cc63efa6b5b0cae12ab1c 100644 (file)
@@ -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, int cmd, void *arg);
 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 */
 
diff --git a/vl.c b/vl.c
index d362536470c2dea98ecc5b02de33082f004a0217..2ed7aecffb29f1286a48b145eb90c7a12b466f4d 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -1594,6 +1594,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len)
     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, ...)
 {
@@ -1645,12 +1650,17 @@ static CharDriverState *qemu_chr_open_null(void)
 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;
@@ -1779,12 +1789,28 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
     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;
 }
 
@@ -1792,10 +1818,20 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
 {
     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)
@@ -1850,6 +1886,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
     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;
 }