Commit bd9bdce694ccb76facc882363e4c337e8a88c918
1 parent
1fc678cc
Add input buffer to mux chr (patch by Tristan Gingold).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3735 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
46 additions
and
3 deletions
hw/mcf_uart.c
hw/pl011.c
| ... | ... | @@ -78,6 +78,7 @@ static uint32_t pl011_read(void *opaque, target_phys_addr_t offset) |
| 78 | 78 | if (s->read_count == s->read_trigger - 1) |
| 79 | 79 | s->int_level &= ~ PL011_INT_RX; |
| 80 | 80 | pl011_update(s); |
| 81 | + qemu_chr_accept_input(s->chr); | |
| 81 | 82 | return c; |
| 82 | 83 | case 1: /* UARTCR */ |
| 83 | 84 | return 0; | ... | ... |
hw/serial.c
hw/slavio_serial.c
| ... | ... | @@ -475,6 +475,7 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) |
| 475 | 475 | else |
| 476 | 476 | ret = s->rx; |
| 477 | 477 | SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret); |
| 478 | + qemu_chr_accept_input(s->chr); | |
| 478 | 479 | return ret; |
| 479 | 480 | default: |
| 480 | 481 | break; | ... | ... |
qemu-char.h
| ... | ... | @@ -40,6 +40,7 @@ struct CharDriverState { |
| 40 | 40 | void *handler_opaque; |
| 41 | 41 | void (*chr_send_event)(struct CharDriverState *chr, int event); |
| 42 | 42 | void (*chr_close)(struct CharDriverState *chr); |
| 43 | + void (*chr_accept_input)(struct CharDriverState *chr); | |
| 43 | 44 | void *opaque; |
| 44 | 45 | int focus; |
| 45 | 46 | QEMUBH *bh; |
| ... | ... | @@ -59,6 +60,7 @@ int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg); |
| 59 | 60 | void qemu_chr_reset(CharDriverState *s); |
| 60 | 61 | int qemu_chr_can_read(CharDriverState *s); |
| 61 | 62 | void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); |
| 63 | +void qemu_chr_accept_input(CharDriverState *s); | |
| 62 | 64 | |
| 63 | 65 | /* async I/O support */ |
| 64 | 66 | ... | ... |
vl.c
| ... | ... | @@ -1594,6 +1594,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) |
| 1594 | 1594 | s->chr_read(s->handler_opaque, buf, len); |
| 1595 | 1595 | } |
| 1596 | 1596 | |
| 1597 | +void qemu_chr_accept_input(CharDriverState *s) | |
| 1598 | +{ | |
| 1599 | + if (s->chr_accept_input) | |
| 1600 | + s->chr_accept_input(s); | |
| 1601 | +} | |
| 1597 | 1602 | |
| 1598 | 1603 | void qemu_chr_printf(CharDriverState *s, const char *fmt, ...) |
| 1599 | 1604 | { |
| ... | ... | @@ -1645,12 +1650,17 @@ static CharDriverState *qemu_chr_open_null(void) |
| 1645 | 1650 | static int term_timestamps; |
| 1646 | 1651 | static int64_t term_timestamps_start; |
| 1647 | 1652 | #define MAX_MUX 4 |
| 1653 | +#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */ | |
| 1654 | +#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1) | |
| 1648 | 1655 | typedef struct { |
| 1649 | 1656 | IOCanRWHandler *chr_can_read[MAX_MUX]; |
| 1650 | 1657 | IOReadHandler *chr_read[MAX_MUX]; |
| 1651 | 1658 | IOEventHandler *chr_event[MAX_MUX]; |
| 1652 | 1659 | void *ext_opaque[MAX_MUX]; |
| 1653 | 1660 | CharDriverState *drv; |
| 1661 | + unsigned char buffer[MUX_BUFFER_SIZE]; | |
| 1662 | + int prod; | |
| 1663 | + int cons; | |
| 1654 | 1664 | int mux_cnt; |
| 1655 | 1665 | int term_got_escape; |
| 1656 | 1666 | int max_size; |
| ... | ... | @@ -1779,12 +1789,28 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch) |
| 1779 | 1789 | return 0; |
| 1780 | 1790 | } |
| 1781 | 1791 | |
| 1792 | +static void mux_chr_accept_input(CharDriverState *chr) | |
| 1793 | +{ | |
| 1794 | + int m = chr->focus; | |
| 1795 | + MuxDriver *d = chr->opaque; | |
| 1796 | + | |
| 1797 | + while (d->prod != d->cons && | |
| 1798 | + d->chr_can_read[m] && | |
| 1799 | + d->chr_can_read[m](d->ext_opaque[m])) { | |
| 1800 | + d->chr_read[m](d->ext_opaque[m], | |
| 1801 | + &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1); | |
| 1802 | + } | |
| 1803 | +} | |
| 1804 | + | |
| 1782 | 1805 | static int mux_chr_can_read(void *opaque) |
| 1783 | 1806 | { |
| 1784 | 1807 | CharDriverState *chr = opaque; |
| 1785 | 1808 | MuxDriver *d = chr->opaque; |
| 1809 | + | |
| 1810 | + if ((d->prod - d->cons) < MUX_BUFFER_SIZE) | |
| 1811 | + return 1; | |
| 1786 | 1812 | if (d->chr_can_read[chr->focus]) |
| 1787 | - return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]); | |
| 1813 | + return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]); | |
| 1788 | 1814 | return 0; |
| 1789 | 1815 | } |
| 1790 | 1816 | |
| ... | ... | @@ -1792,10 +1818,20 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size) |
| 1792 | 1818 | { |
| 1793 | 1819 | CharDriverState *chr = opaque; |
| 1794 | 1820 | MuxDriver *d = chr->opaque; |
| 1821 | + int m = chr->focus; | |
| 1795 | 1822 | int i; |
| 1823 | + | |
| 1824 | + mux_chr_accept_input (opaque); | |
| 1825 | + | |
| 1796 | 1826 | for(i = 0; i < size; i++) |
| 1797 | - if (mux_proc_byte(chr, d, buf[i])) | |
| 1798 | - d->chr_read[chr->focus](d->ext_opaque[chr->focus], &buf[i], 1); | |
| 1827 | + if (mux_proc_byte(chr, d, buf[i])) { | |
| 1828 | + if (d->prod == d->cons && | |
| 1829 | + d->chr_can_read[m] && | |
| 1830 | + d->chr_can_read[m](d->ext_opaque[m])) | |
| 1831 | + d->chr_read[m](d->ext_opaque[m], &buf[i], 1); | |
| 1832 | + else | |
| 1833 | + d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i]; | |
| 1834 | + } | |
| 1799 | 1835 | } |
| 1800 | 1836 | |
| 1801 | 1837 | static void mux_chr_event(void *opaque, int event) |
| ... | ... | @@ -1850,6 +1886,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) |
| 1850 | 1886 | chr->focus = -1; |
| 1851 | 1887 | chr->chr_write = mux_chr_write; |
| 1852 | 1888 | chr->chr_update_read_handler = mux_chr_update_read_handler; |
| 1889 | + chr->chr_accept_input = mux_chr_accept_input; | |
| 1853 | 1890 | return chr; |
| 1854 | 1891 | } |
| 1855 | 1892 | ... | ... |