diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-01-03 05:16:11 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-01-03 05:16:11 +0000 |
commit | d9edba3b07d42108aac7ae3c10ad5fbe0b935006 (patch) | |
tree | 3d208d85691aa0dae35418651ecbb8ad3ddc036e /sys/dev/ic/com.c | |
parent | 37bedcc6b505e7091cbb030db6738fce2e977acb (diff) |
Patches to use Hayes ESP with com.c; from banshee@gabriella.resort.com;
netbsd pr#1865. the ESP card code is always enabled -- we will have to
see if that fails on any chipsets.
Diffstat (limited to 'sys/dev/ic/com.c')
-rw-r--r-- | sys/dev/ic/com.c | 122 |
1 files changed, 106 insertions, 16 deletions
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c index da385681114..ad63516f0ff 100644 --- a/sys/dev/ic/com.c +++ b/sys/dev/ic/com.c @@ -61,6 +61,7 @@ #include <dev/isa/isavar.h> #include <dev/isa/comreg.h> #include <dev/ic/ns16550reg.h> +#include <dev/ic/espreg.h> #define com_lcr com_cfcr #define COM_IBUFSIZE (2 * 256) @@ -76,9 +77,11 @@ struct com_softc { int sc_errors; int sc_iobase; + int sc_espbase; u_char sc_hwflags; #define COM_HW_NOIEN 0x01 #define COM_HW_FIFO 0x02 +#define COM_HW_ESP 0x04 #define COM_HW_CONSOLE 0x40 u_char sc_swflags; #define COM_SW_SOFTCAR 0x01 @@ -186,6 +189,50 @@ comprobe(parent, match, aux) return 1; } +int +comprobeESP(esp_port, sc) + int esp_port; + struct com_softc *sc; +{ + char val, dips; + int com_base_list[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; + + /* Test for ESP signature at the ESP i/o port. */ + if ((inb(esp_port) & 0xf3) == 0) + return(0); + + /* Check compatibility mode settings */ + outb(esp_port + ESP_CMD1, ESP_GETDIPS); + dips = inb(esp_port + ESP_STATUS1); + + /* Does this ESP board service this com port?: Bits 0,1 == COM0..3 */ + if (sc->sc_iobase != com_base_list[(dips & 0x03)]) { + return(0); + } + printf(": ESP"); + + /* Check ESP Self Test bits. */ + /* Check for ESP version 2.0: bits 4,5,6 == 010 */ + outb(esp_port + ESP_CMD1, ESP_GETTEST); + val = inb(esp_port + ESP_STATUS1); /* Always 0x00 */ + val = inb(esp_port + ESP_STATUS2); + if ((val & 0x70) < 0x20) { + printf("-old (%o)", val & 0x70); + return(0); + } + + /* Check for ability to emulate 16550: bit 7 set */ + if (ISSET(dips, 0x80) == 0) { + printf(" slave"); + return(0); + } + + /* We're a full featured ESP card at the right com port. */ + SET(sc->sc_hwflags, COM_HW_ESP); + printf(", 1024 byte fifo\n"); + return(1); +} + void comattach(parent, self, aux) struct device *parent, *self; @@ -196,6 +243,8 @@ comattach(parent, self, aux) struct cfdata *cf = sc->sc_dev.dv_cfdata; int iobase = ia->ia_iobase; struct tty *tp; + int esp_ports[] = { 0x140, 0x180, 0x280, 0 }; + int *espp; sc->sc_iobase = iobase; sc->sc_hwflags = ISSET(cf->cf_flags, COM_HW_NOIEN); @@ -204,19 +253,29 @@ comattach(parent, self, aux) if (sc->sc_dev.dv_unit == comconsole) delay(1000); - /* look for a NS 16550AF UART with FIFOs */ - outb(iobase + com_fifo, - FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14); - delay(100); - if (ISSET(inb(iobase + com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK) - if (ISSET(inb(iobase + com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) { - SET(sc->sc_hwflags, COM_HW_FIFO); - printf(": ns16550a, working fifo\n"); - } else - printf(": ns16550, broken fifo\n"); - else - printf(": ns8250 or ns16450, no fifo\n"); - outb(iobase + com_fifo, 0); + /* Look for a Hayes ESP board. */ + for (espp = esp_ports; *espp != 0; espp++) + if (comprobeESP(*espp, sc)) { + sc->sc_espbase = *espp; + break; + } + /* No ESP; look for other things. */ + if (*espp == 0) { + /* look for a NS 16550AF UART with FIFOs */ + outb(iobase + com_fifo, + FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14); + delay(100); + if (ISSET(inb(iobase + com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK) + if (ISSET(inb(iobase + com_fifo), FIFO_TRIGGER_14) == + FIFO_TRIGGER_14) { + SET(sc->sc_hwflags, COM_HW_FIFO); + printf(": ns16550a, working fifo\n"); + } else + printf(": ns16550, broken fifo\n"); + else + printf(": ns8250 or ns16450, no fifo\n"); + outb(iobase + com_fifo, 0); + } /* disable interrupts */ outb(iobase + com_ier, 0); @@ -312,8 +371,33 @@ comopen(dev, flag, mode, p) sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE; iobase = sc->sc_iobase; - /* Set the FIFO threshold based on the receive speed. */ - if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) + + /* Set up the ESP board */ + if (ISSET(sc->sc_hwflags, COM_HW_ESP)) { + outb(iobase + com_fifo, + /* XXX - bug in ESP requires DMA flag set */ + FIFO_DMA_MODE | + FIFO_ENABLE | FIFO_RCV_RST | + FIFO_XMT_RST | FIFO_TRIGGER_8); + + /* Set 16550 compatibility mode */ + outb(sc->sc_espbase + ESP_CMD1, ESP_SETMODE); + outb(sc->sc_espbase + ESP_CMD2, + ESP_MODE_FIFO | ESP_MODE_RTS | ESP_MODE_SCALE); + + /* Set RTS/CTS flow control */ + outb(sc->sc_espbase + ESP_CMD1, ESP_SETFLOWTYPE); + outb(sc->sc_espbase + ESP_CMD2, ESP_FLOW_RTS); + outb(sc->sc_espbase + ESP_CMD2, ESP_FLOW_CTS); + + /* Set flow control levels */ + outb(sc->sc_espbase + ESP_CMD1, ESP_SETRXFLOW); + outb(sc->sc_espbase + ESP_CMD2, HIBYTE(RXHIGHWATER)); + outb(sc->sc_espbase + ESP_CMD2, LOBYTE(RXHIGHWATER)); + outb(sc->sc_espbase + ESP_CMD2, HIBYTE(RXLOWWATER)); + outb(sc->sc_espbase + ESP_CMD2, LOBYTE(RXLOWWATER)); + } else if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) + /* Set the FIFO threshold based on the receive speed. */ outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8)); @@ -692,7 +776,13 @@ comstart(tp) selwakeup(&tp->t_wsel); } SET(tp->t_state, TS_BUSY); - if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { + if (ISSET(sc->sc_hwflags, COM_HW_ESP)) { + u_char buffer[1024], *cp = buffer; + int n = q_to_b(&tp->t_outq, cp, sizeof buffer); + do { + outb(iobase + com_data, *cp++); + } while (--n); + } else if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) { u_char buffer[16], *cp = buffer; int n = q_to_b(&tp->t_outq, cp, sizeof buffer); do { |