summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ic/com.c122
-rw-r--r--sys/dev/isa/com.c122
-rw-r--r--sys/dev/isa/espreg.h74
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_ */