*BSD News Article 20548


Return to BSD News archive

Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!agate!spool.mu.edu!bloom-beacon.mit.edu!cambridge-news.cygnus.com!athena.mit.edu!raeburn
From: raeburn@athena.mit.edu (Ken Raeburn)
Newsgroups: comp.os.386bsd.development
Subject: AST 4-port serial card support for NetBSD 0.9
Date: 7 Sep 1993 13:25:06 GMT
Organization: Cygnus Support, Cambridge MA
Lines: 212
Message-ID: <RAEBURN.93Sep7092506@cambridge.cygnus.com>
NNTP-Posting-Host: cambridge.cygnus.com


Having no serial port not on my AST 4-port card that could give me a
decent SLIP connection, and having accidentally deleted my hacked 0.8
kernel sources, and therefore having nothing better to do yesterday than
rewrite 4-port card support from scratch, I came up with the following
patches.

It seems to be enough to get SLIP up and running; no noticeable problems
yet with X, named, xntpd, and ftp going.  I've only been running with
these changes for a little while (less than 24 hours, but I've done
several file transfers), and I've only got my modem connected to the
card, so there may be some problems still to be fixed.

These changes do require that "flags 0x1" be given in the config file
for any serial port on a 4-port card.  I'm not going to bother trying to
auto-detect the 4-port card.  They also require that "non-compatible"
mode be used on the card -- nonstandard i/o addresses, one irq for the
whole card.

The changes fall into these categories:
 - initialize the 4-port card
 - don't use MCR_IENABLE with a 4-port card
 - change output style, so 4-port cards with fifos don't produce
   screenfuls of output at boot time
 - for interrupts from a 4-port card, check flags and handle all ports
   ready to be handled

Yeah, these changes will be obsolete as soon as the new com driver is
put in.  But they let me get work done while I wait.  Now I can see the
code I was supposed to be working on over the weekend...

--- com.c.dist	Mon Jul 12 07:37:02 1993
+++ com.c	Mon Sep  6 18:16:17 1993
@@ -78,6 +78,7 @@
 int	comdefaultrate = TTYDEF_SPEED;
 int	commajor;
 short com_addr[NCOM];
+int com_multi;
 struct	tty *com_tty[NCOM];
 
 struct speedtab comspeedtab[] = {
@@ -115,6 +116,11 @@
 comprobe(dev)
 struct isa_device *dev;
 {
+	if (dev->id_flags & 1) {
+		outb (dev->id_iobase | 0x1f, 0x80);
+		/* Is this needed?  Ted's driver for Linux does it.  */
+		(void) inb (dev->id_iobase | 0x1f);
+	}
 	/* force access to id reg */
 	outb(dev->id_iobase+com_cfcr, 0);
 	outb(dev->id_iobase+com_iir, 0);
@@ -132,6 +138,8 @@
 	struct	tty	*tp;
 	u_char		unit;
 	int		port = isdp->id_iobase;
+	char		*pfx = "\t";
+	int		enable = MCR_IENABLE;
 
 	unit = isdp->id_unit;
 	if (unit == comconsole)
@@ -139,17 +147,24 @@
 	com_addr[unit] = port;
 	com_active |= 1 << unit;
 	comsoftCAR |= 1 << unit;	/* XXX */
+	if (isdp->id_flags & 1) {
+		com_multi |= 1 << unit;
+		enable = 0;
+		printf ("%smultiport", pfx);
+		pfx = ", ";
+	}
 
 	/* look for a NS 16550AF UART with FIFOs */
 	outb(port+com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4);
 	DELAY(100);
 	if ((inb(port+com_iir) & IIR_FIFO_MASK) == IIR_FIFO_MASK) {
 		com_hasfifo |= 1 << unit;
-		printf("com%d: fifo\n", isdp->id_unit);
+		printf("%sfifo\n", pfx, isdp->id_unit);
+		pfx = ", ";
 	}
 
 	outb(port+com_ier, 0);
-	outb(port+com_mcr, 0 | MCR_IENABLE);
+	outb(port+com_mcr, 0 | enable);
 #ifdef KGDB
 	if (kgdb_dev == makedev(commajor, unit)) {
 		if (comconsole == unit)
@@ -161,10 +176,10 @@
 				 * Print prefix of device name,
 				 * let kgdb_connect print the rest.
 				 */
-				printf("com%d: ", unit);
+				printf("%s", pfx);
 				kgdb_connect(1);
 			} else
-				printf("com%d: kgdb enabled\n", unit);
+				printf("%skgdb enabled\n", pfx, unit);
 		}
 	}
 #endif
