+
+
+/*
+ * 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 <dos.h>
+#include <go32.h>
+#include <dpmi.h>
+typedef unsigned long u_long;
+
+/* DPMI Communication */
+static union REGS dpmi_regs;
+static struct SREGS dpmi_sregs;
+
+/* 16550 rx fifo trigger point */
+#define FIFO_TRIGGER FIFO_TRIGGER_4
+
+/* input buffer size */
+#define CBSIZE 4096
+
+/* return raw 18Hz clock count */
+extern long rawclock (void);
+
+#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 int 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"
+};
+
+#define COUNT(x) cnts[x]++
+#else
+#define COUNT(x)
+#endif
+
+/* Main interrupt controller port addresses. */
+#define ICU_BASE 0x20
+#define ICU_OCW2 (ICU_BASE + 0)
+#define ICU_MASK (ICU_BASE + 1)
+
+/* Original interrupt controller mask register. */
+unsigned char icu_oldmask;
+
+/* Maximum of 8 interrupts (we don't handle the slave icu yet). */
+#define NINTR 8
+
+static struct intrupt
+ {
+ char inuse;
+ struct dos_ttystate *port;
+ _go32_dpmi_seginfo old_rmhandler;
+ _go32_dpmi_seginfo old_pmhandler;
+ _go32_dpmi_seginfo new_rmhandler;
+ _go32_dpmi_seginfo new_pmhandler;
+ _go32_dpmi_registers regs;
+ }
+intrupts[NINTR];
+
+
+static struct dos_ttystate
+ {
+ int base;
+ int irq;
+ int refcnt;
+ struct intrupt *intrupt;
+ int fifo;
+ int baudrate;
+ unsigned char cbuf[CBSIZE];
+ unsigned int first;
+ unsigned int count;
+ int txbusy;
+ unsigned char old_mcr;
+ int ferr;
+ int perr;
+ int oflo;
+ int msr;
+ }
+ports[4] =
+{
+ {
+ COM1ADDR, 4
+ }
+ ,
+ {
+ COM2ADDR, 3
+ }
+ ,
+ {
+ COM3ADDR, 4
+ }
+ ,
+ {
+ COM4ADDR, 3
+ }
+};
+
+static int dos_open PARAMS ((serial_t scb, const char *name));
+static void dos_raw PARAMS ((serial_t scb));
+static int dos_readchar PARAMS ((serial_t scb, int timeout));
+static int dos_setbaudrate PARAMS ((serial_t scb, int rate));
+static int dos_write PARAMS ((serial_t scb, const char *str, int len));
+static void dos_close PARAMS ((serial_t scb));
+static serial_ttystate dos_get_tty_state PARAMS ((serial_t scb));
+static int dos_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+static int dos_baudconv PARAMS ((int rate));
+
+#define inb(p,a) inportb((p)->base + (a))
+#define outb(p,a,v) outportb((p)->base + (a), (v))
+#define disable() asm volatile ("cli");
+#define enable() asm volatile ("sti");
+