On Fri, 5 Sep 2025, [email protected] wrote:
> From: Denis Mukhin <[email protected]>
>
> Add MCR/MSR registers emulation to the I/O port handler.
>
> Add implementation of ns16x50_iir_check_msi().
>
> Signed-off-by: Denis Mukhin <[email protected]>
> ---
> Changes in v5:
> - Moved earlier in the series
> - Link to v5:
> https://lore.kernel.org/xen-devel/[email protected]/
> ---
> xen/common/emul/vuart/ns16x50.c | 62 ++++++++++++++++++++++++++++++++-
> 1 file changed, 61 insertions(+), 1 deletion(-)
>
> diff --git a/xen/common/emul/vuart/ns16x50.c b/xen/common/emul/vuart/ns16x50.c
> index 9d1fe0284362..a8ec9f6c3a04 100644
> --- a/xen/common/emul/vuart/ns16x50.c
> +++ b/xen/common/emul/vuart/ns16x50.c
> @@ -108,7 +108,7 @@ static bool cf_check ns16x50_iir_check_thr(const struct
> vuart_ns16x50 *vdev)
>
> static bool cf_check ns16x50_iir_check_msi(const struct vuart_ns16x50 *vdev)
> {
> - return false;
> + return vdev->regs[UART_MSR] & UART_MSR_CHANGE;
> }
>
> /*
> @@ -230,12 +230,63 @@ static int ns16x50_io_write8(
> regs[UART_LCR] = val;
> break;
>
> + case UART_MCR: {
> + uint8_t msr_curr, msr_next, msr_delta;
> +
> + msr_curr = regs[UART_MSR];
> + msr_next = 0;
> + msr_delta = 0;
> +
> + if ( val & UART_MCR_RESERVED0 )
> + ns16x50_warn(vdev, "MCR: attempt to set reserved bit: %x\n",
> + UART_MCR_RESERVED0);
> +
> + if ( val & UART_MCR_TCRTLR )
> + ns16x50_warn(vdev, "MCR: not supported: %x\n",
> + UART_MCR_TCRTLR);
> +
> + if ( val & UART_MCR_RESERVED1 )
> + ns16x50_warn(vdev, "MCR: attempt to set reserved bit: %x\n",
> + UART_MCR_RESERVED1);
> +
> + /* Set modem status */
> + if ( val & UART_MCR_LOOP )
> + {
> + if ( val & UART_MCR_DTR )
> + msr_next |= UART_MSR_DSR;
> + if ( val & UART_MCR_RTS )
> + msr_next |= UART_MSR_CTS;
> + if ( val & UART_MCR_OUT1 )
> + msr_next |= UART_MSR_RI;
> + if ( val & UART_MCR_OUT2 )
> + msr_next |= UART_MSR_DCD;
> + }
> + else
> + msr_next |= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS;
> +
> + /* Calculate changes in modem status */
> + if ( (msr_curr & UART_MSR_CTS) ^ (msr_next & UART_MSR_CTS) )
> + msr_delta |= UART_MSR_DCTS;
> + if ( (msr_curr & UART_MSR_DSR) ^ (msr_next & UART_MSR_DSR) )
> + msr_delta |= UART_MSR_DDSR;
> + if ( (msr_curr & UART_MSR_RI) & (msr_next & UART_MSR_RI) )
> + msr_delta |= UART_MSR_TERI;
Should this be:
if ( (msr_curr & UART_MSR_RI) && !(msr_next & UART_MSR_RI) )
msr_delta |= UART_MSR_TERI;
?
> + if ( (msr_curr & UART_MSR_DCD) ^ (msr_next & UART_MSR_DCD) )
> + msr_delta |= UART_MSR_DDCD;
> +
> + regs[UART_MCR] = val & UART_MCR_MASK;
> + regs[UART_MSR] = msr_next | msr_delta;
> +
> + break;
> + }