[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v7 07/16] emul/ns16x50: implement LCR/LSR registers



Hi Denis,

Thank you for the patch.

On Tue, Sep 9, 2025 at 1:16 AM <dmukhin@xxxxxxx> wrote:
>
> From: Denis Mukhin <dmukhin@xxxxxxxx>
>
> Add LCR/LSR registers implementation to the I/O port handler.
>
> Add implementation of ns16x50_dlab_get() and ns16x50_iir_check_lsi().
>
> Signed-off-by: Denis Mukhin <dmukhin@xxxxxxxx>
> ---
> Changes since v6:
> - n/a
> ---
>  xen/common/emul/vuart/ns16x50.c | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/xen/common/emul/vuart/ns16x50.c b/xen/common/emul/vuart/ns16x50.c
> index 664d799ddaee..0831a576cd9e 100644
> --- a/xen/common/emul/vuart/ns16x50.c
> +++ b/xen/common/emul/vuart/ns16x50.c
> @@ -87,12 +87,12 @@ struct vuart_ns16x50 {
>
>  static uint8_t ns16x50_dlab_get(const struct vuart_ns16x50 *vdev)
>  {
> -    return 0;
> +    return vdev->regs[UART_LCR] & UART_LCR_DLAB ? 1 : 0;
>  }
>
>  static bool cf_check ns16x50_iir_check_lsi(const struct vuart_ns16x50 *vdev)
>  {
> -    return false;
> +    return vdev->regs[UART_LSR] & UART_LSR_MASK;
>  }
>
>  static bool cf_check ns16x50_iir_check_rda(const struct vuart_ns16x50 *vdev)
> @@ -228,11 +228,16 @@ static int ns16x50_io_write8(
>              regs[UART_IER] = val & UART_IER_MASK;
>              break;
>
> +        case UART_LCR:
> +            regs[UART_LCR] = val;

I understand that this register is mostly used to control the hardware
behavior, but I think we should pay attention to Bit 7 in this register:

    Bit 7: Divisor Latch Access Bit (DLAB). It must be set high (logic 1)
    to access the Divisor Latches of the Baud Generator during a read or
    write operation. It must be set low (logic 0) to access the Receiver
    Buffer, the Transmitter Holding Register, or the Interrupt Enable
    Register.

I know that you are checking it before accessing DLAB registers, but what
about accesses to RBR, THR, and IER?

> +            break;
> +
>          /* NB: Firmware (e.g. OVMF) may rely on SCR presence. */
>          case UART_SCR:
>              regs[UART_SCR] = val;
>              break;
>
> +        case UART_LSR: /* RO */

Is there a reason we cannot simply leave this unchanged?

>          default:
>              rc = -EINVAL;
>              break;
> @@ -314,6 +319,15 @@ static int ns16x50_io_read8(
>              val = ns16x50_iir_get(vdev);
>              break;
>
> +        case UART_LCR:
> +            val = regs[UART_LCR];
> +            break;
> +
> +        case UART_LSR:
> +            val = regs[UART_LSR] | UART_LSR_THRE | UART_LSR_TEMT;

Why are UART_LSR_THRE and UART_LSR_TEMT set unconditionally?
What about UART_LSR_DR?

> +            regs[UART_LSR] = val & ~UART_LSR_MASK;

Maybe it would be good to mention why we are not resetting
UART_LSR_PE and UART_LSR_FE on read.

> +            break;
> +
>          case UART_SCR:
>              val = regs[UART_SCR];
>              break;
> --
> 2.51.0
>
>

Best regards,
Mykola



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.