From: Anthony Liguori <anthony@codemonkey.ws>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] upgrading emulated UART to 16550A
Date: Thu, 07 Aug 2008 13:58:43 -0500 [thread overview]
Message-ID: <489B45E3.9040005@codemonkey.ws> (raw)
In-Reply-To: <489B3278.4080001@eu.citrix.com>
Stefano Stabellini wrote:
> This is an improved version of the UART 16550A emulation patch.
> The changes compared to previous version are:
>
> - no token bucket anymore;
>
> - fixed a small bug handling IRQs; this was the problem that prevented
> kgdb to work over the serial (thanks to Jason Wessel for the help
> spotting and reproducing this bug).
>
> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
>
> ---
>
> diff --git a/hw/serial.c b/hw/serial.c
> index ffd6ac9..5aab00e 100644
> --- a/hw/serial.c
> +++ b/hw/serial.c
> @@ -1,7 +1,7 @@
> /*
> - * QEMU 16450 UART emulation
> + * QEMU 16550A UART emulation
> *
> - * Copyright (c) 2003-2004 Fabrice Bellard
> + * Copyright (c) 2003-2008 Fabrice Bellard
>
I think the idea was to add a new copyright entry, not to modify
Fabrice's copyright.
> *
> * Permission is hereby granted, free of charge, to any person obtaining a copy
> * of this software and associated documentation files (the "Software"), to deal
> @@ -21,6 +21,10 @@
> * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> * THE SOFTWARE.
> */
> +
> +#include <termios.h>
> +#include <sys/ioctl.h>
>
This doesn't look Windows friendly.
> @@ -100,55 +131,105 @@ struct SerialState {
> target_phys_addr_t base;
> int it_shift;
> int baudbase;
> - QEMUTimer *tx_timer;
> - int tx_burst;
> + int tsr_retry;
> +
> + uint64_t last_xmit_ts; /* Time when the last byte was successfully sent out of the tsr */
> + SerialFIFO recv_fifo;
> + SerialFIFO xmit_fifo;
> +
> + struct QEMUTimer *fifo_timeout_timer;
> + int timeout_ipending; /* timeout interrupt pending state */
> + struct QEMUTimer *transmit_timer;
> +
> +
> + uint64_t char_transmit_time; /* time to transmit a char in ticks*/
> + int poll_msl;
> +
> + struct QEMUTimer *modem_status_poll;
> };
>
> +static void serial_receive1(void *opaque, const uint8_t *buf, int size);
> +
> +static void fifo_clear(SerialState *s, int fifo) {
>
minor nit, but the '{' should be on a new line.
> + SerialFIFO *f = ( fifo ) ? &s->recv_fifo : &s->xmit_fifo;
> + memset(f->data, 0, UART_FIFO_LENGTH);
> + f->count = 0;
> + f->head = 0;
> + f->tail = 0;
> +}
> +
> +static int fifo_put(SerialState *s, int fifo, uint8_t chr) {
> + SerialFIFO *f = ( fifo ) ? &s->recv_fifo : &s->xmit_fifo;
> +
> + f->data[f->head++] = chr;
> +
> + if (f->head == UART_FIFO_LENGTH)
> + f->head = 0;
> + f->count++;
> +
> + return 1;
> +}
> +
> +uint8_t fifo_get(SerialState *s, int fifo) {
>
Any reason for this not to be static?
> -static void serial_tx_done(void *opaque)
> -{
> - SerialState *s = opaque;
>
> - if (s->tx_burst < 0) {
> - uint16_t divider;
> + if ( ( s->ier & UART_IER_RLSI ) && (s->lsr & UART_LSR_INT_ANY ) ) {
> + tmp_iir = UART_IIR_RLSI;
> + } else if ( s->timeout_ipending ) {
> + tmp_iir = UART_IIR_CTI;
> + } else if ( ( s->ier & UART_IER_RDI ) && (s->lsr & UART_LSR_DR ) ) {
> + if ( !(s->fcr & UART_FCR_FE) ) {
> + tmp_iir = UART_IIR_RDI;
> + } else if ( s->recv_fifo.count >= s->recv_fifo.itl ) {
> + tmp_iir = UART_IIR_RDI;
> + }
> + } else if ( (s->ier & UART_IER_THRI) && s->thr_ipending ) {
> + tmp_iir = UART_IIR_THRI;
> + } else if ( (s->ier & UART_IER_MSI) && (s->msr & UART_MSR_ANY_DELTA) ) {
> + tmp_iir = UART_IIR_MSI;
> + }
>
> - if (s->divider)
> - divider = s->divider;
> - else
> - divider = 1;
> + s->iir = tmp_iir | ( s->iir & 0xF0 );
>
> - /* We assume 10 bits/char, OK for this purpose. */
> - s->tx_burst = THROTTLE_TX_INTERVAL * 1000 /
> - (1000000 * 10 / (s->baudbase / divider));
> + if ( tmp_iir != UART_IIR_NO_INT ) {
> + qemu_irq_raise(s->irq);
> + } else {
> + qemu_irq_lower(s->irq);
>
More nits, lose the whitespace in the conditions. For instance:
} else if ( ( s->ier & UART_IER_RDI ) => } else if ((s->ier &
UART_IER_RDI).
The rest of the file uses the later style so it's a little weird to have
portions of the code be different.
> }
> - s->thr_ipending = 1;
> - s->lsr |= UART_LSR_THRE;
> - s->lsr |= UART_LSR_TEMT;
> - serial_update_irq(s);
> }
>
> static void serial_update_parameters(SerialState *s)
> {
> - int speed, parity, data_bits, stop_bits;
> + int speed, parity, data_bits, stop_bits, frame_size;
> QEMUSerialSetParams ssp;
>
> + if (s->divider == 0)
> + return;
> +
> + frame_size = 1;
> if (s->lcr & 0x08) {
> if (s->lcr & 0x10)
> parity = 'E';
> @@ -156,19 +237,21 @@ static void serial_update_parameters(SerialState *s)
> parity = 'O';
> } else {
> parity = 'N';
> + frame_size = 0;
> }
> if (s->lcr & 0x04)
> stop_bits = 2;
> else
> stop_bits = 1;
> +
> data_bits = (s->lcr & 0x03) + 5;
> - if (s->divider == 0)
> - return;
> + frame_size += data_bits + stop_bits;
> speed = s->baudbase / s->divider;
> ssp.speed = speed;
> ssp.parity = parity;
> ssp.data_bits = data_bits;
> ssp.stop_bits = stop_bits;
> + s->char_transmit_time = ( ticks_per_sec / speed ) * frame_size;
> qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
> #if 0
> printf("speed=%d parity=%c data=%d stop=%d\n",
> @@ -176,6 +259,88 @@ static void serial_update_parameters(SerialState *s)
> #endif
> }
>
> +static void serial_update_msl( SerialState *s )
>
More bad whitespace.
> +static void serial_xmit(void *opaque) {
> + SerialState *s = opaque;
> + uint64_t new_xmit_ts = qemu_get_clock(vm_clock);
> +
> + if ( s->tsr_retry <= 0 ) {
> + if (s->fcr & UART_FCR_FE) {
> + s->tsr = fifo_get(s,XMIT_FIFO);
> + if ( !s->xmit_fifo.count )
> + s->lsr |= UART_LSR_THRE;
> + } else {
> + s->tsr = s->thr;
> + s->lsr |= UART_LSR_THRE;
> + }
> + }
> +
> + if ( (s->mcr & UART_MCR_LOOP
> + /* in loopback mode, say that we just received a char */
> + ? (serial_receive1(s, &s->tsr, 1), 1)
> + : qemu_chr_write(s->chr, &s->tsr, 1))
>
This is just nutty :-) Please rewrite this if() statement to be a
little less obscure.
> @@ -524,18 +832,11 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
> s = qemu_mallocz(sizeof(SerialState));
> if (!s)
> return NULL;
> - s->irq = irq;
> +
> s->base = base;
> s->it_shift = it_shift;
> - s->baudbase= baudbase;
> -
> - s->tx_timer = qemu_new_timer(vm_clock, serial_tx_done, s);
> - if (!s->tx_timer)
> - return NULL;
> -
> - qemu_register_reset(serial_reset, s);
> - serial_reset(s);
>
> + serial_init_core(s, irq, baudbase, chr);
> register_savevm("serial", base, 2, serial_save, serial_load, s);
>
Isn't it necessary to bump the savevm() version number since you've
changed the format.
Regards,
Anthony Liguori
next prev parent reply other threads:[~2008-08-07 18:59 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-07 17:35 [Qemu-devel] [PATCH] upgrading emulated UART to 16550A Stefano Stabellini
2008-08-07 18:58 ` Anthony Liguori [this message]
2008-08-07 21:02 ` Samuel Thibault
2008-08-07 21:13 ` Anthony Liguori
2008-08-07 21:39 ` Samuel Thibault
2008-08-08 14:36 ` Stefano Stabellini
2008-08-07 19:26 ` Jason Wessel
-- strict thread matches above, loose matches on Subject: below --
2008-08-08 16:58 Stefano Stabellini
2008-08-09 18:26 ` Anthony Liguori
2008-08-09 18:44 ` Samuel Thibault
2008-08-11 14:17 ` Anthony Liguori
2008-08-08 14:55 Stefano Stabellini
2008-08-08 15:15 ` Stefano Stabellini
2008-08-05 13:15 Stefano Stabellini
2008-08-05 13:57 ` Thiemo Seufer
2008-08-05 14:17 ` Stefano Stabellini
2008-08-05 15:02 ` Jason Wessel
2008-08-05 15:15 ` Stefano Stabellini
2008-08-06 2:28 ` Anthony Liguori
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=489B45E3.9040005@codemonkey.ws \
--to=anthony@codemonkey.ws \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).