+/*
+ * NS16550 UART registers
+ */
+
+#define COM1ADDR 0x3f8
+#define COM2ADDR 0x2f8
+#define COM3ADDR 0x3e8
+#define COM4ADDR 0x3e0
+
+#define com_data 0 /* data register (R/W) */
+#define com_dlbl 0 /* divisor latch low (W) */
+#define com_ier 1 /* interrupt enable (W) */
+#define com_dlbh 1 /* divisor latch high (W) */
+#define com_iir 2 /* interrupt identification (R) */
+#define com_fifo 2 /* FIFO control (W) */
+#define com_lctl 3 /* line control register (R/W) */
+#define com_cfcr 3 /* line control register (R/W) */
+#define com_mcr 4 /* modem control register (R/W) */
+#define com_lsr 5 /* line status register (R/W) */
+#define com_msr 6 /* modem status register (R/W) */
+
+/*
+ * Constants for computing 16 bit baud rate divisor (lower byte
+ * in com_dlbl, upper in com_dlbh) from 1.8432MHz crystal. Divisor is
+ * 1.8432 MHz / (16 * X) for X bps. If the baud rate can't be set
+ * to within +- (desired_rate*SPEED_TOLERANCE/1000) bps, we fail.
+ */
+#define COMTICK (1843200/16)
+#define SPEED_TOLERANCE 30 /* thousandths; real == desired +- 3.0% */
+
+/* interrupt enable register */
+#define IER_ERXRDY 0x1 /* int on rx ready */
+#define IER_ETXRDY 0x2 /* int on tx ready */
+#define IER_ERLS 0x4 /* int on line status change */
+#define IER_EMSC 0x8 /* int on modem status change */
+
+/* interrupt identification register */
+#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
+#define IIR_IMASK 0xf /* interrupt cause mask */
+#define IIR_NOPEND 0x1 /* nothing pending */
+#define IIR_RLS 0x6 /* receive line status */
+#define IIR_RXRDY 0x4 /* receive ready */
+#define IIR_RXTOUT 0xc /* receive timeout */
+#define IIR_TXRDY 0x2 /* transmit ready */
+#define IIR_MLSC 0x0 /* modem status */
+
+
+/* fifo control register */
+#define FIFO_ENABLE 0x01 /* enable fifo */
+#define FIFO_RCV_RST 0x02 /* reset receive fifo */
+#define FIFO_XMT_RST 0x04 /* reset transmit fifo */
+#define FIFO_DMA_MODE 0x08 /* enable dma mode */
+#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */
+#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */
+#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */
+#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */
+
+/* character format control register */
+#define CFCR_DLAB 0x80 /* divisor latch */
+#define CFCR_SBREAK 0x40 /* send break */
+#define CFCR_PZERO 0x30 /* zero parity */
+#define CFCR_PONE 0x20 /* one parity */
+#define CFCR_PEVEN 0x10 /* even parity */
+#define CFCR_PODD 0x00 /* odd parity */
+#define CFCR_PENAB 0x08 /* parity enable */
+#define CFCR_STOPB 0x04 /* 2 stop bits */
+#define CFCR_8BITS 0x03 /* 8 data bits */
+#define CFCR_7BITS 0x02 /* 7 data bits */
+#define CFCR_6BITS 0x01 /* 6 data bits */
+#define CFCR_5BITS 0x00 /* 5 data bits */
+
+/* modem control register */
+#define MCR_LOOPBACK 0x10 /* loopback */
+#define MCR_IENABLE 0x08 /* output 2 = int enable */
+#define MCR_DRS 0x04 /* output 1 = xxx */
+#define MCR_RTS 0x02 /* enable RTS */
+#define MCR_DTR 0x01 /* enable DTR */
+
+/* line status register */
+#define LSR_RCV_FIFO 0x80 /* error in receive fifo */
+#define LSR_TSRE 0x40 /* transmitter empty */
+#define LSR_TXRDY 0x20 /* transmitter ready */
+#define LSR_BI 0x10 /* break detected */
+#define LSR_FE 0x08 /* framing error */
+#define LSR_PE 0x04 /* parity error */
+#define LSR_OE 0x02 /* overrun error */
+#define LSR_RXRDY 0x01 /* receiver ready */
+#define LSR_RCV_MASK 0x1f
+
+/* modem status register */
+#define MSR_DCD 0x80
+#define MSR_RI 0x40
+#define MSR_DSR 0x20
+#define MSR_CTS 0x10
+#define MSR_DDCD 0x08
+#define MSR_TERI 0x04
+#define MSR_DDSR 0x02
+#define MSR_DCTS 0x01
+
+#include <time.h>
+#include <dos.h>
+#include <go32.h>
+#include <dpmi.h>
+typedef unsigned long u_long;
+
+/* 16550 rx fifo trigger point */
+#define FIFO_TRIGGER FIFO_TRIGGER_4
+
+/* input buffer size */
+#define CBSIZE 4096
+
+#define RAWHZ 18
+
+#ifdef DOS_STATS
+#define CNT_RX 16
+#define CNT_TX 17
+#define CNT_STRAY 18
+#define CNT_ORUN 19
+#define NCNT 20
+
+static int intrcnt;
+static size_t cnts[NCNT];
+static char *cntnames[NCNT] =
+{
+ /* h/w interrupt counts. */
+ "mlsc", "nopend", "txrdy", "?3",
+ "rxrdy", "?5", "rls", "?7",
+ "?8", "?9", "?a", "?b",
+ "rxtout", "?d", "?e", "?f",
+ /* s/w counts. */
+ "rxcnt", "txcnt", "stray", "swoflo"
+};