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...
-----------------------------------------------------------------------------