Subject: New ESP patches to com.c
To: Robert Dobbs <banshee@gabriella.resort.com>
From: Michael L. VanLoon -- HeadCandy.com <michaelv@HeadCandy.com>
List: port-i386
Date: 09/11/1995 21:57:38
I got to thinking about the mail I sent last night, and decided this
wouldn't be too hard to solve at all. So, here's the patch to make it
work. The first patch is a diff between the com.c patched with your
original patch, and my new com.c. The second, is a patch of my com.c
vs. the original NetBSD one (for those who haven't been following this
thread and who may want to try this themselves). This now works
correctly on my machine (from dmesg):
com0 at isa0 port 0x3e8-0x3ef irq 9: ESP: ns16550a, working fifo
com1 at isa0 port 0x3f8-0x3ff irq 4: ns16550a, working fifo
com2 at isa0 port 0x2f8-0x2ff irq 3: ns16550a, working fifo
One thing that I got to thinking of as I was looking through this that
might still be done is: I noticed that it probes for the existance of
the ESP and sets its registers *each*time* through the com probe loop.
This should only be done once. So, maybe the com iobase matching test
should be at the beginning of comprobeESP, and jump out immediately if
they don't match? Also, it would be nice to be able to set the ESP
base address in the kernel config file, rather than hard-coding it
into the com.c file. Suggestions? Comments?
When I get time (no promises), I'll see if there are any other
optimizations which could be made. For example, does it handle the
(supposed) dynamic changing of FIFO trigger level based on port speed
(as in, ignoring this)? I don't know -- I haven't looked at that
code, yet.
Patch 1 (R. Dobbs patched com.c vs. my new patched com.c):
----- >8 ---------- Begin patch ---------- 8< -----
--- esp/com.c-esp Sun Sep 10 20:07:57 1995
+++ com.c Mon Sep 11 21:31:34 1995
@@ -172,14 +172,24 @@
return 1;
}
-void comprobeESP(iobase, sc)
- int iobase;
+void comprobeESP(esp_iobase, com_iobase, sc)
+ int esp_iobase;
+ int com_iobase;
struct com_softc *sc;
{
char val;
+ int combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
+
+ /*
+ * Hayes ESP cards have two iobases. One is for compatibility with
+ * 16550 serial chips, and at the same ISA PC base addresses. The
+ * other is for ESP-specific enhanced features, and lies at a
+ * different addressing range entirely (0x140, 0x180, or 0x280).
+ * Hence the need for esp_iobase and com_iobase.
+ */
/* Test for ESP signature */
- if ((inb(iobase) & 0xf3) == 0)
+ if ((inb(esp_iobase) & 0xf3) == 0)
return;
#define ESP_GETTEST 0x01
@@ -189,17 +199,17 @@
#define ESP_STATUS2 5
/* Check for ESP version 2.0: bits 4,5,6 == 010 */
- outb(iobase + ESP_CMD1, ESP_GETTEST);
- val = inb(iobase + ESP_STATUS1); /* Clear reg 1 */
- val = inb(iobase + ESP_STATUS2);
+ outb(esp_iobase + ESP_CMD1, ESP_GETTEST);
+ val = inb(esp_iobase + ESP_STATUS1); /* Clear reg 1 */
+ val = inb(esp_iobase + ESP_STATUS2);
if ((val & 0x70) < 0x20) {
printf(": old ESP(%o)", val & 0x70);
return;
}
/* Check for ability to emulate 16550: bit 8 == 1 */
- outb(iobase + ESP_CMD1, ESP_GETDIPS);
- val = inb(iobase + ESP_STATUS1);
+ outb(esp_iobase + ESP_CMD1, ESP_GETDIPS);
+ val = inb(esp_iobase + ESP_STATUS1);
if ((val & 0x80) == 0) {
printf(": ESP slave");
return;
@@ -208,8 +218,8 @@
/* Determine which com port this ESP card services: bits 0,1 */
val &= 0x03; /* Mask off all but bits 0,1 */
- /* sc->sc_dev.dv_unit is the com port: 0..3 */
- if (sc->sc_dev.dv_unit == val) {
+ /* val (0-3) is the port #; combaselist[val] is the com_iobase */
+ if (com_iobase == combaselist[val]) {
sc->sc_hwflags |= COM_HW_ESP;
printf(": ESP");
}
@@ -250,7 +260,7 @@
delay(1000);
/* look for a Hayes ESP board at ESP_PORT */
- comprobeESP(ESP_PORT, sc);
+ comprobeESP(ESP_PORT, iobase, sc);
/* look for a NS 16550AF UART with FIFOs */
outb(iobase + com_fifo,
----- >8 ---------- End patch ---------- 8< -----
Patch 2 (NetBSD original com.c vs. my new patched com.c):
----- >8 ---------- Begin patch ---------- 8< -----
--- esp/com.c-orig Tue Jul 4 00:04:29 1995
+++ com.c Mon Sep 11 21:31:34 1995
@@ -62,7 +62,9 @@
#include <dev/isa/comreg.h>
#include <dev/ic/ns16550reg.h>
-#define COM_IBUFSIZE (2 * 256)
+#define ESP_PORT 0x140 /* IO Address for ESP (jumpered on card) */
+
+#define COM_IBUFSIZE (2 * 512)
#define COM_IHIGHWATER ((3 * COM_IBUFSIZE) / 4)
struct com_softc {
@@ -78,6 +80,7 @@
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
@@ -169,6 +172,59 @@
return 1;
}
+void comprobeESP(esp_iobase, com_iobase, sc)
+ int esp_iobase;
+ int com_iobase;
+ struct com_softc *sc;
+{
+ char val;
+ int combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
+
+ /*
+ * Hayes ESP cards have two iobases. One is for compatibility with
+ * 16550 serial chips, and at the same ISA PC base addresses. The
+ * other is for ESP-specific enhanced features, and lies at a
+ * different addressing range entirely (0x140, 0x180, or 0x280).
+ * Hence the need for esp_iobase and com_iobase.
+ */
+
+ /* Test for ESP signature */
+ if ((inb(esp_iobase) & 0xf3) == 0)
+ return;
+
+#define ESP_GETTEST 0x01
+#define ESP_GETDIPS 0x02
+#define ESP_CMD1 4
+#define ESP_STATUS1 4
+#define ESP_STATUS2 5
+
+ /* Check for ESP version 2.0: bits 4,5,6 == 010 */
+ outb(esp_iobase + ESP_CMD1, ESP_GETTEST);
+ val = inb(esp_iobase + ESP_STATUS1); /* Clear reg 1 */
+ val = inb(esp_iobase + ESP_STATUS2);
+ if ((val & 0x70) < 0x20) {
+ printf(": old ESP(%o)", val & 0x70);
+ return;
+ }
+
+ /* Check for ability to emulate 16550: bit 8 == 1 */
+ outb(esp_iobase + ESP_CMD1, ESP_GETDIPS);
+ val = inb(esp_iobase + ESP_STATUS1);
+ if ((val & 0x80) == 0) {
+ printf(": ESP slave");
+ return;
+ }
+
+ /* Determine which com port this ESP card services: bits 0,1 */
+ val &= 0x03; /* Mask off all but bits 0,1 */
+
+ /* val (0-3) is the port #; combaselist[val] is the com_iobase */
+ if (com_iobase == combaselist[val]) {
+ sc->sc_hwflags |= COM_HW_ESP;
+ printf(": ESP");
+ }
+}
+
int
comprobe(parent, match, aux)
struct device *parent;
@@ -203,6 +259,9 @@
if (sc->sc_dev.dv_unit == comconsole)
delay(1000);
+ /* look for a Hayes ESP board at ESP_PORT */
+ comprobeESP(ESP_PORT, iobase, sc);
+
/* look for a NS 16550AF UART with FIFOs */
outb(iobase + com_fifo,
FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
@@ -311,6 +370,30 @@
sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
iobase = sc->sc_iobase;
+ /* Setup the ESP board */
+ if (sc->sc_hwflags & COM_HW_ESP) {
+ outb(iobase + com_fifo,
+ FIFO_DMA_MODE | FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_8);
+#define ESP_SETMODE 0x10
+#define ESP_CMD2 5
+ /* Set 16550 compatibility mode */
+ outb(ESP_PORT + ESP_CMD1, ESP_SETMODE);
+ outb(ESP_PORT + ESP_CMD2, 0x80 | 0x04 | 0x02);
+#define ESP_SETFLOWTYPE 0x0A
+ /* Set RTS/CTS flow control */
+ outb(ESP_PORT + ESP_CMD1, ESP_SETFLOWTYPE);
+ outb(ESP_PORT + ESP_CMD2, 0x04);
+ outb(ESP_PORT + ESP_CMD2, 0x10);
+#define ESP_SETRXFLOW 0x0A
+#define HIBYTE(w) ((char)(((short)(w) >> 8) & 0xff))
+#define LOBYTE(w) ((char)(w))
+ /* Set flow control levels */
+ outb(ESP_PORT + ESP_CMD1, ESP_SETRXFLOW);
+ outb(ESP_PORT + ESP_CMD2, HIBYTE(768));
+ outb(ESP_PORT + ESP_CMD2, LOBYTE(768));
+ outb(ESP_PORT + ESP_CMD2, HIBYTE(512));
+ outb(ESP_PORT + ESP_CMD2, LOBYTE(512));
+ } else
/* Set the FIFO threshold based on the receive speed. */
if (sc->sc_hwflags & COM_HW_FIFO)
outb(iobase + com_fifo,
@@ -674,6 +757,13 @@
selwakeup(&tp->t_wsel);
}
tp->t_state |= TS_BUSY;
+ if (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 (sc->sc_hwflags & COM_HW_FIFO) {
u_char buffer[16], *cp = buffer;
int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
----- >8 ---------- End patch ---------- 8< -----
-----------------------------------------------------------------------------
Michael L. VanLoon michaelv@HeadCandy.com
--< Free your mind and your machine -- NetBSD free un*x >--
NetBSD working ports: 386+PC, Mac, Amiga, HP300, Sun3, Sun4, PC532,
DEC pmax (MIPS R2k/3k), DEC/AXP (Alpha)
NetBSD ports in progress: VAX and others...
-----------------------------------------------------------------------------