diff options
Diffstat (limited to 'hw/serial.c')
-rw-r--r-- | hw/serial.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/hw/serial.c b/hw/serial.c index ac04e65225..75be4de12e 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -85,6 +85,7 @@ struct SerialState { int thr_ipending; int irq; CharDriverState *chr; + int last_break_enable; }; static void serial_update_irq(SerialState *s) @@ -103,6 +104,32 @@ static void serial_update_irq(SerialState *s) } } +static void serial_update_parameters(SerialState *s) +{ + int speed, parity, data_bits, stop_bits; + + if (s->lcr & 0x08) { + if (s->lcr & 0x10) + parity = 'E'; + else + parity = 'O'; + } else { + parity = 'N'; + } + if (s->lcr & 0x04) + stop_bits = 2; + else + stop_bits = 1; + data_bits = (s->lcr & 0x03) + 5; + if (s->divider == 0) + return; + speed = 115200 / s->divider; +#if 0 + printf("speed=%d parity=%c data=%d stop=%d\n", + speed, parity, data_bits, stop_bits); +#endif +} + static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) { SerialState *s = opaque; @@ -117,6 +144,7 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) case 0: if (s->lcr & UART_LCR_DLAB) { s->divider = (s->divider & 0xff00) | val; + serial_update_parameters(s); } else { s->thr_ipending = 0; s->lsr &= ~UART_LSR_THRE; @@ -132,6 +160,7 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) case 1: if (s->lcr & UART_LCR_DLAB) { s->divider = (s->divider & 0x00ff) | (val << 8); + serial_update_parameters(s); } else { s->ier = val & 0x0f; if (s->lsr & UART_LSR_THRE) { @@ -143,7 +172,16 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) case 2: break; case 3: - s->lcr = val; + { + int break_enable; + s->lcr = val; + serial_update_parameters(s); + break_enable = (val >> 6) & 1; + if (break_enable != s->last_break_enable) { + s->last_break_enable = break_enable; + qemu_chr_set_serial_break(s, break_enable); + } + } break; case 4: s->mcr = val & 0x1f; |