@@ -283,20 +298,20 @@
 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
 }
  
-comintr(unit)
+void
+comintr2(unit)
 	register int unit;
 {
 	register com;
 	register u_char code;
 	register struct tty *tp;
 
-	unit;
 	com = com_addr[unit];
 	while (1) {
 		code = inb(com+com_iir);
 		switch (code & IIR_IMASK) {
 		case IIR_NOPEND:
-			return (1);
+			return;
 		case IIR_RXTOUT:
 		case IIR_RXRDY:
 			tp = com_tty[unit];
@@ -342,7 +357,7 @@
 			break;
 		default:
 			if (code & IIR_NOPEND)
-				return (1);
+				return;
 			log(LOG_WARNING, "com%d: weird interrupt: 0x%x\n",
 			    unit, code);
 			/* fall through */
@@ -353,6 +368,30 @@
 	}
 }
 
+comintr(unit)
+     int unit;
+{
+  int addr, maddr, flags;
+
+  if ((com_multi & (1 << unit)) == 0)
+    {
+      comintr2 (unit);
+      return 1;
+    }
+
+  addr = com_addr[unit];
+  maddr = addr & ~0x1f;
+  unit -= (addr - maddr) / 8;
+
+  flags = inb (addr | 0x1f) & 0xf;
+
+#define CHECK(I)  ((flags & (1 << (I))) ? 0 : comintr2 (unit + (I)))
+  CHECK (0), CHECK (1), CHECK (2), CHECK (3);
+#undef CHECK
+
+  return 1;
+}
+
 comeint(unit, stat, com)
 	register int unit, stat;
 	register com;
@@ -388,6 +427,7 @@
 {
 	register struct tty *tp;
 	register int stat;
+	int enable = (com_multi & (1 << unit)) ? 0 : MCR_IENABLE;
 
 	tp = com_tty[unit];
 	stat = inb(com+com_msr);
@@ -396,7 +436,8 @@
 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
 			outb(com+com_mcr,
-				inb(com+com_mcr) & ~(MCR_DTR | MCR_RTS) | MCR_IENABLE);
+			     ((inb(com+com_mcr) & ~(MCR_DTR | MCR_RTS))
+			      | enable));
 	} else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) &&
 		   (tp->t_flags & CRTSCTS)) {
 		/* the line is up and we want to do rts/cts flow control */
@@ -573,22 +614,24 @@
 	register com;
 	register int unit;
 	int s;
+	int enable;
 
 	unit = UNIT(dev);
+	enable = (com_multi & (1 << unit)) ? 0 : MCR_IENABLE;
 	com = com_addr[unit];
 	s = spltty();
 	switch (how) {
 
 	case DMSET:
-		outb(com+com_mcr, bits | MCR_IENABLE);
+		outb(com+com_mcr, bits | enable);
 		break;
 
 	case DMBIS:
-		outb(com+com_mcr, inb(com+com_mcr) | bits | MCR_IENABLE);
+		outb(com+com_mcr, inb(com+com_mcr) | bits | enable);
 		break;
 
 	case DMBIC:
-		outb(com+com_mcr, inb(com+com_mcr) & ~bits | MCR_IENABLE);
+		outb(com+com_mcr, inb(com+com_mcr) & ~bits | enable);
 		break;
 
 	case DMGET: