summaryrefslogtreecommitdiff
path: root/sys/dev/ic/com.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-01-03 05:16:11 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-01-03 05:16:11 +0000
commitd9edba3b07d42108aac7ae3c10ad5fbe0b935006 (patch)
tree3d208d85691aa0dae35418651ecbb8ad3ddc036e /sys/dev/ic/com.c
parent37bedcc6b505e7091cbb030db6738fce2e977acb (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.c122
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 {