diff options
-rw-r--r-- | sys/dev/ic/com.c | 122 | ||||
-rw-r--r-- | sys/dev/isa/com.c | 122 | ||||
-rw-r--r-- | sys/dev/isa/espreg.h | 74 |
3 files changed, 286 insertions, 32 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 { diff --git a/sys/dev/isa/com.c b/sys/dev/isa/com.c index da385681114..ad63516f0ff 100644 --- a/sys/dev/isa/com.c +++ b/sys/dev/isa/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 { diff --git a/sys/dev/isa/espreg.h b/sys/dev/isa/espreg.h new file mode 100644 index 00000000000..02993943b89 --- /dev/null +++ b/sys/dev/isa/espreg.h @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 1995 Sean E. Fagin, John M Vinopal. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ESPREG_H_ +#define _ESPREG_H_ + +/* + * Definitions for Hayes ESP serial cards. + */ + +/* + * CMD1 and CMD2 are the command ports, offsets from <esp_iobase>. + */ +#define ESP_CMD1 4 +#define ESP_CMD2 5 + +/* + * STAT1 and STAT2 are to get return values and status bytes + */ +#define ESP_STATUS1 ESP_CMD1 +#define ESP_STATUS2 ESP_CMD2 + +/* + * Commands. Commands are given by writing the command value to + * ESP_CMD1 and then writing or reading some number of bytes from + * ESP_CMD2 or ESP_STATUS2. + */ +#define ESP_GETTEST 0x01 /* self-test command (1 byte + extras) */ +#define ESP_GETDIPS 0x02 /* get on-board DIP switches (1 byte) */ +#define ESP_SETFLOWTYPE 0x08 /* set type of flow-control (2 bytes) */ +#define ESP_SETRXFLOW 0x0a /* set Rx FIFO flow control levels (4 bytes) */ +#define ESP_SETMODE 0x10 /* set board mode (1 byte) */ + +/* Mode bits (ESP_SETMODE). */ +#define ESP_MODE_FIFO 0x02 /* act like a 16550 (compatibility mode) */ +#define ESP_MODE_RTS 0x04 /* use RTS hardware flow control */ +#define ESP_MODE_SCALE 0x80 /* scale FIFO trigger levels */ + +/* Flow control type bits (ESP_SETFLOWTYPE). */ +#define ESP_FLOW_RTS 0x04 /* cmd1: local Rx sends RTS flow control */ +#define ESP_FLOW_CTS 0x10 /* cmd2: local transmitter responds to CTS */ + +/* Used by ESP_SETRXFLOW. */ +#define RXHIGHWATER 768 +#define RXLOWWATER 512 +#define HIBYTE(w) (((w) >> 8) & 0xff) +#define LOBYTE(w) ((w) & 0xff) + +#endif /* !_ESPREG_H_ */ |