summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-05-04 06:13:22 +0000
committerpeter <peter@FreeBSD.org>1996-05-04 06:13:22 +0000
commitc1aa340b208998228bacdb4a155e41ae823176f8 (patch)
treed1c893237c7c58ab721b4086154c24b18b74f3e0 /sys
parente8c7788704b1c60ca56c64a490f0e9ad9df3e585 (diff)
parentb200fe400c41fa4c3b0962412950112c37be1a2a (diff)
downloadFreeBSD-src-c1aa340b208998228bacdb4a155e41ae823176f8.zip
FreeBSD-src-c1aa340b208998228bacdb4a155e41ae823176f8.tar.gz
This commit was generated by cvs2svn to compensate for changes in r15593,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/isa/README.stl47
-rw-r--r--sys/i386/isa/ic/scd1400.h10
-rw-r--r--sys/i386/isa/stallion.c322
3 files changed, 311 insertions, 68 deletions
diff --git a/sys/i386/isa/README.stl b/sys/i386/isa/README.stl
index 312eaa0..1c55226 100644
--- a/sys/i386/isa/README.stl
+++ b/sys/i386/isa/README.stl
@@ -2,8 +2,8 @@
Stallion Multiport Serial Driver Readme
---------------------------------------
-Version: 0.0.2 alpha
-Date: 08JAN96
+Version: 0.0.3 alpha
+Date: 05FEB96
Author: Greg Ungerer (gerg@stallion.oz.au)
@@ -32,13 +32,12 @@ other good stuff).
The EasyIO range of cards comes in 3 forms, the EasyIO-4, EasyIO-8 and the
EasyIO-8M. All of these are non-expandable, low cost, ISA, multiport boards
-with 4, 8 and 8 RS-232C ports respectively. The EasyIO-8M is not currently
-supported by this driver. Though it is pretty easy to support so I'll do
-that when I get a chance. Each EasyIO board requires 8 bytes of IO address
-space and 1 interrupt. On an EISA system it is possible to share 1 interrupt
-between multiple boards. The EasyIO-4 has 10 pin RJ connectors, and the
-EasyIO-8 comes with a dongle cable that can be either 10 pin RJ connectors or
-DB-25 connectors. The EasyIO-8M has 6 pin RJ connectors.
+with 4, 8 and 8 RS-232C ports respectively. Each EasyIO board requires 8
+bytes of IO address space and 1 interrupt. On an EISA system it is possible
+to share 1 interrupt between multiple boards. The EasyIO-4 has 10 pin RJ
+connectors, and the EasyIO-8 comes with a dongle cable that can be either
+10 pin RJ connectors or DB-25 connectors. The EasyIO-8M has 6 pin RJ
+connectors.
The EasyConnection 8/32 family of boards is a relatively low cost modular
range of multiport serial boards. The EasyConnection 8/32 boards can be
@@ -60,6 +59,19 @@ I am working on drivers for other boards in the Stallion range, so look
out for those some time soon...
+1.1 HOW TO GET BOARDS
+
+Stallion Technologies has offices all over the world, as well as many more
+distributors and resellers. To find out about local availability please
+contact the nearest Stallion office and they can give you all the information
+you need. Look in the "Offices" file in the driver package for a current list
+of Stallion Technologies offices.
+
+Another good source of information about the Stallion range of boards and
+local availability is on the Stallion Web page. Check it out at
+http://www.stallion.com.
+
+
2. INSTALLATION
@@ -71,8 +83,8 @@ You will need to build a new kernel to use this driver. So the first thing
you need is to have the full kernel source. Most people will have this
(I hope!). The following assumes that the kernel source is in /usr/src/sys.
-The driver can support up to 8 boards (any combination of EasyIO and
-EasyConnection 8/32 boards). So there is a theoretical maximum of 256 ports.
+The driver can support up to 8 boards, with any combination of EasyIO and
+EasyConnection 8/32 boards. So there is a theoretical maximum of 256 ports.
(Off-course I have not tested a system with this many!)
Instructions to install:
@@ -82,10 +94,11 @@ Instructions to install:
cp stallion.c /usr/src/sys/i386/isa
cp scd1400.h /usr/src/sys/i386/ic
- Note: if you are not using FreeBSD 2.1.0 then you may need to edit the
+ Note: if you are NOT using FreeBSD 2.1.0 then you will need to edit the
stallion.c file and change the VFREEBSD define to match your version.
-2. Add a character device switch table entry for the driver into the cdevsw
+2. (Note: skip to next step if on a FreeBSD kernel later than 2.1.0)
+ Add a character device switch table entry for the driver into the cdevsw
table structure. This involves adding some code into the kernel conf.c
file:
@@ -150,10 +163,15 @@ i386/isa/stallion.c optional stl device-driver
- if you already have a kernel config that you use then you
could just use that (instead of MYKERNEL)
vi MYKERNEL
+ - if only using ECH-PCI boards then you don't need to enter a
+ configuration line, the kernel will automatically detect
+ the board at boot up, so skip to step 5.
- enter a line for each board that you want to use, eg:
device stl0 at isa? port 0x2a0 tty irq 10 vector stlintr
+ (I suggest you put them after the sio? entries)
+ (Don't enter lines for ECH-PCI boards)
- change the io address and irq in this line as required
- save the file and exit
@@ -231,9 +249,6 @@ Be aware that this driver is still very new, so there is sure to be some bugs
in it. Please email me any feedback on bugs, problems, or even good
experiences with this driver!
-There is no real smart line discipline bypass code yet (like in the sio
-driver). I will add this for the next driver release.
-
I will probably also add LKM support some time soon.
diff --git a/sys/i386/isa/ic/scd1400.h b/sys/i386/isa/ic/scd1400.h
index b9cdcee..d3f3f26 100644
--- a/sys/i386/isa/ic/scd1400.h
+++ b/sys/i386/isa/ic/scd1400.h
@@ -35,7 +35,6 @@
*/
/*****************************************************************************/
-
#ifndef _CD1400_H
#define _CD1400_H
/*****************************************************************************/
@@ -45,8 +44,6 @@
*/
#define CD1400_PORTS 4
-#define CD1400_CLKHZ 25000000
-
/*
* Define the cd1400 uarts internal FIFO sizes.
*/
@@ -179,11 +176,16 @@
#define COR3_SCD12 0x10
/*
- * Define values used by COR4.
+ * Define the bit values of COR4.
*/
#define COR4_BRKINT 0x08
#define COR4_IGNBRK 0x18
+/*
+ * Define the bit values of COR5.
+ */
+#define COR5_ISTRIP 0x80
+
/*****************************************************************************/
/*
diff --git a/sys/i386/isa/stallion.c b/sys/i386/isa/stallion.c
index 4b43463..68c2683 100644
--- a/sys/i386/isa/stallion.c
+++ b/sys/i386/isa/stallion.c
@@ -3,7 +3,7 @@
/*
* stallion.c -- stallion multiport serial driver.
*
- * Copyright (c) 1995 Greg Ungerer (gerg@stallion.oz.au).
+ * Copyright (c) 1995-1996 Greg Ungerer (gerg@stallion.oz.au).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,12 +50,17 @@
#include <sys/uio.h>
#include <sys/syslog.h>
#include <sys/devconf.h>
-
#include <machine/cpu.h>
#include <machine/clock.h>
#include <i386/isa/isa_device.h>
#include <i386/isa/ic/scd1400.h>
+#include <pci.h>
+#if NPCI > 0
+#include <pci/pcivar.h>
+#include <pci/pcireg.h>
+#endif
+
/*****************************************************************************/
/*
@@ -121,11 +126,11 @@ static unsigned int stl_irqshared = 0;
* a good balance between performance and memory usage. These seem
* to work pretty well...
*/
-#define STL_RXBUFSIZE 1024
-#define STL_TXBUFSIZE 1024
+#define STL_RXBUFSIZE 2048
+#define STL_TXBUFSIZE 2048
-#define STL_TXBUFLOW 256
-#define STL_RXBUFHIGH 768
+#define STL_TXBUFLOW (STL_TXBUFSIZE / 4)
+#define STL_RXBUFHIGH (3 * STL_RXBUFSIZE / 4)
/*****************************************************************************/
@@ -135,7 +140,7 @@ static unsigned int stl_irqshared = 0;
*/
static char *stl_drvname = "stl";
static char *stl_longdrvname = "Stallion Multiport Serial Driver";
-static char *stl_drvversion = "0.0.2";
+static char *stl_drvversion = "0.0.3";
static int stl_brdprobed[STL_MAXBRDS];
static int stl_nrbrds = 0;
@@ -204,11 +209,13 @@ typedef struct {
int dtrwait;
int dotimestamp;
int waitopens;
+ int hotchar;
unsigned int state;
unsigned int sigs;
unsigned int rxignoremsk;
unsigned int rxmarkmsk;
unsigned int rxerrs[STL_NRRXERRS];
+ unsigned long clk;
struct termios initintios;
struct termios initouttios;
struct termios lockintios;
@@ -242,6 +249,7 @@ typedef struct {
unsigned int iostatus;
unsigned int ioctrl;
unsigned int ioctrlval;
+ unsigned long clk;
stlpanel_t *panels[STL_MAXPANELS];
stlport_t *ports[STL_PORTSPERBRD];
} stlbrd_t;
@@ -264,6 +272,8 @@ static stlbrd_t *stl_brds[STL_MAXBRDS];
#define ASY_DCDCHANGE 0x4
#define ASY_DTRWAIT 0x8
#define ASY_RTSFLOW 0x10
+#define ASY_RTSFLOWMODE 0x20
+#define ASY_CTSFLOWMODE 0x40
#define ASY_ACTIVE (ASY_TXLOW | ASY_RXDATA | ASY_DCDCHANGE)
@@ -337,6 +347,10 @@ static char *stl_brdnames[] = {
#define ECH_PNLINTRPEND 0x80
#define ECH_ADDR2MASK 0x1e0
+#define EIO_CLK 25000000
+#define EIO_CLK8M 20000000
+#define ECH_CLK EIO_CLK
+
/*
* Define the offsets within the register bank for all io registers.
* These io address offsets are common to both the EIO and ECH.
@@ -350,6 +364,11 @@ static char *stl_brdnames[] = {
#define EREG_BANKSIZE 8
/*
+ * Define the PCI vendor and device id for ECH8/32-PCI.
+ */
+#define STL_PCIDEVID 0xd001100b
+
+/*
* Define the vector mapping bits for the programmable interrupt board
* hardware. These bits encode the interrupt for the board to use - it
* is software selectable (except the EIO-8M).
@@ -427,17 +446,19 @@ STATIC d_stop_t stlstop;
#if VFREEBSD >= 220
STATIC d_devtotty_t stldevtotty;
#else
-struct tty *stldevtotty(dev_t dev);
+struct tty *stldevtotty(dev_t dev);
#endif
/*
* Internal function prototypes.
*/
static stlport_t *stl_dev2port(dev_t dev);
+static int stl_findfreeunit(void);
static int stl_rawopen(stlport_t *portp);
static int stl_rawclose(stlport_t *portp);
static int stl_param(struct tty *tp, struct termios *tiosp);
static void stl_start(struct tty *tp);
+static void stl_ttyoptim(stlport_t *portp, struct termios *tiosp);
static void stl_dotimeout(void);
static void stl_poll(void *arg);
static void stl_rxprocess(stlport_t *portp);
@@ -462,6 +483,12 @@ static void stl_disableintrs(stlport_t *portp);
static void stl_sendbreak(stlport_t *portp, long len);
static void stl_flush(stlport_t *portp, int flag);
+#if NPCI > 0
+static char *stlpciprobe(pcici_t tag, pcidi_t type);
+static void stlpciattach(pcici_t tag, int unit);
+static int stlpciintr(void * arg);
+#endif
+
/*****************************************************************************/
/*
@@ -473,13 +500,34 @@ struct isa_driver stldriver = {
/*****************************************************************************/
+#if NPCI > 0
+
+/*
+ * Declare the driver pci structure.
+ */
+static unsigned long stl_count;
+
+static struct pci_device stlpcidriver = {
+ "stl",
+ stlpciprobe,
+ stlpciattach,
+ &stl_count,
+ NULL,
+};
+
+DATA_SET (pcidevice_set, stlpcidriver);
+
+#endif
+
+/*****************************************************************************/
+
#if VFREEBSD >= 220
/*
* FreeBSD-2.2+ kernel linkage.
*/
-#define CDEV_MAJOR 70
+#define CDEV_MAJOR 72
static struct cdevsw stl_cdevsw =
{ stlopen, stlclose, stlread, stlwrite,
@@ -508,7 +556,8 @@ SYSINIT(sidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,stl_drvinit,NULL)
/*
* Probe for some type of EasyIO or EasyConnection 8/32 board at
* the supplied address. All we do is check if we can find the
- * board ID for the board...
+ * board ID for the board... (Note, PCI boards not checked here,
+ * they are done in the stlpciprobe() routine).
*/
int stlprobe(struct isa_device *idp)
@@ -547,6 +596,24 @@ int stlprobe(struct isa_device *idp)
/*****************************************************************************/
/*
+ * Find an available internal board number (unit number). The problem
+ * is that the same unit numbers can be assigned to different boards
+ * detected during the ISA and PCI initialization phases.
+ */
+
+static int stl_findfreeunit()
+{
+ int i;
+
+ for (i = 0; (i < STL_MAXBRDS); i++)
+ if (stl_brds[i] == (stlbrd_t *) NULL)
+ break;
+ return((i >= STL_MAXBRDS) ? -1 : i);
+}
+
+/*****************************************************************************/
+
+/*
* Allocate resources for and initialize the specified board.
*/
@@ -567,10 +634,14 @@ int stlattach(struct isa_device *idp)
}
bzero(brdp, sizeof(stlbrd_t));
- if (idp->id_unit >= stl_nrbrds)
- stl_nrbrds = idp->id_unit + 1;
+ if ((brdp->brdnr = stl_findfreeunit()) < 0) {
+ printf("STALLION: too many boards found, max=%d\n",
+ STL_MAXBRDS);
+ return(0);
+ }
+ if (brdp->brdnr >= stl_nrbrds)
+ stl_nrbrds = brdp->brdnr + 1;
- brdp->brdnr = idp->id_unit;
brdp->brdtype = stl_brdprobed[idp->id_unit];
brdp->ioaddr1 = idp->id_iobase;
brdp->ioaddr2 = stl_ioshared;
@@ -583,6 +654,95 @@ int stlattach(struct isa_device *idp)
/*****************************************************************************/
+#if NPCI > 0
+
+/*
+ * Probe specifically for the PCI boards. We need to be a little
+ * carefull here, since it looks sort like a Nat Semi IDE chip...
+ */
+
+char *stlpciprobe(pcici_t tag, pcidi_t type)
+{
+ unsigned long class;
+
+#if DEBUG
+ printf("stlpciprobe(tag=%x,type=%x)\n", (int) &tag, (int) type);
+#endif
+
+ switch (type) {
+ case STL_PCIDEVID:
+ break;
+ default:
+ return((char *) NULL);
+ }
+
+ class = pci_conf_read(tag, PCI_CLASS_REG);
+ if ((class & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE)
+ return((char *) NULL);
+
+ return("Stallion EasyConnection 8/32-PCI");
+}
+
+/*****************************************************************************/
+
+/*
+ * Allocate resources for and initialize the specified PCI board.
+ */
+
+void stlpciattach(pcici_t tag, int unit)
+{
+ stlbrd_t *brdp;
+ unsigned long iobase, iopage, irq;
+
+#if DEBUG
+ printf("stlpciattach(tag=%x,unit=%x)\n", (int) &tag, unit);
+#endif
+
+ brdp = (stlbrd_t *) malloc(sizeof(stlbrd_t), M_TTYS, M_NOWAIT);
+ if (brdp == (stlbrd_t *) NULL) {
+ printf("STALLION: failed to allocate memory (size=%d)\n",
+ sizeof(stlbrd_t));
+ return;
+ }
+ bzero(brdp, sizeof(stlbrd_t));
+
+ if ((unit < 0) || (unit > STL_MAXBRDS)) {
+ printf("STALLION: bad PCI board unit number=%d\n", unit);
+ return;
+ }
+
+/*
+ * Allocate us a new driver unique unit number.
+ */
+ if ((brdp->brdnr = stl_findfreeunit()) < 0) {
+ printf("STALLION: too many boards found, max=%d\n",
+ STL_MAXBRDS);
+ return;
+ }
+ if (brdp->brdnr >= stl_nrbrds)
+ stl_nrbrds = brdp->brdnr + 1;
+
+ brdp->brdtype = BRD_ECHPCI;
+ brdp->ioaddr1 = ((unsigned int) pci_conf_read(tag, 0x14)) & 0xfffc;
+ brdp->ioaddr2 = ((unsigned int) pci_conf_read(tag, 0x10)) & 0xfffc;
+ brdp->irq = ((int) pci_conf_read(tag, 0x3c)) & 0xff;
+ brdp->irqtype = 0;
+ if (pci_map_int(tag, stlpciintr, (void *) NULL, &tty_imask) == 0) {
+ printf("STALLION: failed to map interrupt irq=%d for unit=%d\n",
+ brdp->irq, brdp->brdnr);
+ return;
+ }
+
+#if 0
+ printf("%s(%d): ECH-PCI iobase=%x iopage=%x irq=%d\n", __file__, __LINE__, brdp->ioaddr2, brdp->ioaddr1, brdp->irq);
+#endif
+ stl_brdinit(brdp);
+}
+
+#endif
+
+/*****************************************************************************/
+
STATIC int stlopen(dev_t dev, int flag, int mode, struct proc *p)
{
struct tty *tp;
@@ -600,7 +760,6 @@ STATIC int stlopen(dev_t dev, int flag, int mode, struct proc *p)
portp = stl_dev2port(dev);
if (portp == (stlport_t *) NULL)
return(ENXIO);
-
tp = &portp->tty;
callout = minor(dev) & STL_CALLOUTDEV;
error = 0;
@@ -666,7 +825,7 @@ stlopen_restart:
((tp->t_cflag & CLOCAL) == 0) &&
((flag & O_NONBLOCK) == 0)) {
portp->waitopens++;
- error = tsleep(TSA_CARR_ON(tp), (TTIPRI | PCATCH), "stldcd",0);
+ error = tsleep(TSA_CARR_ON(tp), (TTIPRI | PCATCH), "stldcd", 0);
portp->waitopens--;
if (error)
goto stlopen_end;
@@ -677,6 +836,7 @@ stlopen_restart:
* Open the line discipline.
*/
error = (*linesw[tp->t_line].l_open)(dev, tp);
+ stl_ttyoptim(portp, &tp->t_termios);
if ((tp->t_state & TS_ISOPEN) && callout)
portp->callout = 1;
@@ -712,6 +872,7 @@ STATIC int stlclose(dev_t dev, int flag, int mode, struct proc *p)
x = spltty();
(*linesw[tp->t_line].l_close)(tp, flag);
+ stl_ttyoptim(portp, &tp->t_termios);
stl_rawclose(portp);
ttyclose(tp);
splx(x);
@@ -737,24 +898,30 @@ STATIC int stlread(dev_t dev, struct uio *uiop, int flag)
/*****************************************************************************/
#if VFREEBSD >= 220
+
STATIC void stlstop(struct tty *tp, int rw)
-#else
-STATIC int stlstop(struct tty *tp, int rw)
-#endif
{
#if DEBUG
printf("stlstop(tp=%x,rw=%x)\n", (int) tp, rw);
#endif
stl_flush((stlport_t *) tp, rw);
+}
-#if VFREEBSD >= 220
- return;
#else
- return(0);
+
+STATIC int stlstop(struct tty *tp, int rw)
+{
+#if DEBUG
+ printf("stlstop(tp=%x,rw=%x)\n", (int) tp, rw);
#endif
+
+ stl_flush((stlport_t *) tp, rw);
+ return(0);
}
+#endif
+
/*****************************************************************************/
STATIC struct tty *stldevtotty(dev_t dev)
@@ -890,6 +1057,7 @@ STATIC int stlioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
x = spltty();
error = ttioctl(tp, cmd, data, flag);
+ stl_ttyoptim(portp, &tp->t_termios);
if (error >= 0) {
splx(x);
return(error);
@@ -1104,9 +1272,6 @@ static void stl_start(struct tty *tp)
}
#endif
-/*
- * Do not transmit if we are timing out or stopped.
- */
if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
splx(x);
return;
@@ -1450,7 +1615,7 @@ static inline void stl_rxisr(stlpanel_t *panelp, int ioaddr)
*/
if (buflen <= (STL_RXBUFSIZE - STL_RXBUFHIGH)) {
if (((portp->state & ASY_RTSFLOW) == 0) &&
- (tp->t_cflag & CRTS_IFLOW)) {
+ (portp->state & ASY_RTSFLOWMODE)) {
portp->state |= ASY_RTSFLOW;
stl_setreg(portp, MCOR1,
(stl_getreg(portp, MCOR1) & 0xf0));
@@ -1497,6 +1662,10 @@ static inline void stl_rxisr(stlpanel_t *panelp, int ioaddr)
if (status & ST_OVERRUN)
portp->rxerrs[STL_RXOVERRUN]++;
if ((portp->rxignoremsk & status) == 0) {
+ if ((tp->t_state & TS_CAN_BYPASS_L_RINT) &&
+ ((status & ST_FRAMING) ||
+ ((status & ST_PARITY) && (tp->t_iflag & INPCK))))
+ ch = 0;
if ((portp->rxmarkmsk & status) == 0)
status = 0;
*(head + STL_RXBUFSIZE) = status;
@@ -1700,6 +1869,18 @@ void stlintr(int unit)
/*****************************************************************************/
+#if NPCI > 0
+
+static int stlpciintr(void *arg)
+{
+ stlintr(0);
+ return(1);
+}
+
+#endif
+
+/*****************************************************************************/
+
/*
* If we haven't scheduled a timeout then do it, some port needs high
* level processing.
@@ -1782,7 +1963,7 @@ static void stl_poll(void *arg)
static void stl_rxprocess(stlport_t *portp)
{
struct tty *tp;
- unsigned int len, stlen;
+ unsigned int len, stlen, lostlen;
char *head, *tail;
char status;
int ch;
@@ -1815,10 +1996,23 @@ static void stl_rxprocess(stlport_t *portp)
}
if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
-#if 1
-printf("%s(%d): cannot TS_CAN_BYPASS_L_RINT!\n", __file__, __LINE__);
-#else
if (len > 0) {
+ if (((tp->t_rawq.c_cc + len) >= TTYHOG) &&
+ ((portp->state & ASY_RTSFLOWMODE) ||
+ (tp->t_iflag & IXOFF)) &&
+ ((tp->t_state & TS_TBLOCK) == 0)) {
+#if 1
+ if ((TTYHOG - tp->t_rawq.c_cc - 1) < 0)
+ printf("%s(%d): len < 0, len=%d "
+ "stlen=%d TTYHOG=%d cc=%d\n",
+ __file__, __LINE__, len,
+ stlen, TTYHOG, tp->t_rawq.c_cc);
+#endif
+ ch = TTYHOG - tp->t_rawq.c_cc - 1;
+ len = (ch > 0) ? ch : 0;
+ stlen = MIN(stlen, len);
+ ttyblock(tp);
+ }
lostlen = b_to_q(tail, stlen, &tp->t_rawq);
tail += stlen;
len -= stlen;
@@ -1829,14 +2023,8 @@ printf("%s(%d): cannot TS_CAN_BYPASS_L_RINT!\n", __file__, __LINE__);
}
portp->rxerrs[STL_RXLDLOST] += lostlen;
ttwakeup(tp);
- if (tp->t_state & TS_TTSTOP) {
- tp->t_state &= ~TS_TTSTOP;
- tp->t_lflag &= ~FLUSHO;
- ttstart(tp);
- }
portp->rx.tail = tail;
}
-#endif
} else {
while (portp->rx.tail != head) {
ch = *(portp->rx.tail);
@@ -1960,6 +2148,9 @@ static int stl_param(struct tty *tp, struct termios *tiosp)
cor1 |= COR1_PARNONE;
}
+ if (tiosp->c_iflag & ISTRIP)
+ cor5 |= COR5_ISTRIP;
+
/*
* Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
* space for hardware flow control and the like. This should be set to
@@ -1982,7 +2173,7 @@ static int stl_param(struct tty *tp, struct termios *tiosp)
if (tiosp->c_ospeed > 0) {
for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
- clkdiv = ((CD1400_CLKHZ / stl_cd1400clkdivs[clk]) /
+ clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) /
tiosp->c_ospeed);
if (clkdiv < 0x100)
break;
@@ -2018,10 +2209,9 @@ static int stl_param(struct tty *tp, struct termios *tiosp)
mcor1 |= FIFO_RTSTHRESHOLD;
/*
- * All register cd1400 register values calculated so go through and set
- * them all up.
+ * All cd1400 register values calculated so go through and set them
+ * all up.
*/
-
#if DEBUG
printf("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", portp->portnr,
portp->panelnr, portp->brdnr);
@@ -2040,12 +2230,9 @@ static int stl_param(struct tty *tp, struct termios *tiosp)
stl_setreg(portp, CAR, (portp->portnr & 0x3));
srer = stl_getreg(portp, SRER);
stl_setreg(portp, SRER, 0);
- if (stl_updatereg(portp, COR1, cor1))
- ccr = 1;
- if (stl_updatereg(portp, COR2, cor2))
- ccr = 1;
- if (stl_updatereg(portp, COR3, cor3))
- ccr = 1;
+ ccr += stl_updatereg(portp, COR1, cor1);
+ ccr += stl_updatereg(portp, COR2, cor2);
+ ccr += stl_updatereg(portp, COR3, cor3);
if (ccr) {
stl_ccrwait(portp);
stl_setreg(portp, CCR, CCR_CORCHANGE);
@@ -2075,6 +2262,10 @@ static int stl_param(struct tty *tp, struct termios *tiosp)
portp->sigs &= ~TIOCM_CD;
stl_setreg(portp, SRER, ((srer & ~sreroff) | sreron));
BRDDISABLE(portp->brdnr);
+ portp->state &= ~(ASY_RTSFLOWMODE | ASY_CTSFLOWMODE);
+ portp->state |= ((tiosp->c_cflag & CRTS_IFLOW) ? ASY_RTSFLOWMODE : 0);
+ portp->state |= ((tiosp->c_cflag & CCTS_OFLOW) ? ASY_CTSFLOWMODE : 0);
+ stl_ttyoptim(portp, tiosp);
enable_intr();
return(0);
}
@@ -2097,7 +2288,7 @@ static void stl_flowcontrol(stlport_t *portp, int hw, int sw)
hwflow = -1;
- if (portp->tty.t_cflag & CRTS_IFLOW) {
+ if (portp->state & ASY_RTSFLOWMODE) {
if (hw == 0) {
if ((portp->state & ASY_RTSFLOW) == 0)
hwflow = 0;
@@ -2320,6 +2511,35 @@ static void stl_sendbreak(stlport_t *portp, long len)
/*****************************************************************************/
/*
+ * Enable l_rint processing bypass mode if tty modes allow it.
+ */
+
+static void stl_ttyoptim(stlport_t *portp, struct termios *tiosp)
+{
+ struct tty *tp;
+
+ tp = &portp->tty;
+ if (((tiosp->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR)) == 0) &&
+ (((tiosp->c_iflag & BRKINT) == 0) || (tiosp->c_iflag & IGNBRK)) &&
+ (((tiosp->c_iflag & PARMRK) == 0) ||
+ ((tiosp->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))) &&
+ ((tiosp->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) ==0) &&
+ (linesw[tp->t_line].l_rint == ttyinput))
+ tp->t_state |= TS_CAN_BYPASS_L_RINT;
+ else
+ tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
+
+ if (tp->t_line == SLIPDISC)
+ portp->hotchar = 0xc0;
+ else if (tp->t_line == PPPDISC)
+ portp->hotchar = 0x7e;
+ else
+ portp->hotchar = 0;
+}
+
+/*****************************************************************************/
+
+/*
* Try and find and initialize all the ports on a panel. We don't care
* what sort of board these ports are on - since the port io registers
* are almost identical when dealing with ports.
@@ -2401,6 +2621,7 @@ static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
portp->portnr = i;
portp->brdnr = panelp->brdnr;
portp->panelnr = panelp->panelnr;
+ portp->clk = brdp->clk;
portp->ioaddr = ioaddr;
portp->uartaddr = (i & 0x4) << 5;
portp->pagenr = panelp->pagenr + (i >> 3);
@@ -2461,11 +2682,14 @@ static int stl_initeio(stlbrd_t *brdp)
brdp->ioctrl = brdp->ioaddr1 + 1;
brdp->iostatus = brdp->ioaddr1 + 2;
+ brdp->clk = EIO_CLK;
status = inb(brdp->iostatus);
switch (status & EIO_IDBITMASK) {
- case EIO_8PORTRS:
case EIO_8PORTM:
+ brdp->clk = EIO_CLK8M;
+ /* fall thru */
+ case EIO_8PORTRS:
case EIO_8PORTDI:
brdp->nrports = 8;
break;
@@ -2569,6 +2793,8 @@ static int stl_initech(stlbrd_t *brdp)
brdp->ioctrl = brdp->ioaddr1 + 2;
}
+ brdp->clk = ECH_CLK;
+
/*
* Scan through the secondary io address space looking for panels.
* As we find'em allocate and initialize panel structures for each.
@@ -2678,7 +2904,7 @@ static int stl_brdinit(stlbrd_t *brdp)
}
}
- printf("stl%d: %s (driver version %s) nrpanels=%d nrports=%d\n",
+ printf("stl(%d): %s (driver version %s) nrpanels=%d nrports=%d\n",
brdp->brdnr, stl_brdnames[brdp->brdtype], stl_drvversion,
brdp->nrpanels, brdp->nrports);
return(0);
OpenPOWER on IntegriCloud