|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XTF PATCH v1 6/6] x86: add NS16550-compatible emulator test
From: Denis Mukhin <dmukhin@xxxxxxxx>
Add initial test suite for NS16550-compatible emulator.
Signed-off-by: Denis Mukhin <dmukhin@xxxxxxxx>
---
tests/emul-ns16x50/.gitignore | 3 +
tests/emul-ns16x50/Makefile | 9 +
tests/emul-ns16x50/main.c | 644 ++++++++++++++++++++++++++++++++++
tests/emul-ns16x50/patterns.c | 65 ++++
4 files changed, 721 insertions(+)
create mode 100644 tests/emul-ns16x50/.gitignore
create mode 100644 tests/emul-ns16x50/Makefile
create mode 100644 tests/emul-ns16x50/main.c
create mode 100644 tests/emul-ns16x50/patterns.c
diff --git a/tests/emul-ns16x50/.gitignore b/tests/emul-ns16x50/.gitignore
new file mode 100644
index 000000000000..28fbd61de7b5
--- /dev/null
+++ b/tests/emul-ns16x50/.gitignore
@@ -0,0 +1,3 @@
+*.swo
+*.swp
+
diff --git a/tests/emul-ns16x50/Makefile b/tests/emul-ns16x50/Makefile
new file mode 100644
index 000000000000..11ddfc82fb74
--- /dev/null
+++ b/tests/emul-ns16x50/Makefile
@@ -0,0 +1,9 @@
+include $(ROOT)/build/common.mk
+
+NAME := emul-ns16x50
+CATEGORY := functional
+TEST-ENVS := hvm64
+
+obj-perenv += main.o patterns.o
+
+include $(ROOT)/build/gen.mk
diff --git a/tests/emul-ns16x50/main.c b/tests/emul-ns16x50/main.c
new file mode 100644
index 000000000000..39a566d2b1d5
--- /dev/null
+++ b/tests/emul-ns16x50/main.c
@@ -0,0 +1,644 @@
+/**
+ * Tests for NS16550-compatible emulator.
+ */
+
+#include <xtf.h>
+#include <xtf/ns16550.h>
+
+const char test_title[] = "NS16550-compatible emulator tests";
+
+extern const char *pattern_4096;
+
+#define COM_PORT(n,b) \
+{ \
+ .name = n, \
+ .base = b, \
+ .reg_shift = 0, \
+ .reg_width = 1, \
+ .clk_freq = 1843200U, \
+ .baud = 115200U, \
+}
+
+/*
+ * PC COM ports.
+ */
+static const struct ns16550 com_ports[] = {
+ COM_PORT("com1", 0x3f8U),
+ COM_PORT("com2", 0x2f8U),
+ COM_PORT("com3", 0x3e8U),
+ COM_PORT("com4", 0x2e8U),
+};
+
+static const struct ns16550 *uart;
+
+static int ns16550_parse_cmdline(const char *s)
+{
+ const char *console = "console=";
+ size_t console_len = strlen(console);
+ unsigned int idx;
+
+ if (!s)
+ return -1;
+
+ /* console=com2 */
+ while ( *s && *s == ' ' )
+ s++;
+
+ if ( strncmp(s, console, console_len) )
+ return -1;
+
+ s += console_len;
+
+ for ( idx = 0; idx < ARRAY_SIZE(com_ports); idx++ )
+ if ( !strncmp(s, com_ports[idx].name, strlen(com_ports[idx].name)) )
+ break;
+
+ if ( idx == ARRAY_SIZE(com_ports) )
+ return -1;
+
+ return idx;
+}
+
+void test_setup(void)
+{
+ const char *cmdline;
+ int idx;
+
+ if ( !IS_DEFINED(CONFIG_HVM) )
+ return xtf_skip("N/A\n");
+
+ cmdline = (const char *)(uintptr_t)pvh_start_info->cmdline_paddr;
+ idx = ns16550_parse_cmdline(cmdline);
+ if ( idx < 0 )
+ return xtf_failure("not configured\n");
+
+ uart = &com_ports[idx];
+ printk("Testing with %s (0x%lx)...\n", uart->name, uart->base);
+
+ if ( ns16550_init(uart) )
+ return xtf_failure("failed to initialize\n");
+}
+
+static void test_thr(const char *banner)
+{
+ uint8_t iir;
+
+ ns16550_outb(uart, UART_IER, UART_IER_ETHREI);
+
+ ns16550_puts(uart, pattern_4096);
+
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( (iir & (UART_IIR_NOINT | UART_IIR_THR)) == UART_IIR_NOINT )
+ return xtf_failure("%s: expect UART_IIR_THR\n", banner);
+
+ ns16550_outb(uart, UART_IER, 0);
+}
+
+static void test_scr(const char *banner)
+{
+ unsigned int in, out;
+
+ /* Enable all interrupt reasons */
+ ns16550_outb(uart, UART_IER,
+ UART_IER_ERDAI | UART_IER_ETHREI |
+ UART_IER_ELSI | UART_IER_EMSI);
+
+ for ( in = 0; in < 256; in++ )
+ {
+ ns16550_outb(uart, UART_SCR, in);
+ out = ns16550_inb(uart, UART_SCR);
+ if ( in != out )
+ return xtf_failure("%s: wrote 0x%02x, read 0x%02x\n",
+ banner, in, out);
+ }
+
+ ns16550_outb(uart, UART_IER, 0);
+}
+
+static void test_lcr(const char *banner)
+{
+ static const uint8_t patterns[] = {
+ 0,
+ UART_LCR_WLEN8,
+ UART_LCR_WLEN8 | UART_LCR_STB,
+ UART_LCR_WLEN7 | UART_LCR_PE | UART_LCR_EP,
+ UART_LCR_WLEN8 | UART_LCR_SB,
+ UART_LCR_WLEN8 | UART_LCR_DLAB,
+ 0xff,
+ };
+ unsigned int i;
+
+ for ( i = 0; i < ARRAY_SIZE(patterns); i++ )
+ {
+ uint8_t r;
+
+ ns16550_outb(uart, UART_LCR, patterns[i]);
+ r = ns16550_inb(uart, UART_LCR);
+ if ( r != patterns[i] )
+ xtf_failure("%s: wrote %#x, read %#x\n",
+ banner, patterns[i], r);
+ }
+
+ ns16550_outb(uart, UART_LCR, UART_LCR_8N1);
+}
+
+static void test_ier(const char *banner)
+{
+ uint8_t in, out;
+
+ /* Test valid permutations. */
+ for ( out = 0; out <= UART_IER_MASK; out++ )
+ {
+ ns16550_outb(uart, UART_IER, out);
+ in = ns16550_inb(uart, UART_IER);
+ if ( in != out )
+ xtf_failure("%s: wrote %#x, read %#x\n",
+ banner, out, in);
+ }
+
+ /* Ensure reserved bits are not touched. */
+ out = 0xff;
+ ns16550_outb(uart, UART_IER, out);
+ in = ns16550_inb(uart, UART_IER);
+ if ( in != UART_IER_MASK )
+ xtf_failure("%s: wrote %x, read %#x (expected %x)\n",
+ banner, out, in, UART_IER_MASK);
+}
+
+static void test_divisor_latch(const char *banner)
+{
+ /*
+ * divisor = 115200 / baud
+ * divisor 0 is invalid
+ *
+ * DLL = divisor & 0xff
+ * DLM = divisor >> 8
+ */
+ static const struct {
+ uint8_t dll;
+ uint8_t dlm;
+ } baud_rates[] = {
+ { 0x00, 0x00 }, /* unsupported */
+ { 0xff, 0xff }, /* unsupported */
+ { 0x00, 0x09 }, /* 50 baud */
+ { 0x00, 0x06 }, /* 75 baud */
+ { 0x17, 0x04 }, /* 110 baud (approx) */
+ { 0x59, 0x03 }, /* 134.5 baud (approx) */
+ { 0x00, 0x03 }, /* 150 baud */
+ { 0x80, 0x01 }, /* 300 baud */
+ { 0xc0, 0x00 }, /* 600 baud */
+ { 0x60, 0x00 }, /* 1200 baud */
+ { 0x40, 0x00 }, /* 1800 baud */
+ { 0x3a, 0x00 }, /* 2000 baud (approx) */
+ { 0x30, 0x00 }, /* 2400 baud */
+ { 0x20, 0x00 }, /* 3600 baud */
+ { 0x18, 0x00 }, /* 4800 baud */
+ { 0x10, 0x00 }, /* 7200 baud */
+ { 0x0c, 0x00 }, /* 9600 baud */
+ { 0x08, 0x00 }, /* 14400 baud */
+ { 0x06, 0x00 }, /* 19200 baud */
+ { 0x04, 0x00 }, /* 28800 baud */
+ { 0x03, 0x00 }, /* 38400 baud */
+ { 0x02, 0x00 }, /* 57600 baud */
+ { 0x01, 0x00 }, /* 115200 baud */
+ };
+ unsigned i, n;
+
+ /* DLAB=0 */
+ ns16550_outb(uart, UART_LCR, UART_LCR_8N1);
+ /* Plant IER - that will be asserted later */
+ ns16550_outb(uart, UART_IER, UART_IER_MASK);
+
+ for ( i = 0; i < ARRAY_SIZE(baud_rates); i++ )
+ {
+ uint8_t dll, dlm, r;
+
+ /* DLAB=1 */
+ ns16550_outb(uart, UART_LCR, UART_LCR_DLAB);
+
+ /* Pre-poison to catch any cross-write. */
+ ns16550_outb(uart, UART_DLL, ~baud_rates[i].dll);
+ ns16550_outb(uart, UART_DLM, ~baud_rates[i].dlm);
+
+ ns16550_outb(uart, UART_DLL, baud_rates[i].dll);
+ ns16550_outb(uart, UART_DLM, baud_rates[i].dlm);
+
+ dll = ns16550_inb(uart, UART_DLL);
+ dlm = ns16550_inb(uart, UART_DLM);
+
+ if ( dll != baud_rates[i].dll || dlm != baud_rates[i].dlm )
+ xtf_failure("%s: 1st attempt failed: wrote {%#x,%#x}, read
{%#x,%#x}\n",
+ banner,
+ baud_rates[i].dll, baud_rates[i].dlm,
+ dll, dlm);
+
+ /* Flip DLAB, plant THR, assert on planted IER */
+ for ( n = 0; n < 8; n++ )
+ {
+ ns16550_outb(uart, UART_LCR, UART_LCR_8N1);
+
+ /* THR offset is the same as DLL */
+ ns16550_outb(uart, UART_THR, '\0');
+
+ /* IER offset is the same as DLM */
+ r = ns16550_inb(uart, UART_IER);
+ if ( r != UART_IER_MASK )
+ xtf_failure("%s: IER not survided DLAB flip %d: read %#x
expect %#x\n",
+ banner, n, r, UART_IER_MASK);
+
+ ns16550_outb(uart, UART_LCR, UART_LCR_DLAB);
+ }
+
+ /* Check divisor latch survives */
+ dll = ns16550_inb(uart, UART_DLL);
+ dlm = ns16550_inb(uart, UART_DLM);
+
+ if ( dll != baud_rates[i].dll || dlm != baud_rates[i].dlm )
+ xtf_failure("%s: 2nd attempt failed: wrote {%#x,%#x}, read
{%#x,%#x}\n",
+ banner,
+ baud_rates[i].dll, baud_rates[i].dlm,
+ dll, dlm);
+
+ /* DLAB=0 */
+ ns16550_outb(uart, UART_LCR, UART_LCR_8N1);
+ }
+}
+
+static void test_mcr(const char *banner)
+{
+ uint8_t in, out;
+
+ /*
+ * Test combinations of DTR/RTS/OUT1/OUT2 except LOOP, which
+ * is exercised by a separate test.
+ */
+ for ( out = 0; out <= (UART_MCR_DTR | UART_MCR_RTS |
+ UART_MCR_OUT1 | UART_MCR_OUT2); out++ )
+ {
+ ns16550_outb(uart, UART_MCR, out);
+ in = ns16550_inb(uart, UART_MCR);
+ if ( in != out )
+ xtf_failure("%s: wrote %#x, read %#x\n", banner, in, out);
+ }
+
+ /*
+ * Reserved bits must read as zero.
+ */
+ ns16550_outb(uart, UART_MCR, 0xff);
+ in = ns16550_inb(uart, UART_MCR);
+ if ( in & ~UART_MCR_MASK )
+ xtf_failure("%s: reserved bits readable: %#x\n", banner, in);
+
+ ns16550_outb(uart, UART_MCR, 0);
+}
+
+static void test_fcr_toggle(const char *banner)
+{
+ uint8_t iir;
+
+ ns16550_outb(uart, UART_FCR, 0);
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( iir & UART_IIR_FE )
+ xtf_failure("%s: IIR FIFO bits set with UART_FCR_ENABLE clear: %#x\n",
+ banner, iir);
+
+ ns16550_outb(uart, UART_FCR, UART_FCR_ENABLE);
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( (iir & UART_IIR_FE) != UART_IIR_FE )
+ xtf_failure("%s: IIR FIFO bits not 0b11 with UART_FCR_ENABLE set:
%#x\n",
+ banner, iir);
+
+ ns16550_outb(uart, UART_FCR, 0);
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( iir & UART_IIR_FE )
+ xtf_failure("%s: IIR FIFO bits stuck after UART_FCR_ENABLE clear:
%#x\n",
+ banner, iir);
+}
+
+static void test_fcr_trigger(const char *banner)
+{
+ static const uint8_t levels[] = {
+ UART_FCR_TRG1,
+ UART_FCR_TRG4,
+ UART_FCR_TRG8,
+ UART_FCR_TRG14,
+ };
+ unsigned int i;
+
+ for ( i = 0; i < ARRAY_SIZE(levels); i++ )
+ {
+ uint8_t iir;
+
+ ns16550_outb(uart, UART_FCR, UART_FCR_ENABLE | levels[i]);
+ iir = ns16550_inb(uart, UART_IIR);
+
+#ifdef STRICT
+ if ( !(iir & UART_IIR_NOINT) )
+ xtf_failure("%s: FCR trigger %#x raised an interrupt (IIR %#x)\n",
+ banner, levels[i], iir);
+#endif
+ if ( (iir & UART_IIR_FE) != UART_IIR_FE )
+ xtf_failure("%s: FIFO indication lost at trigger %#x (IIR %#x)\n",
+ banner, levels[i], iir);
+ }
+}
+
+static void test_fcr_clear(const char *banner)
+{
+ unsigned int i;
+ uint8_t lsr;
+
+ ns16550_outb(uart, UART_IER, UART_IER_MASK);
+
+ for ( i = 0; i < 16; i++ )
+ {
+ ns16550_outb(uart, UART_FCR,
+ UART_FCR_ENABLE | UART_FCR_CLRX | UART_FCR_CLTX);
+ }
+
+ /* Plant a byte via loopback. */
+ ns16550_outb(uart, UART_MCR, UART_MCR_LOOP);
+ ns16550_outb(uart, UART_THR, 'A');
+
+ lsr = ns16550_inb(uart, UART_LSR);
+ if ( lsr & UART_LSR_DR )
+ {
+ ns16550_outb(uart, UART_FCR, UART_FCR_ENABLE | UART_FCR_CLRX);
+ lsr = ns16550_inb(uart, UART_LSR);
+ if ( lsr & UART_LSR_DR )
+ xtf_failure("%s: DR still set after UART_FCR_CLRX (LSR %#x)\n",
+ banner, lsr);
+
+ ns16550_outb(uart, UART_MCR, 0);
+ ns16550_outb(uart, UART_FCR, 0);
+ }
+ else
+ {
+ return xtf_failure("%s: loopback byte not delivered (LSR %#x)\n",
+ banner, lsr);
+ }
+}
+
+/*
+ * MCR.LOOP. Data path first, then the modem path (in loopback the
+ * four MCR outputs route to the four MSR inputs: DTR->DSR, RTS->CTS,
+ * OUT1->RI, OUT2->DCD).
+ */
+static void test_loopback_data_path(const char *banner)
+{
+ unsigned int v;
+
+ ns16550_outb(uart, UART_LCR, UART_LCR_8N1);
+ ns16550_outb(uart, UART_IER, 0);
+ ns16550_outb(uart, UART_FCR, UART_FCR_CLRX | UART_FCR_CLTX);
+
+ /* Discard any stale delta state. */
+ ns16550_inb(uart, UART_MSR);
+
+ ns16550_outb(uart, UART_MCR, UART_MCR_LOOP);
+ if ( !(ns16550_inb(uart, UART_MCR) & UART_MCR_LOOP) )
+ return xtf_failure("%s: UART_MCR_LOOP did not stick\n",
+ banner);
+
+ for ( v = 0; v < 256; v++ )
+ {
+ uint8_t lsr, r;
+
+ lsr = ns16550_inb(uart, UART_LSR);
+ if ( !(lsr & UART_LSR_THRE) )
+ return xtf_failure("%s: THRE clear before THR read %#x (LSR
%#x)\n",
+ banner, v, lsr);
+
+ ns16550_outb(uart, UART_THR, v);
+
+ lsr = ns16550_inb(uart, UART_LSR);
+ if ( !(lsr & UART_LSR_DR) )
+ return xtf_failure("%s: DR clear after THT read %#x (LSR %#x)\n",
+ banner, v, lsr);
+ if ( lsr & UART_LSR_ERRORS )
+ return xtf_failure("%s: error status after THR read %#x (LSR
%#x)\n",
+ banner, v, lsr);
+
+ r = ns16550_inb(uart, UART_RBR);
+ if ( r != v )
+ return xtf_failure("%s: loopback corrupted byte: sent %#x, got
%#x\n",
+ banner, v, r);
+
+ lsr = ns16550_inb(uart, UART_LSR);
+ if ( lsr & UART_LSR_DR )
+ return xtf_failure("%s: DR still set after draining RBR (LSR
%#x)\n",
+ banner, lsr);
+ }
+}
+
+static void test_loopback_modem_path(const char *banner)
+{
+ uint8_t msr, mask;
+
+ ns16550_outb(uart, UART_LCR, UART_LCR_8N1);
+ ns16550_outb(uart, UART_IER, 0);
+ ns16550_outb(uart, UART_FCR, UART_FCR_CLRX | UART_FCR_CLTX);
+
+ /* Discard any stale delta state. */
+ ns16550_inb(uart, UART_MSR);
+ ns16550_outb(uart, UART_MCR, UART_MCR_LOOP | UART_MCR_DTR |
+ UART_MCR_RTS | UART_MCR_OUT1 |
+ UART_MCR_OUT2);
+
+ if ( !(ns16550_inb(uart, UART_MCR) & UART_MCR_LOOP) )
+ return xtf_failure("%s: UART_MCR_LOOP did not stick\n",
+ banner);
+
+ msr = ns16550_inb(uart, UART_MSR);
+ mask = UART_MSR_CTS | UART_MSR_DSR | UART_MSR_RI | UART_MSR_DCD |
+ UART_MSR_DCTS | UART_MSR_DDSR | UART_MSR_TERI | UART_MSR_DDCD;
+ if ( msr != mask )
+ xtf_failure("%s: MSR after raising all outputs: %#x (expected %#x)\n",
+ banner, msr, mask);
+
+ /* The read above consumed the deltas; lines persist. */
+ msr = ns16550_inb(uart, UART_MSR);
+ mask = UART_MSR_CTS | UART_MSR_DSR | UART_MSR_RI | UART_MSR_DCD;
+ if ( msr != mask )
+ xtf_failure("%s: MSR deltas not cleared by read: %#x (expected %#x)\n",
+ banner, msr, mask);
+
+ /*
+ * Drop all outputs. Lines fall, DCTS/DDSR/DDCD latch again, and
+ * this time no TERI.
+ */
+ ns16550_outb(uart, UART_MCR, UART_MCR_LOOP);
+
+ msr = ns16550_inb(uart, UART_MSR);
+ mask = UART_MSR_DCTS | UART_MSR_DDSR | UART_MSR_DDCD;
+ if ( msr != mask )
+ xtf_failure("%s: MSR after dropping all outputs: %#x (expected %#x)\n",
+ banner, msr, mask);
+
+ msr = ns16550_inb(uart, UART_MSR);
+ if ( msr )
+ xtf_failure("%s: MSR not clear after delta consumption: %#x\n",
+ banner, msr);
+}
+
+static void test_iir_noint(const char *banner)
+{
+ uint8_t iir;
+
+ ns16550_outb(uart, UART_FCR, UART_FCR_CLRX | UART_FCR_CLTX);
+ ns16550_outb(uart, UART_MCR, UART_MCR_LOOP);
+ ns16550_outb(uart, UART_IER, 0);
+ ns16550_outb(uart, UART_THR, '\0');
+
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( !(iir & UART_IIR_NOINT) )
+ xtf_failure("%s: interrupt reported with IER == 0: IIR %#x\n",
+ banner, iir);
+}
+
+static void test_iir_thr_source(const char *banner)
+{
+ uint8_t iir;
+
+ ns16550_outb(uart, UART_FCR, UART_FCR_CLRX | UART_FCR_CLTX);
+ ns16550_outb(uart, UART_MCR, UART_MCR_LOOP);
+
+ /*
+ * THR is already empty, so enabling ETHREI must immediately
+ * assert the THR-empty source.
+ */
+ ns16550_outb(uart, UART_IER, UART_IER_ETHREI);
+
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( (iir & UART_IIR_MASK) != UART_IIR_THR )
+ xtf_failure("%s: THR source not asserted on ETHREI enable: IIR %#x\n",
+ banner, iir);
+
+ ns16550_outb(uart, UART_THR, '\0');
+ ns16550_drain_rx(uart);
+
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( (iir & UART_IIR_MASK) != UART_IIR_THR )
+ xtf_failure("%s: THR source not regenerated by THR write: IIR %#x\n",
+ banner, iir);
+
+ /* Disabling ETHREI must retract the indication. */
+ ns16550_outb(uart, UART_IER, 0);
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( !(iir & UART_IIR_NOINT) )
+ xtf_failure("%s: THR source survives ETHREI disable: IIR %#x\n",
+ banner, iir);
+}
+
+static void test_iir_rda_source(const char *banner)
+{
+ uint8_t iir;
+
+ ns16550_outb(uart, UART_FCR, UART_FCR_CLRX | UART_FCR_CLTX);
+ ns16550_outb(uart, UART_MCR, UART_MCR_LOOP);
+ ns16550_outb(uart, UART_IER, UART_IER_ERDAI);
+
+ /* Nothing pending yet. */
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( !(iir & UART_IIR_NOINT) )
+ xtf_failure("%s: RDA asserted with no Rx data: IIR %#x\n",
+ banner, iir);
+
+ /* Plant a byte; RDA must assert. */
+ ns16550_outb(uart, UART_THR, '\0');
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( (iir & UART_IIR_MASK) != UART_IIR_RDA )
+ xtf_failure("%s: RDA not asserted with Rx data pending: IIR %#x\n",
+ banner, iir);
+
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( (iir & UART_IIR_MASK) != UART_IIR_RDA )
+ xtf_failure("%s: RDA cleared by IIR read: IIR %#x\n",
+ banner, iir);
+
+ ns16550_inb(uart, UART_RBR);
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( !(iir & UART_IIR_NOINT) )
+ xtf_failure("%s: RDA not cleared by draining RBR: IIR %#x\n",
+ banner, iir);
+}
+
+static void test_iir_priority(const char *banner)
+{
+ uint8_t iir;
+
+ ns16550_outb(uart, UART_IER, UART_IER_ERDAI | UART_IER_ETHREI);
+ ns16550_outb(uart, UART_THR, '\0');
+
+ /*
+ * Priority order is LSI > RDA > timeout > THR > MSI
+ */
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( (iir & UART_IIR_MASK) != UART_IIR_RDA )
+ xtf_failure("%s: RDA does not outrank THR: IIR %#x\n",
+ banner, iir);
+
+ /*
+ * Drain Rx; THR-empty is still outstanding (the THR write above
+ * re-armed it, and no IIR read has identified it as the source
+ * while it was the highest priority), so IIR falls back to THR.
+ */
+ ns16550_inb(uart, UART_RBR);
+ iir = ns16550_inb(uart, UART_IIR);
+ if ( (iir & UART_IIR_MASK) != UART_IIR_THR )
+ xtf_failure("%s: THR not reported after RDA drained: IIR %#x\n",
+ banner, iir);
+}
+
+struct test_case {
+ const char *banner;
+ void (*run)(const char *banner);
+};
+
+#define TEST_CASE(b, r) { .banner = (b), .run = (r) }
+
+static const struct test_case test_suite[] = {
+ TEST_CASE("THR", test_thr),
+ TEST_CASE("SCR", test_scr),
+ TEST_CASE("LCR", test_lcr),
+ TEST_CASE("IER", test_ier),
+ TEST_CASE("DLL/DLM", test_divisor_latch),
+ TEST_CASE("MCR", test_mcr),
+ TEST_CASE("FCR-togggle", test_fcr_toggle),
+ TEST_CASE("FCR-trigger", test_fcr_trigger),
+ TEST_CASE("FCR-clear", test_fcr_clear),
+ TEST_CASE("LOOPBACK-data", test_loopback_data_path),
+ TEST_CASE("LOOPBACK-modem", test_loopback_modem_path),
+ TEST_CASE("IIR-noint", test_iir_noint),
+ TEST_CASE("IIR-thr", test_iir_thr_source),
+ TEST_CASE("IIR-rda", test_iir_rda_source),
+ TEST_CASE("IIR-prio", test_iir_priority),
+};
+
+void test_main(void)
+{
+ unsigned i;
+
+ for ( i = 0; i < ARRAY_SIZE(test_suite); i++ )
+ {
+ const struct test_case *t = &test_suite[i];
+
+ printk(" Test: %s\n", t->banner);
+ t->run(t->banner);
+ }
+
+ if ( !xtf_status_reported() )
+ xtf_success(NULL);
+
+ xtf_report_status();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tests/emul-ns16x50/patterns.c b/tests/emul-ns16x50/patterns.c
new file mode 100644
index 000000000000..b47cb6345364
--- /dev/null
+++ b/tests/emul-ns16x50/patterns.c
@@ -0,0 +1,65 @@
+const char *pattern_4096 =
+ "The quick brown fox jumps over the lazy dog. The quick brown fox"
+ " jumps over the lazy dog. The quick brown fox jumps over the laz"
+ "y dog. The quick brown fox jumps over the lazy dog. The quick br"
+ "own fox jumps over the lazy dog. The quick brown fox jumps over "
+ "the lazy dog. The quick brown fox jumps over the lazy dog. The q"
+ "uick brown fox jumps over the lazy dog. The quick brown fox jump"
+ "s over the lazy dog. The quick brown fox jumps over the lazy dog"
+ ". The quick brown fox jumps over the lazy dog. The quick brown f"
+ "ox jumps over the lazy dog. The quick brown fox jumps over the l"
+ "azy dog. The quick brown fox jumps over the lazy dog. The quick "
+ "brown fox jumps over the lazy dog. The quick brown fox jumps ove"
+ "r the lazy dog. The quick brown fox jumps over the lazy dog. The"
+ " quick brown fox jumps over the lazy dog. The quick brown fox ju"
+ "mps over the lazy dog. The quick brown fox jumps over the lazy d"
+ "og. The quick brown fox jumps over the lazy dog. The quick brown"
+ " fox jumps over the lazy dog. The quick brown fox jumps over the"
+ " lazy dog. The quick brown fox jumps over the lazy dog. The quic"
+ "k brown fox jumps over the lazy dog. The quick brown fox jumps o"
+ "ver the lazy dog. The quick brown fox jumps over the lazy dog. T"
+ "he quick brown fox jumps over the lazy dog. The quick brown fox "
+ "jumps over the lazy dog. The quick brown fox jumps over the lazy"
+ " dog. The quick brown fox jumps over the lazy dog. The quick bro"
+ "wn fox jumps over the lazy dog. The quick brown fox jumps over t"
+ "he lazy dog. The quick brown fox jumps over the lazy dog. The qu"
+ "ick brown fox jumps over the lazy dog. The quick brown fox jumps"
+ " over the lazy dog. The quick brown fox jumps over the lazy dog."
+ " The quick brown fox jumps over the lazy dog. The quick brown fo"
+ "x jumps over the lazy dog. The quick brown fox jumps over the la"
+ "zy dog. The quick brown fox jumps over the lazy dog. The quick b"
+ "rown fox jumps over the lazy dog. The quick brown fox jumps over"
+ " the lazy dog. The quick brown fox jumps over the lazy dog. The "
+ "quick brown fox jumps over the lazy dog. The quick brown fox jum"
+ "ps over the lazy dog. The quick brown fox jumps over the lazy do"
+ "g. The quick brown fox jumps over the lazy dog. The quick brown "
+ "fox jumps over the lazy dog. The quick brown fox jumps over the "
+ "lazy dog. The quick brown fox jumps over the lazy dog. The quick"
+ " brown fox jumps over the lazy dog. The quick brown fox jumps ov"
+ "er the lazy dog. The quick brown fox jumps over the lazy dog. Th"
+ "e quick brown fox jumps over the lazy dog. The quick brown fox j"
+ "umps over the lazy dog. The quick brown fox jumps over the lazy "
+ "dog. The quick brown fox jumps over the lazy dog. The quick brow"
+ "n fox jumps over the lazy dog. The quick brown fox jumps over th"
+ "e lazy dog. The quick brown fox jumps over the lazy dog. The qui"
+ "ck brown fox jumps over the lazy dog. The quick brown fox jumps "
+ "over the lazy dog. The quick brown fox jumps over the lazy dog. "
+ "The quick brown fox jumps over the lazy dog. The quick brown fox"
+ " jumps over the lazy dog. The quick brown fox jumps over the laz"
+ "y dog. The quick brown fox jumps over the lazy dog. The quick br"
+ "own fox jumps over the lazy dog. The quick brown fox jumps over "
+ "the lazy dog. The quick brown fox jumps over the lazy dog. The q"
+ "uick brown fox jumps over the lazy dog. The quick brown fox jump"
+ "s over the lazy dog. The quick brown fox jumps over the lazy dog"
+ ". The quick brown fox jumps over the lazy dog. The quick brown f"
+ "ox jumps over the lazy dog. The quick brown fox jumps over the l"
+ "azy dog. The quick brown fox jumps over the lazy dog. The quick "
+ "brown fox jumps over the lazy dog. The quick brown fox jumps ove"
+ "r the lazy dog. The quick brown fox jumps over the lazy dog. The"
+ " quick brown fox jumps over the lazy dog. The quick brown fox ju"
+ "mps over the lazy dog. The quick brown fox jumps over the lazy d"
+ "og. The quick brown fox jumps over the lazy dog. The quick brown"
+ " fox jumps over the lazy dog. The quick brown fox jumps over the"
+ " lazy dog. The quick brown fox jumps over the lazy dog. The quic"
+ "k brown fox jumps over the lazy dog. The quick brown fox jumps o"
+ "ver the lazy dog. The quick brown fox jumps over the lazy dog.\n";
--
2.56.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |