summaryrefslogtreecommitdiffstats
path: root/sys/dev/si/si.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/si/si.c')
-rw-r--r--sys/dev/si/si.c208
1 files changed, 93 insertions, 115 deletions
diff --git a/sys/dev/si/si.c b/sys/dev/si/si.c
index 8371391..e0912f8 100644
--- a/sys/dev/si/si.c
+++ b/sys/dev/si/si.c
@@ -30,7 +30,7 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHORS BE LIABLE.
*
- * $Id: si.c,v 1.3 1995/08/13 15:18:05 peter Exp $
+ * $Id: si.c,v 1.4 1995/08/13 15:44:37 peter Exp $
*/
#ifndef lint
@@ -86,7 +86,6 @@ enum si_mctl { GET, SET, BIS, BIC };
static void si_command __P((struct si_port *, int, int));
static int si_modem __P((struct si_port *, enum si_mctl, int));
static void si_write_enable __P((struct si_port *, int));
-static int si_drainwait __P((struct si_port *, char *));
static int si_Sioctl __P((dev_t, int, caddr_t, int, struct proc *));
static void si_start __P((struct tty *));
static void si_lstart __P((struct si_port *));
@@ -1347,6 +1346,7 @@ siparam(tp, t)
int error = 0; /* shutup gcc */
int ispeed = 0; /* shutup gcc */
int ospeed = 0; /* shutup gcc */
+ BYTE val;
DPRINT((pp, DBG_ENTRY|DBG_PARAM, "siparam(%x,%x)\n", tp, t));
cflag = t->c_cflag;
@@ -1373,91 +1373,120 @@ siparam(tp, t)
oldspl = spltty();
ccbp = pp->sp_ccb;
- if (iflag & IGNBRK) /* Breaks */
- ccbp->hi_break = BR_IGN;
- else
- ccbp->hi_break = 0;
- if (iflag & BRKINT) /* Interrupt on break? */
- ccbp->hi_break |= BR_INT;
- if (iflag & PARMRK) /* Parity mark? */
- ccbp->hi_break |= BR_PARMRK;
- if (iflag & IGNPAR) /* Ignore chars with parity errors? */
- ccbp->hi_break |= BR_PARIGN;
+ /* ========== set hi_break ========== */
+ val = 0;
+ if (iflag & IGNBRK) /* Breaks */
+ val |= BR_IGN;
+ if (iflag & BRKINT) /* Interrupt on break? */
+ val |= BR_INT;
+ if (iflag & PARMRK) /* Parity mark? */
+ val |= BR_PARMRK;
+ if (iflag & IGNPAR) /* Ignore chars with parity errors? */
+ val |= BR_PARIGN;
+ ccbp->hi_break = val;
+
+ /* ========== set hi_csr ========== */
/* if not hung up.. */
if (t->c_ospeed != 0) {
/* Set I/O speeds */
- ccbp->hi_csr = (ispeed << 4) | ospeed;
+ val = (ispeed << 4) | ospeed;
}
+ ccbp->hi_csr = val;
+ /* ========== set hi_mr2 ========== */
+ val = 0;
if (cflag & CSTOPB) /* Stop bits */
- ccbp->hi_mr2 = MR2_2_STOP;
+ val |= MR2_2_STOP;
else
- ccbp->hi_mr2 = MR2_1_STOP;
+ val |= MR2_1_STOP;
+ /*
+ * Enable H/W RTS/CTS handshaking. The default TA/MTA is
+ * a DCE, hence the reverse sense of RTS and CTS
+ */
+ /* Output Flow - RTS must be raised before data can be sent */
+ if (cflag & CCTS_OFLOW)
+ val |= MR2_RTSCONT;
+
+ ccbp->hi_mr1 = val;
+
+ /* ========== set hi_mr1 ========== */
+ val = 0;
if (!(cflag & PARENB)) /* Parity */
- ccbp->hi_mr1 = MR1_NONE;
+ val |= MR1_NONE;
else
- ccbp->hi_mr1 = MR1_WITH;
+ val |= MR1_WITH;
if (cflag & PARODD)
- ccbp->hi_mr1 |= MR1_ODD;
+ val |= MR1_ODD;
if ((cflag & CS8) == CS8) { /* 8 data bits? */
- ccbp->hi_mr1 |= MR1_8_BITS;
- ccbp->hi_mask = 0xFF;
+ val |= MR1_8_BITS;
} else if ((cflag & CS7) == CS7) { /* 7 data bits? */
- ccbp->hi_mr1 |= MR1_7_BITS;
- ccbp->hi_mask = 0x7F;
+ val |= MR1_7_BITS;
} else if ((cflag & CS6) == CS6) { /* 6 data bits? */
- ccbp->hi_mr1 |= MR1_6_BITS;
- ccbp->hi_mask = 0x3F;
+ val |= MR1_6_BITS;
} else { /* Must be 5 */
- ccbp->hi_mr1 |= MR1_5_BITS;
- ccbp->hi_mask = 0x1F;
+ val |= MR1_5_BITS;
}
+ /*
+ * Enable H/W RTS/CTS handshaking. The default TA/MTA is
+ * a DCE, hence the reverse sense of RTS and CTS
+ */
+ /* Input Flow - CTS is raised when port is ready to receive data */
+ if (cflag & CRTS_IFLOW)
+ val |= MR1_CTSCONT;
+ ccbp->hi_mr1 = val;
+
+ /* ========== set hi_mask ========== */
+ val = 0xff;
+ if ((cflag & CS8) == CS8) { /* 8 data bits? */
+ val &= 0xFF;
+ } else if ((cflag & CS7) == CS7) { /* 7 data bits? */
+ val &= 0x7F;
+ } else if ((cflag & CS6) == CS6) { /* 6 data bits? */
+ val &= 0x3F;
+ } else { /* Must be 5 */
+ val &= 0x1F;
+ }
if (iflag & ISTRIP)
- ccbp->hi_mask &= 0x7F;
+ val &= 0x7F;
+
+ ccbp->hi_mask = val;
+ /* ========== set hi_prtcl ========== */
+ val = 0;
/* Monitor DCD etc. if a modem */
if (!(cflag & CLOCAL))
- ccbp->hi_prtcl = SP_DCEN;
- else
- ccbp->hi_prtcl = 0;
-
- /* XXX: the card handles all the flow control... */
- ccbp->hi_txon = t->c_cc[VSTART];
- ccbp->hi_txoff = t->c_cc[VSTOP];
-
- ccbp->hi_rxon = t->c_cc[VSTART];
- ccbp->hi_rxoff = t->c_cc[VSTOP];
-
+ val |= SP_DCEN;
if (iflag & IXANY)
- ccbp->hi_prtcl |= SP_TANY;
+ val |= SP_TANY;
if (iflag & IXON)
- ccbp->hi_prtcl |= SP_TXEN;
+ val |= SP_TXEN;
if (iflag & IXOFF)
- ccbp->hi_prtcl |= SP_RXEN;
+ val |= SP_RXEN;
if (iflag & INPCK)
- ccbp->hi_prtcl |= SP_PAEN;
+ val |= SP_PAEN;
- /*
- * Enable H/W RTS/CTS handshaking. The default TA/MTA is
- * a DCE, hence the reverse sense of RTS and CTS
- */
+ ccbp->hi_prtcl = val;
- /* Output - RTS must be raised before data can be sent */
- if (cflag & CCTS_OFLOW)
- ccbp->hi_mr2 |= MR2_RTSCONT;
- /* Input - CTS is raised when port is ready to receive data */
- if (cflag & CRTS_IFLOW)
- ccbp->hi_mr1 |= MR1_CTSCONT;
+ /* ========== set hi_{rx|tx}{on|off} ========== */
+ /* XXX: the card TOTALLY shields us from the flow control... */
+ ccbp->hi_txon = t->c_cc[VSTART];
+ ccbp->hi_txoff = t->c_cc[VSTOP];
+
+ ccbp->hi_rxon = t->c_cc[VSTART];
+ ccbp->hi_rxoff = t->c_cc[VSTOP];
+
+ /* ========== send settings to the card ========== */
/* potential sleep here */
if (ccbp->hi_stat == IDLE_CLOSE) /* Not yet open */
si_command(pp, LOPEN, SI_WAIT); /* open it */
else
si_command(pp, CONFIG, SI_WAIT); /* change params */
+ /* ========== set DTR etc ========== */
/* Hangup if ospeed == 0 */
if (t->c_ospeed == 0) {
(void) si_modem(pp, BIC, TIOCM_DTR|TIOCM_RTS);
@@ -1478,65 +1507,6 @@ out:
}
/*
- * Wait for buffered TX characters to drain away.
- * IT IS THE RESPONSIBILITY OF THE CALLER TO DISABLE/ENABLE WRITES.
- */
-static int
-si_drainwait(pp, msg)
- register struct si_port *pp;
- char *msg;
-{
- register struct tty *tp = pp->sp_tty;
- volatile struct si_channel *ccbp = pp->sp_ccb;
- int error, oldspl, time;
- BYTE x;
-
- DPRINT((pp, DBG_ENTRY|DBG_DRAIN, "si_drainwait(%x,%s)\n",
- pp, msg));
- error = 0;
-
- oldspl = spltty();
-
- /* number of pending characters in output buffer */
- x = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
-
- while ( (x != 0 && (tp->t_state & TS_BUSY))
- || (ccbp->hi_stat == IDLE_BREAK)) {
-
- DPRINT((pp, DBG_DRAIN,
- " x %d. t_state %x sp_state %x hi_stat %x\n",
- x, tp->t_state, pp->sp_state, ccbp->hi_stat));
-
- /* else waiting got chars */
- /* guess how long */
- time = ttspeedtab(tp->t_ospeed, chartimes);
-
- if (time == 0 || time > x)
- time = 1;
- else
- time = x/time + 1;
-
- error = ttysleep(tp, (caddr_t)pp,
- TTOPRI|PCATCH, msg, time);
-
- if (error != EWOULDBLOCK) {
- DPRINT((pp, DBG_DRAIN|DBG_FAIL,
- "%s, wait for drain broken by signal %d\n",
- msg, error));
- break;
- }
- error = 0;
-
- /* reload count */
- x = (int)ccbp->hi_txipos - (int)ccbp->hi_txopos;
- }
- tp->t_state &= ~TS_BUSY;
- ttwwakeup(tp);
- splx(oldspl);
- return(error);
-}
-
-/*
* Enable or Disable the writes to this channel...
* "state" -> enabled = 1; disabled = 0;
*/
@@ -1688,7 +1658,7 @@ out:
* it is called.
*/
-static char rxbuf[SLXOS_BUFFERSIZE]; /* input staging area */
+static BYTE rxbuf[SLXOS_BUFFERSIZE]; /* input staging area */
int
siintr(int bdnum)
@@ -1701,7 +1671,7 @@ siintr(int bdnum)
register struct tty *tp;
volatile caddr_t maddr;
BYTE op, ip, cc;
- int x, card, port, n;
+ int x, card, port, n, i;
volatile BYTE *z;
BYTE c;
static int in_poll = 0;
@@ -1889,8 +1859,11 @@ siintr(int bdnum)
}
} else {
for(x = 0; x < n; x++) {
- (*linesw[tp->t_line].l_rint)(
- rxbuf[x], tp);
+ i = rxbuf[x];
+ (*linesw[tp->t_line].l_rint)(rxbuf[x], tp);
+ if (pp->sp_hotchar && i == pp->sp_hotchar) {
+ setsofttty();
+ }
}
}
@@ -2187,6 +2160,7 @@ si_disc_optim(tp, t, pp)
tp->t_state |= TS_CAN_BYPASS_L_RINT;
else
tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
+
/*
* Prepare to reduce input latency for packet
* discplines with a end of packet character.
@@ -2197,6 +2171,10 @@ si_disc_optim(tp, t, pp)
pp->sp_hotchar = 0x7e;
else
pp->sp_hotchar = 0;
+
+ DPRINT((pp, DBG_OPTIM, "bypass: %s, hotchar: %x\n",
+ (tp->t_state & TS_CAN_BYPASS_L_RINT) ? "on" : "off",
+ pp->sp_hotchar));
}
OpenPOWER on IntegriCloud