From: Denis Mukhin <dmukhin@ford.com>
Implement put_rx() vUART hook for placing a character into the emulated RX
FIFO from console driver.
That implements physical console forwarding to the guest OS over emulated
NS16550.
Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
Changes since v4:
- new patch
---
xen/common/emul/vuart/ns16x50.c | 48 ++++++++++++++++++++++++++++++++-
1 file changed, 47 insertions(+), 1 deletion(-)
diff --git a/xen/common/emul/vuart/ns16x50.c b/xen/common/emul/vuart/ns16x50.c
index d57695564329..1fb65370d464 100644
--- a/xen/common/emul/vuart/ns16x50.c
+++ b/xen/common/emul/vuart/ns16x50.c
@@ -804,13 +804,59 @@ static void cf_check ns16x50_free(void *arg)
XVFREE(vdev);
}
+static int cf_check ns16x50_put_rx(void *arg, char ch)
+{
+ struct vuart_ns16x50 *vdev = arg;
+ uint8_t *regs;
+ uint8_t dlab;
+ int rc = -EBUSY;
+
+ spin_lock(&vdev->lock);
+
+ dlab = ns16x50_dlab_get(vdev);
+ regs = vdev->regs;
+
+ if ( dlab )
+ ns16x50_debug(vdev, "THR/RBR access disabled: DLAB=1\n");
+ else if ( regs[UART_MCR] & UART_MCR_LOOP )
+ ns16x50_debug(vdev, "THR/RBR access disabled: loopback mode\n");
+ else
+ {
+ struct vuart *vuart = container_of(arg, struct vuart, vdev);
+ struct domain *d = vuart->owner;
+ uint8_t val = 0;
+
+ rc = ns16x50_fifo_rx_putchar(vdev, ch);
+ if ( rc == -ENOSPC )
+ val |= UART_LSR_OE;
+
+ /* NB: UART_LSR_DR is also set when UART_LSR is accessed. */
+ regs[UART_LSR] |= UART_LSR_DR | val;
+
+ /*
+ * Echo the user input on Xen console iff Xen console input is owned
+ * by ns16x50 domain.
+ * NB: use 'console_timestamps=none' to disable Xen timestamps.
+ */
+ if ( is_console_printable(ch) )
+ guest_printk(d, "%c", ch);
+
+ /* FIXME: check FCR when to fire an interrupt */
+ ns16x50_irq_check(vdev);
+ }
+
+ spin_unlock(&vdev->lock);
+
+ return rc;
+}
+
#define ns16x50_emulator \
{ \
.compatible = "ns16550", \
.alloc = ns16x50_alloc, \
.free = ns16x50_free, \
.dump_state = NULL, \
- .put_rx = NULL, \
+ .put_rx = ns16x50_put_rx, \
}
VUART_REGISTER(ns16x50, ns16x50_emulator);
--
2.51.0