# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID c33272c2571c7bab7056d8228490700d1df405f9
# Parent b3d94f4ddffefed8a5cb8dd65a60da9491d460e7
[HVM] Fix Qemu-dm serial issues:
1. Retry transmit via a polling timer if a byte cannot be written
immediately to its destination.
2. Turn off output processing of raw serial lines.
Signed-off-by: Xiaowei Yang <xiaowei.yang@xxxxxxxxx>
Signed-off-by: Yunhong Jiang <yunhong.jiang@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
tools/ioemu/hw/serial.c | 44 +++++++++++++++++++++++++++++++++++++-------
tools/ioemu/vl.c | 2 +-
2 files changed, 38 insertions(+), 8 deletions(-)
diff -r b3d94f4ddffe -r c33272c2571c tools/ioemu/hw/serial.c
--- a/tools/ioemu/hw/serial.c Sat Oct 28 12:30:38 2006 +0100
+++ b/tools/ioemu/hw/serial.c Mon Oct 30 09:45:17 2006 +0000
@@ -93,6 +93,15 @@ struct SerialState {
int last_break_enable;
target_ulong base;
int it_shift;
+
+ /*
+ * If a character transmitted via UART cannot be written to its
+ * destination immediately we remember it here and retry a few times via
+ * a polling timer.
+ */
+ int write_retries;
+ char write_chr;
+ QEMUTimer *write_retry_timer;
};
static void serial_update_irq(SerialState *s)
@@ -204,10 +213,32 @@ static void serial_get_token(void)
tokens_avail--;
}
+static void serial_chr_write(void *opaque)
+{
+ SerialState *s = opaque;
+
+ qemu_del_timer(s->write_retry_timer);
+
+ /* Retry every 100ms for 300ms total. */
+ if (qemu_chr_write(s->chr, &s->write_chr, 1) == -1) {
+ if (s->write_retries++ >= 3)
+ printf("serial: write error\n");
+ else
+ qemu_mod_timer(s->write_retry_timer,
+ qemu_get_clock(vm_clock) + ticks_per_sec / 10);
+ return;
+ }
+
+ /* Success: Notify guest that THR is empty. */
+ s->thr_ipending = 1;
+ s->lsr |= UART_LSR_THRE;
+ s->lsr |= UART_LSR_TEMT;
+ serial_update_irq(s);
+}
+
static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
SerialState *s = opaque;
- unsigned char ch;
addr &= 7;
#ifdef DEBUG_SERIAL
@@ -223,12 +254,9 @@ static void serial_ioport_write(void *op
s->thr_ipending = 0;
s->lsr &= ~UART_LSR_THRE;
serial_update_irq(s);
- ch = val;
- qemu_chr_write(s->chr, &ch, 1);
- s->thr_ipending = 1;
- s->lsr |= UART_LSR_THRE;
- s->lsr |= UART_LSR_TEMT;
- serial_update_irq(s);
+ s->write_chr = val;
+ s->write_retries = 0;
+ serial_chr_write(s);
}
break;
case 1:
@@ -424,6 +452,7 @@ SerialState *serial_init(SetIRQFunc *set
s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
s->iir = UART_IIR_NO_INT;
s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
+ s->write_retry_timer = qemu_new_timer(vm_clock, serial_chr_write, s);
register_savevm("serial", base, 1, serial_save, serial_load, s);
@@ -511,6 +540,7 @@ SerialState *serial_mm_init (SetIRQFunc
s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
s->base = base;
s->it_shift = it_shift;
+ s->write_retry_timer = qemu_new_timer(vm_clock, serial_chr_write, s);
register_savevm("serial", base, 1, serial_save, serial_load, s);
diff -r b3d94f4ddffe -r c33272c2571c tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Sat Oct 28 12:30:38 2006 +0100
+++ b/tools/ioemu/vl.c Mon Oct 30 09:45:17 2006 +0000
@@ -1684,7 +1684,7 @@ static void tty_serial_init(int fd, int
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|INLCR|IGNCR|ICRNL|IXON);
- tty.c_oflag |= OPOST;
+ tty.c_oflag &= ~OPOST; /* no output mangling of raw serial stream */
tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS);
switch(data_bits) {
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|