Subject: Hayes ESP card final(?) patches
To: Robert Dobbs <banshee@gabriella.resort.com>
From: Michael L. VanLoon -- HeadCandy.com <michaelv@HeadCandy.com>
List: port-i386
Date: 09/12/1995 21:53:16
Last night, once again, I just decided I had to get this thing
perfect. I rearranged the probe logic a little bit so it didn't query
the ESP card on every pass through the comprobe loop. I also added
code so the automatic FIFO adjust logic wouldn't mess up the ESP.
Here's my latest set of patches. Patch 1 is against Robert Dobbs' ESP
patch. Patch 2 is the same code against the standard NetBSD com.c.
Off the top of my head, I don't think anything else needs to be done
to these. With the possible exception of better configuration code,
where the ESP enhanced I/O address isn't hard-coded. Maybe eventually
something like the boca and ast drivers where there's a "master", and
the ports themselves are "slaves". This would have the added benefit
of "just working" with multi-port ESP boards. That would probably
involve a master esp.c, and a completely separate driver unlrelated to
com.c. I'm not sure I'm ready to tackle that right away, however.
This code has been running in my machine all day, with a cron job
auto-connecting and disconnecting my PPP connection at various times.
I have seen absolutely no problems. It *looked* like it was
processing packets a little quicker when I supped, but of course
that's probably purely subjective and my imagination. :-) If Mr. Dobbs
agrees, I'd like to ask Charles to look these over and see if he'd be
willing to incorporate them into /sys/dev/isa/com.c. And, thanks
Robert for doing the initial work to make this all possible.
Patch 1 (Robert Dobbs' ESP-enhanced com.c vs. my new com.c):
----- >8 ---------- Begin patch ---------- 8< -----
--- esp/com.c-esp Sun Sep 10 20:07:57 1995
+++ com.c Mon Sep 11 23:04:04 1995
@@ -172,14 +172,25 @@
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;
+ char dips;
+ 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
@@ -188,31 +199,46 @@
#define ESP_STATUS1 4
#define ESP_STATUS2 5
+ /*
+ * ESP is present at ESP enhanced base address; unknown com port
+ */
+
+ /* Get the dip-switch configurations */
+ outb(esp_iobase + ESP_CMD1, ESP_GETDIPS);
+ dips = inb(esp_iobase + ESP_STATUS1);
+
+ /* Determine which com port this ESP card services: bits 0,1 of */
+ /* dips is the port # (0-3); combaselist[val] is the com_iobase */
+ if (com_iobase == combaselist[dips & 0x03]) {
+ printf(": ESP");
+ } else {
+ /* this com port is not us */
+ return;
+ }
+
/* 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);
+ printf("-old (%o)", val & 0x70);
+ /* we do not support the necessary features */
return;
}
/* Check for ability to emulate 16550: bit 8 == 1 */
- outb(iobase + ESP_CMD1, ESP_GETDIPS);
- val = inb(iobase + ESP_STATUS1);
- if ((val & 0x80) == 0) {
- printf(": ESP slave");
+ if ((dips & 0x80) == 0) {
+ printf(" slave");
+ /* XXX Does slave really mean no 16550 support?? */
return;
}
- /* Determine which com port this ESP card services: bits 0,1 */
- val &= 0x03; /* Mask off all but bits 0,1 */
+ /*
+ * If we made it this far, we are a full-featured ESP v2.0 (or
+ * better), at the correct com port address.
+ */
- /* sc->sc_dev.dv_unit is the com port: 0..3 */
- if (sc->sc_dev.dv_unit == val) {
- sc->sc_hwflags |= COM_HW_ESP;
- printf(": ESP");
- }
+ sc->sc_hwflags |= COM_HW_ESP;
}
int
@@ -250,7 +276,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,
@@ -673,7 +699,7 @@
* Set the FIFO threshold based on the receive speed, if we are
* changing it.
*/
- if (tp->t_ispeed != t->c_ispeed) {
+ if ((tp->t_ispeed != t->c_ispeed) && !(sc->sc_hwflags & COM_HW_ESP)) {
if (sc->sc_hwflags & COM_HW_FIFO)
outb(iobase + com_fifo,
FIFO_ENABLE |
----- >8 ---------- End patch ---------- 8< -----
Patch 2 (standard NetBSD com.c vs. my new com.c):
----- >8 ---------- Begin patch ---------- 8< -----
--- esp/com.c-orig Tue Jul 4 00:04:29 1995
+++ com.c Mon Sep 11 23:04:04 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,75 @@
return 1;
}
+void comprobeESP(esp_iobase, com_iobase, sc)
+ int esp_iobase;
+ int com_iobase;
+ struct com_softc *sc;
+{
+ char val;
+ char dips;
+ 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
+
+ /*
+ * ESP is present at ESP enhanced base address; unknown com port
+ */
+
+ /* Get the dip-switch configurations */
+ outb(esp_iobase + ESP_CMD1, ESP_GETDIPS);
+ dips = inb(esp_iobase + ESP_STATUS1);
+
+ /* Determine which com port this ESP card services: bits 0,1 of */
+ /* dips is the port # (0-3); combaselist[val] is the com_iobase */
+ if (com_iobase == combaselist[dips & 0x03]) {
+ printf(": ESP");
+ } else {
+ /* this com port is not us */
+ return;
+ }
+
+ /* 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 (%o)", val & 0x70);
+ /* we do not support the necessary features */
+ return;
+ }
+
+ /* Check for ability to emulate 16550: bit 8 == 1 */
+ if ((dips & 0x80) == 0) {
+ printf(" slave");
+ /* XXX Does slave really mean no 16550 support?? */
+ return;
+ }
+
+ /*
+ * If we made it this far, we are a full-featured ESP v2.0 (or
+ * better), at the correct com port address.
+ */
+
+ sc->sc_hwflags |= COM_HW_ESP;
+}
+
int
comprobe(parent, match, aux)
struct device *parent;
@@ -203,6 +275,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 +386,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,
@@ -600,7 +699,7 @@
* Set the FIFO threshold based on the receive speed, if we are
* changing it.
*/
- if (tp->t_ispeed != t->c_ispeed) {
+ if ((tp->t_ispeed != t->c_ispeed) && !(sc->sc_hwflags & COM_HW_ESP)) {
if (sc->sc_hwflags & COM_HW_FIFO)
outb(iobase + com_fifo,
FIFO_ENABLE |
@@ -674,6 +773,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...
-----------------------------------------------------------------------------