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: