All of lore.kernel.org
 help / color / mirror / Atom feed
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

  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.