summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorgwr <gwr@NetBSD.org>1996-04-10 21:44:35 +0000
committergwr <gwr@NetBSD.org>1996-04-10 21:44:35 +0000
commit32d12d3be499df36aa968d255ab0a9997bc0731b (patch)
tree6e92cef7a6bb8d8f043b486545990cf8a6c6f105 /sys/dev
parent5eb08a6790bbacb4c9443f004a009ad6e162f644 (diff)
Make the ring size configurable in the tty driver.
Make the pseudo-interrupt functions return void. Call the tty layer at spltty (to be safe).
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/z8530sc.c47
-rw-r--r--sys/dev/ic/z8530sc.h12
-rw-r--r--sys/dev/ic/z8530tty.c167
-rw-r--r--sys/dev/ic/z8530var.h12
-rw-r--r--sys/dev/sun/kbd.c252
-rw-r--r--sys/dev/sun/ms.c34
6 files changed, 301 insertions, 223 deletions
diff --git a/sys/dev/ic/z8530sc.c b/sys/dev/ic/z8530sc.c
index b564817822e..454b4618d14 100644
--- a/sys/dev/ic/z8530sc.c
+++ b/sys/dev/ic/z8530sc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: z8530sc.c,v 1.2 1996/01/30 22:35:09 gwr Exp $ */
+/* $NetBSD: z8530sc.c,v 1.3 1996/04/10 21:44:35 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -116,11 +116,13 @@ zs_iflush(cs)
if ((rr0 & ZSRR0_RX_READY) == 0)
break;
- /* Read the data. */
+ /*
+ * First read the status, because reading the data
+ * destroys the status of this char.
+ */
+ rr1 = zs_read_reg(cs, 1);
c = zs_read_data(cs);
- /* Need to read status register too? */
- rr1 = zs_read_reg(cs, 1);
if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
/* Clear the receive error. */
zs_write_csr(cs, ZSWR0_RESET_ERRORS);
@@ -220,13 +222,12 @@ zsc_intr_hard(arg)
register struct zsc_softc *zsc = arg;
register struct zs_chanstate *cs_a;
register struct zs_chanstate *cs_b;
- register int rval, soft;
+ register int rval;
register u_char rr3;
cs_a = &zsc->zsc_cs[0];
cs_b = &zsc->zsc_cs[1];
rval = 0;
- soft = 0;
/* Note: only channel A has an RR3 */
rr3 = zs_read_reg(cs_a, 3);
@@ -237,18 +238,18 @@ zsc_intr_hard(arg)
if (rr3 & ZSRR3_IP_B_RX)
(*cs_b->cs_ops->zsop_rxint)(cs_b);
+ /* Handle status interrupts (i.e. flow control). */
+ if (rr3 & ZSRR3_IP_A_STAT)
+ (*cs_a->cs_ops->zsop_stint)(cs_a);
+ if (rr3 & ZSRR3_IP_B_STAT)
+ (*cs_b->cs_ops->zsop_stint)(cs_b);
+
/* Handle transmit done interrupts. */
if (rr3 & ZSRR3_IP_A_TX)
(*cs_a->cs_ops->zsop_txint)(cs_a);
if (rr3 & ZSRR3_IP_B_TX)
(*cs_b->cs_ops->zsop_txint)(cs_b);
- /* Handle status interrupts. */
- if (rr3 & ZSRR3_IP_A_STAT)
- (*cs_a->cs_ops->zsop_stint)(cs_a);
- if (rr3 & ZSRR3_IP_B_STAT)
- (*cs_b->cs_ops->zsop_stint)(cs_b);
-
/* Clear interrupt. */
if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
zs_write_csr(cs_a, ZSWR0_CLR_INTR);
@@ -259,8 +260,7 @@ zsc_intr_hard(arg)
rval |= 2;
}
- if ((cs_a->cs_softreq) || (cs_b->cs_softreq))
- {
+ if ((cs_a->cs_softreq) || (cs_b->cs_softreq)) {
/* This is a machine-dependent function (or macro). */
zsc_req_softint(zsc);
}
@@ -278,18 +278,19 @@ zsc_intr_soft(arg)
{
register struct zsc_softc *zsc = arg;
register struct zs_chanstate *cs;
- register int req, rval, s, unit;
+ register int rval, unit;
rval = 0;
for (unit = 0; unit < 2; unit++) {
cs = &zsc->zsc_cs[unit];
- s = splzs();
- req = cs->cs_softreq;
- cs->cs_softreq = 0;
- splx(s);
-
- if (req) {
+ /*
+ * The softint flag can be safely cleared once
+ * we have decided to call the softint routine.
+ * (No need to do splzs() first.)
+ */
+ if (cs->cs_softreq) {
+ cs->cs_softreq = 0;
(*cs->cs_ops->zsop_softint)(cs);
rval = 1;
}
@@ -298,7 +299,7 @@ zsc_intr_soft(arg)
}
-static int
+static void
zsnull_intr(cs)
struct zs_chanstate *cs;
{
@@ -306,7 +307,7 @@ zsnull_intr(cs)
zs_write_reg(cs, 15, 0);
}
-static int
+static void
zsnull_softint(cs)
struct zs_chanstate *cs;
{
diff --git a/sys/dev/ic/z8530sc.h b/sys/dev/ic/z8530sc.h
index 57ec9c4dc91..f271fe46bde 100644
--- a/sys/dev/ic/z8530sc.h
+++ b/sys/dev/ic/z8530sc.h
@@ -1,4 +1,4 @@
-/* $NetBSD: z8530sc.h,v 1.1 1996/01/24 01:07:24 gwr Exp $ */
+/* $NetBSD: z8530sc.h,v 1.2 1996/04/10 21:44:44 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -50,10 +50,10 @@
* Function vector - per channel
*/
struct zsops {
- int (*zsop_rxint)(); /* receive char available */
- int (*zsop_stint)(); /* external/status */
- int (*zsop_txint)(); /* xmit buffer empty */
- int (*zsop_softint)(); /* process software interrupt */
+ void (*zsop_rxint)(); /* receive char available */
+ void (*zsop_stint)(); /* external/status */
+ void (*zsop_txint)(); /* xmit buffer empty */
+ void (*zsop_softint)(); /* process software interrupt */
};
extern struct zsops zsops_null;
@@ -93,9 +93,9 @@ struct zs_chanstate {
u_char cs_heldchange; /* change pending (creg != preg) */
u_char cs_rr0; /* last rr0 processed */
+ u_char cs_rr0_new; /* rr0 saved in status interrupt. */
char cs_softreq; /* need soft interrupt call */
- char cs__spare;
};
struct zsc_softc {
diff --git a/sys/dev/ic/z8530tty.c b/sys/dev/ic/z8530tty.c
index 06e059348b6..2bc08b73761 100644
--- a/sys/dev/ic/z8530tty.c
+++ b/sys/dev/ic/z8530tty.c
@@ -1,4 +1,4 @@
-/* $NetBSD: z8530tty.c,v 1.5 1996/03/18 23:06:02 gwr Exp $ */
+/* $NetBSD: z8530tty.c,v 1.6 1996/04/10 21:44:47 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -59,6 +59,7 @@
#include <sys/conf.h>
#include <sys/file.h>
#include <sys/ioctl.h>
+#include <sys/malloc.h>
#include <sys/tty.h>
#include <sys/time.h>
#include <sys/kernel.h>
@@ -85,9 +86,14 @@ extern int zs_check_kgdb();
* Note: must be a power of two!
*/
#ifndef ZSTTY_RING_SIZE
-#define ZSTTY_RING_SIZE 1024
+#define ZSTTY_RING_SIZE 2048
#endif
-#define ZSTTY_RING_MASK (ZSTTY_RING_SIZE-1)
+
+/*
+ * Make this an option variable one can patch.
+ * But be warned: this must be a power of 2!
+ */
+int zstty_rbuf_size = ZSTTY_RING_SIZE;
struct zstty_softc {
struct device zst_dev; /* required first: base device */
@@ -125,7 +131,8 @@ struct zstty_softc {
*/
u_int zst_rbget; /* ring buffer `get' index */
volatile u_int zst_rbput; /* ring buffer `put' index */
- u_short zst_rbuf[ZSTTY_RING_SIZE]; /* rr1, data pairs */
+ u_int zst_ringmask;
+ u_short *zst_rbuf; /* rr1, data pairs */
};
@@ -223,11 +230,16 @@ zstty_attach(parent, self, aux)
}
printf("\n");
- tp = zst->zst_tty = ttymalloc();
+ tp = ttymalloc();
tp->t_dev = dev;
tp->t_oproc = zsstart;
tp->t_param = zsparam;
+ zst->zst_tty = tp;
+ zst->zst_ringmask = zstty_rbuf_size - 1;
+ zst->zst_rbuf = malloc(zstty_rbuf_size * sizeof(zst->zst_rbuf[0]),
+ M_DEVBUF, M_WAITOK);
+
/*
* Hardware init
*/
@@ -786,16 +798,20 @@ zs_modem(zst, onoff)
* XXX: need to do input flow-control to avoid ring overrun.
*/
-static int
+/*
+ * receiver ready interrupt. (splzs)
+ */
+static void
zstty_rxint(cs)
register struct zs_chanstate *cs;
{
register struct zstty_softc *zst;
- register put, put_next;
+ register put, put_next, ringmask;
register u_char c, rr0, rr1;
zst = cs->cs_private;
put = zst->zst_rbput;
+ ringmask = zst->zst_ringmask;
nextchar:
@@ -812,7 +828,7 @@ nextchar:
}
zst->zst_rbuf[put] = (c << 8) | rr1;
- put_next = (put + 1) & ZSTTY_RING_MASK;
+ put_next = (put + 1) & ringmask;
/* Would overrun if increment makes (put==get). */
if (put_next == zst->zst_rbget) {
@@ -832,59 +848,93 @@ nextchar:
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return(1);
}
-static int
+/*
+ * transmitter ready interrupt. (splzs)
+ */
+static void
zstty_txint(cs)
register struct zs_chanstate *cs;
{
register struct zstty_softc *zst;
- register int count, rval;
+ register int count;
zst = cs->cs_private;
count = zst->zst_tbc;
+ /*
+ * If our transmit buffer still has data,
+ * just send the next character.
+ */
if (count > 0) {
/* Send the next char. */
+ zst->zst_tbc = --count;
zs_write_data(cs, *zst->zst_tba);
zst->zst_tba++;
- zst->zst_tbc = --count;
- rval = 0;
- } else {
- /* Nothing more to send. */
- zs_write_csr(cs, ZSWR0_RESET_TXINT);
- zst->zst_intr_flags |= INTR_TX_EMPTY;
- rval = 1; /* want softcall */
+ return;
}
- cs->cs_softreq = rval;
- return (rval);
+ zs_write_csr(cs, ZSWR0_RESET_TXINT);
+
+ /* Ask the softint routine for more output. */
+ zst->zst_intr_flags |= INTR_TX_EMPTY;
+ cs->cs_softreq = 1;
}
-static int
+/*
+ * status change interrupt. (splzs)
+ */
+static void
zstty_stint(cs)
register struct zs_chanstate *cs;
{
register struct zstty_softc *zst;
- register int rr0;
+ register struct tty *tp;
+ register u_char rr0;
zst = cs->cs_private;
+ tp = zst->zst_tty;
rr0 = zs_read_csr(cs);
zs_write_csr(cs, ZSWR0_RESET_STATUS);
- if ((rr0 & ZSRR0_BREAK) &&
+ /*
+ * The chip's hardware flow control is, as noted in zsreg.h,
+ * busted---if the DCD line goes low the chip shuts off the
+ * receiver (!). If we want hardware CTS flow control but do
+ * not have it, and carrier is now on, turn HFC on; if we have
+ * HFC now but carrier has gone low, turn it off.
+ */
+ if (rr0 & ZSRR0_DCD) {
+ if (tp->t_cflag & CCTS_OFLOW &&
+ (cs->cs_creg[3] & ZSWR3_HFC) == 0) {
+ cs->cs_creg[3] |= ZSWR3_HFC;
+ zs_write_reg(cs, 3, cs->cs_creg[3]);
+ }
+ } else {
+ if (cs->cs_creg[3] & ZSWR3_HFC) {
+ cs->cs_creg[3] &= ~ZSWR3_HFC;
+ zs_write_reg(cs, 3, cs->cs_creg[3]);
+ }
+ }
+
+ /*
+ * Check here for console break, so that we can abort
+ * even when interrupts are locking up the machine.
+ */
+ if ((rr0 & ZSRR0_BREAK) &&
(zst->zst_hwflags & ZS_HWFLAG_CONSOLE))
{
zs_abort();
- return (0);
+ return;
}
+ cs->cs_rr0_new = rr0;
zst->zst_intr_flags |= INTR_ST_CHECK;
+
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return (1);
}
/*
@@ -904,7 +954,10 @@ zsoverrun(zst, ptime, what)
}
}
-static int
+/*
+ * Software interrupt. Called at zssoft
+ */
+static void
zstty_softint(cs)
struct zs_chanstate *cs;
{
@@ -912,24 +965,29 @@ zstty_softint(cs)
register struct linesw *line;
register struct tty *tp;
register int get, c, s;
- int intr_flags;
+ int intr_flags, ringmask;
register u_short ring_data;
register u_char rr0, rr1;
zst = cs->cs_private;
tp = zst->zst_tty;
line = &linesw[tp->t_line];
+ ringmask = zst->zst_ringmask;
/* Atomically get and clear flags. */
s = splzs();
intr_flags = zst->zst_intr_flags;
zst->zst_intr_flags = 0;
- splx(s);
+
+ /*
+ * Lower to tty priority while servicing the ring.
+ */
+ (void) spltty();
if (intr_flags & INTR_RX_OVERRUN) {
/* May turn this on again below. */
intr_flags &= ~INTR_RX_OVERRUN;
- zsoverrun(zst, "ring");
+ zsoverrun(zst, &zst->zst_rotime, "ring");
}
/*
@@ -938,7 +996,7 @@ zstty_softint(cs)
get = zst->zst_rbget;
while (get != zst->zst_rbput) {
ring_data = zst->zst_rbuf[get];
- get = (get + 1) & ZSTTY_RING_MASK;
+ get = (get + 1) & ringmask;
if (ring_data & ZSRR1_DO)
intr_flags |= INTR_RX_OVERRUN;
@@ -953,25 +1011,30 @@ zstty_softint(cs)
}
zst->zst_rbget = get;
- /* If set, it is from the loop above. */
+ /*
+ * If the overrun flag is set now, it was set while
+ * copying char/status pairs from the ring, which
+ * means this was a hardware (fifo) overrun.
+ */
if (intr_flags & INTR_RX_OVERRUN) {
- zsoverrun(zst, "fifo");
+ zsoverrun(zst, &zst->zst_fotime, "fifo");
}
if (intr_flags & INTR_TX_EMPTY) {
/*
- * Transmit done. Change registers and resume,
- * or just clear BUSY.
+ * The transmitter output buffer count is zero.
+ * If we suspended output for a "held" change,
+ * then handle that now and resume. Otherwise,
+ * try to start a new output chunk.
*/
if (cs->cs_heldchange) {
- s = splzs();
+ (void) splzs();
rr0 = zs_read_csr(cs);
if ((rr0 & ZSRR0_DCD) == 0)
cs->cs_preg[3] &= ~ZSWR3_HFC;
zs_loadchannelregs(cs);
- splx(s);
+ (void) spltty();
cs->cs_heldchange = 0;
-
if (zst->zst_heldtbc &&
(tp->t_state & TS_TTSTOP) == 0)
{
@@ -993,31 +1056,11 @@ zstty_softint(cs)
if (intr_flags & INTR_ST_CHECK) {
/*
- * Status line change.
- *
- * The chip's hardware flow control is, as noted in zsreg.h,
- * busted---if the DCD line goes low the chip shuts off the
- * receiver (!). If we want hardware CTS flow control but do
- * not have it, and carrier is now on, turn HFC on; if we have
- * HFC now but carrier has gone low, turn it off.
+ * Status line change. HFC bit is run in
+ * hardware interrupt, to avoid locking
+ * at splzs here.
*/
- s = splzs();
- rr0 = zs_read_csr(cs);
- if (rr0 & ZSRR0_DCD) {
- if (tp->t_cflag & CCTS_OFLOW &&
- (cs->cs_creg[3] & ZSWR3_HFC) == 0) {
- cs->cs_creg[3] |= ZSWR3_HFC;
- zs_write_reg(cs, 3, cs->cs_creg[3]);
- }
- } else {
- if (cs->cs_creg[3] & ZSWR3_HFC) {
- cs->cs_creg[3] &= ~ZSWR3_HFC;
- zs_write_reg(cs, 3, cs->cs_creg[3]);
- }
- }
- splx(s);
-
- /* Was there a change on DCD? */
+ rr0 = cs->cs_rr0_new;
if ((rr0 ^ cs->cs_rr0) & ZSRR0_DCD) {
c = ((rr0 & ZSRR0_DCD) != 0);
if (line->l_modem(tp, c) == 0)
@@ -1026,7 +1069,7 @@ zstty_softint(cs)
cs->cs_rr0 = rr0;
}
- return (1);
+ splx(s);
}
struct zsops zsops_tty = {
diff --git a/sys/dev/ic/z8530var.h b/sys/dev/ic/z8530var.h
index e7c2e59fe3a..532ee6a336c 100644
--- a/sys/dev/ic/z8530var.h
+++ b/sys/dev/ic/z8530var.h
@@ -1,4 +1,4 @@
-/* $NetBSD: z8530var.h,v 1.1 1996/01/24 01:07:24 gwr Exp $ */
+/* $NetBSD: z8530var.h,v 1.2 1996/04/10 21:44:44 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -50,10 +50,10 @@
* Function vector - per channel
*/
struct zsops {
- int (*zsop_rxint)(); /* receive char available */
- int (*zsop_stint)(); /* external/status */
- int (*zsop_txint)(); /* xmit buffer empty */
- int (*zsop_softint)(); /* process software interrupt */
+ void (*zsop_rxint)(); /* receive char available */
+ void (*zsop_stint)(); /* external/status */
+ void (*zsop_txint)(); /* xmit buffer empty */
+ void (*zsop_softint)(); /* process software interrupt */
};
extern struct zsops zsops_null;
@@ -93,9 +93,9 @@ struct zs_chanstate {
u_char cs_heldchange; /* change pending (creg != preg) */
u_char cs_rr0; /* last rr0 processed */
+ u_char cs_rr0_new; /* rr0 saved in status interrupt. */
char cs_softreq; /* need soft interrupt call */
- char cs__spare;
};
struct zsc_softc {
diff --git a/sys/dev/sun/kbd.c b/sys/dev/sun/kbd.c
index 3a71ccb7661..4e12d3e590c 100644
--- a/sys/dev/sun/kbd.c
+++ b/sys/dev/sun/kbd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kbd.c,v 1.6 1996/03/21 22:37:26 gwr Exp $ */
+/* $NetBSD: kbd.c,v 1.7 1996/04/10 21:44:58 gwr Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -378,12 +378,18 @@ kbdselect(dev, rw, p)
return (ev_select(&k->k_events, rw, p));
}
-static int kbd_oldkeymap __P((struct kbd_state *ks,
- u_long cmd, struct okiockey *okio));
+static int kbd_ioccmd(struct kbd_softc *k, int *data);
static int kbd_iockeymap __P((struct kbd_state *ks,
u_long cmd, struct kiockeymap *kio));
+static int kbd_iocsled(struct kbd_softc *k, int *data);
+
+#ifdef KIOCGETKEY
+static int kbd_oldkeymap __P((struct kbd_state *ks,
+ u_long cmd, struct okiockey *okio));
+#endif
+
int
kbdioctl(dev, cmd, data, flag, p)
dev_t dev;
@@ -431,14 +437,7 @@ kbdioctl(dev, cmd, data, flag, p)
break;
case KIOCCMD: /* Send a command to the keyboard */
- /*
- * ``unimplemented commands are ignored'' (blech)
- * so cannot check return value from kbd_docmd
- */
- error = kbd_drain_tx(k);
- if (error == 0) {
- (void) kbd_docmd(k, *(int *)data);
- }
+ error = kbd_ioccmd(k, (int *)data);
break;
case KIOCTYPE: /* Get keyboard type */
@@ -456,8 +455,7 @@ kbdioctl(dev, cmd, data, flag, p)
break;
case KIOCSLED:
- error = kbd_drain_tx(k);
- kbd_set_leds(k, *(int *)data);
+ error = kbd_iocsled(k, (int *)data);
break;
case KIOCGLED:
@@ -489,7 +487,7 @@ kbdioctl(dev, cmd, data, flag, p)
/*
* Get/Set keymap entry
*/
-int
+static int
kbd_iockeymap(ks, cmd, kio)
struct kbd_state *ks;
u_long cmd;
@@ -574,6 +572,76 @@ kbd_oldkeymap(ks, cmd, kio)
}
#endif /* KIOCGETKEY */
+
+/*
+ * keyboard command ioctl
+ * ``unimplemented commands are ignored'' (blech)
+ */
+static int
+kbd_ioccmd(k, data)
+ struct kbd_softc *k;
+ int *data;
+{
+ struct kbd_state *ks = &k->k_state;
+ int cmd, error, s;
+
+ cmd = *data;
+ switch (cmd) {
+
+ case KBD_CMD_BELL:
+ case KBD_CMD_NOBELL:
+ /* Supported by type 2, 3, and 4 keyboards */
+ break;
+
+ case KBD_CMD_CLICK:
+ case KBD_CMD_NOCLICK:
+ /* Unsupported by type 2 keyboards */
+ if (ks->kbd_id <= KB_SUN2)
+ return (0);
+ ks->kbd_click = (cmd == KBD_CMD_CLICK);
+ break;
+
+ default:
+ return (0);
+ }
+
+ s = spltty();
+
+ error = kbd_drain_tx(k);
+ if (error == 0) {
+ kbd_output(k, cmd);
+ kbd_start_tx(k);
+ }
+
+ splx(s);
+
+ return (error);
+}
+
+/*
+ * Set LEDs ioctl.
+ */
+static int
+kbd_iocsled(k, data)
+ struct kbd_softc *k;
+ int *data;
+{
+ struct kbd_state *ks = &k->k_state;
+ int leds, error, s;
+
+ leds = *data;
+
+ s = spltty();
+ error = kbd_drain_tx(k);
+ if (error == 0) {
+ kbd_set_leds(k, leds);
+ }
+ splx(s);
+
+ return (error);
+}
+
+
/****************************************************************
* middle layers:
* - keysym to ASCII sequence
@@ -688,8 +756,7 @@ kbd_input_funckey(k, keysym)
/*
* This is called by kbd_input_raw() or by kb_repeat()
- * to deliver ASCII input. Called at splsoftclock()
- * XXX: Raise to spltty before calling kd_input() ?
+ * to deliver ASCII input. Called at spltty().
*/
void
kbd_input_keysym(k, keysym)
@@ -750,23 +817,25 @@ kbd_input_keysym(k, keysym)
/*
* This is the autorepeat timeout function.
- * (called at splsoftclock)
+ * Called at splsoftclock().
*/
void
kbd_repeat(void *arg)
{
struct kbd_softc *k = (struct kbd_softc *)arg;
+ int s = spltty();
if (k->k_repeating && k->k_repeatsym >= 0) {
kbd_input_keysym(k, k->k_repeatsym);
timeout(kbd_repeat, k, k->k_repeat_step);
}
+ splx(s);
}
/*
* Called by our kbd_softint() routine on input,
* which passes the raw hardware scan codes.
- * Note: this is called at splsoftclock()
+ * Called at spltty()
*/
void
kbd_input_raw(k, c)
@@ -881,7 +950,7 @@ kbd_input_raw(k, c)
* Interface to the lower layer (zscc)
****************************************************************/
-static int
+static void
kbd_rxint(cs)
register struct zs_chanstate *cs;
{
@@ -892,11 +961,12 @@ kbd_rxint(cs)
k = cs->cs_private;
put = k->k_rbput;
- /* Read the input data ASAP. */
- c = zs_read_data(cs);
-
- /* Save the status register too. */
+ /*
+ * First read the status, because reading the received char
+ * destroys the status of this char.
+ */
rr1 = zs_read_reg(cs, 1);
+ c = zs_read_data(cs);
if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
/* Clear the receive error. */
@@ -937,29 +1007,24 @@ kbd_rxint(cs)
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return(1);
}
-static int
+static void
kbd_txint(cs)
register struct zs_chanstate *cs;
{
register struct kbd_softc *k;
- register int count, rval;
k = cs->cs_private;
-
zs_write_csr(cs, ZSWR0_RESET_TXINT);
-
k->k_intr_flags |= INTR_TX_EMPTY;
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return (1);
}
-static int
+static void
kbd_stint(cs)
register struct zs_chanstate *cs;
{
@@ -968,7 +1033,7 @@ kbd_stint(cs)
k = cs->cs_private;
- rr0 = zs_read_csr(cs);
+ cs->cs_rr0_new = zs_read_csr(cs);
zs_write_csr(cs, ZSWR0_RESET_STATUS);
#if 0
@@ -982,14 +1047,13 @@ kbd_stint(cs)
k->k_intr_flags |= INTR_ST_CHECK;
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return (1);
}
/*
* Get input from the recieve ring and pass it on.
* Note: this is called at splsoftclock()
*/
-static int
+static void
kbd_softint(cs)
struct zs_chanstate *cs;
{
@@ -1005,7 +1069,9 @@ kbd_softint(cs)
s = splzs();
intr_flags = k->k_intr_flags;
k->k_intr_flags = 0;
- splx(s);
+
+ /* Now lower to spltty for the rest. */
+ (void) spltty();
/*
* Copy data from the receive ring to the event layer.
@@ -1059,9 +1125,10 @@ kbd_softint(cs)
*/
log(LOG_ERR, "%s: status interrupt?\n",
k->k_dev.dv_xname);
+ cs->cs_rr0 = cs->cs_rr0_new;
}
- return (1);
+ splx(s);
}
struct zsops zsops_kbd = {
@@ -1078,6 +1145,7 @@ struct zsops zsops_kbd = {
/*
* Initialization to be done at first open.
* This is called from kbdopen or kdopen (in kd.c)
+ * Called with user context.
*/
int
kbd_iopen(unit)
@@ -1146,6 +1214,9 @@ out:
return error;
}
+/*
+ * Called by kbd_input_raw, at spltty()
+ */
void
kbd_was_reset(k)
struct kbd_softc *k;
@@ -1167,14 +1238,20 @@ kbd_was_reset(k)
case KB_SUN3:
/* Type 3 keyboards come up with keyclick on */
- if (!ks->kbd_click)
- (void) kbd_docmd(k, KBD_CMD_NOCLICK);
+ if (!ks->kbd_click) {
+ /* turn off the click */
+ kbd_output(k, KBD_CMD_NOCLICK);
+ kbd_start_tx(k);
+ }
break;
case KB_SUN4:
/* Type 4 keyboards come up with keyclick off */
- if (ks->kbd_click)
- (void) kbd_docmd(k, KBD_CMD_CLICK);
+ if (ks->kbd_click) {
+ /* turn on the click */
+ kbd_output(k, KBD_CMD_CLICK);
+ kbd_start_tx(k);
+ }
break;
}
@@ -1182,6 +1259,9 @@ kbd_was_reset(k)
ks->kbd_leds = 0;
}
+/*
+ * Called by kbd_input_raw, at spltty()
+ */
void
kbd_new_layout(k)
struct kbd_softc *k;
@@ -1200,28 +1280,28 @@ kbd_new_layout(k)
/*
* Wait for output to finish.
- * Called with user context.
+ * Called at spltty(). Has user context.
*/
int
kbd_drain_tx(k)
struct kbd_softc *k;
{
- int error, s;
+ int error;
error = 0;
- s = spltty();
+
while (k->k_txflags & K_TXBUSY) {
k->k_txflags |= K_TXWANT;
error = tsleep((caddr_t)&k->k_txflags,
PZERO | PCATCH, "kbdout", 0);
}
- splx(s);
+
return (error);
}
/*
- * Send out a byte to the keyboard (i.e. reset)
- * Called with user context.
+ * Enqueue some output for the keyboard
+ * Called at spltty().
*/
void
kbd_output(k, c)
@@ -1229,9 +1309,8 @@ kbd_output(k, c)
int c; /* the data */
{
struct zs_chanstate *cs = k->k_cs;
- int put, s;
+ int put;
- s = spltty();
put = k->k_tbput;
k->k_tbuf[put] = (u_char)c;
put = (put + 1) & KBD_TX_RING_MASK;
@@ -1244,10 +1323,12 @@ kbd_output(k, c)
/* OK, really increment. */
k->k_tbput = put;
}
-
- splx(s);
}
+/*
+ * Start the sending data from the output queue
+ * Called at spltty().
+ */
void
kbd_start_tx(k)
struct kbd_softc *k;
@@ -1256,9 +1337,8 @@ kbd_start_tx(k)
int get, s;
u_char c;
- s = spltty();
if (k->k_txflags & K_TXBUSY)
- goto out;
+ return;
/* Is there anything to send? */
get = k->k_tbget;
@@ -1268,7 +1348,7 @@ kbd_start_tx(k)
k->k_txflags &= ~K_TXWANT;
wakeup((caddr_t)&k->k_txflags);
}
- goto out;
+ return;
}
/* Have something to send. */
@@ -1278,41 +1358,41 @@ kbd_start_tx(k)
k->k_txflags |= K_TXBUSY;
/* Need splzs to avoid interruption of the delay. */
- (void) splzs();
+ s = splzs();
zs_write_data(cs, c);
-
-out:
splx(s);
}
-
+/*
+ * Called at spltty by:
+ * kbd_update_leds, kbd_iocsled
+ */
void
kbd_set_leds(k, new_leds)
struct kbd_softc *k;
int new_leds;
{
struct kbd_state *ks = &k->k_state;
- int s;
-
- s = spltty();
/* Don't send unless state changes. */
if (ks->kbd_leds == new_leds)
- goto out;
+ return;
+
ks->kbd_leds = new_leds;
/* Only type 4 and later has LEDs anyway. */
if (ks->kbd_id < 4)
- goto out;
+ return;
kbd_output(k, KBD_CMD_SETLED);
kbd_output(k, new_leds);
kbd_start_tx(k);
-
-out:
- splx(s);
}
+/*
+ * Called at spltty by:
+ * kbd_input_keysym
+ */
void
kbd_update_leds(k)
struct kbd_softc *k;
@@ -1331,47 +1411,3 @@ kbd_update_leds(k)
kbd_set_leds(k, leds);
}
-
-/*
- * Execute a keyboard command; return 0 on success.
- */
-int
-kbd_docmd(k, cmd)
- struct kbd_softc *k;
- int cmd;
-{
- struct kbd_state *ks = &k->k_state;
- int error, s;
-
- switch (cmd) {
-
- case KBD_CMD_BELL:
- case KBD_CMD_NOBELL:
- /* Supported by type 2, 3, and 4 keyboards */
- break;
-
- case KBD_CMD_CLICK:
- /* Unsupported by type 2 keyboards */
- if (ks->kbd_id != KB_SUN2) {
- ks->kbd_click = 1;
- break;
- }
- return (EINVAL);
-
- case KBD_CMD_NOCLICK:
- /* Unsupported by type 2 keyboards */
- if (ks->kbd_id != KB_SUN2) {
- ks->kbd_click = 0;
- break;
- }
- return (EINVAL);
-
- default:
- return (EINVAL); /* ENOTTY? EOPNOTSUPP? */
- }
-
- kbd_output(k, cmd);
- kbd_start_tx(k);
- return (0);
-}
-
diff --git a/sys/dev/sun/ms.c b/sys/dev/sun/ms.c
index 9d7c019286c..a37665b3f29 100644
--- a/sys/dev/sun/ms.c
+++ b/sys/dev/sun/ms.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ms.c,v 1.4 1996/03/17 00:57:16 thorpej Exp $ */
+/* $NetBSD: ms.c,v 1.5 1996/04/10 21:45:01 gwr Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -478,7 +478,7 @@ out:
* Interface to the lower layer (zscc)
****************************************************************/
-static int
+static void
ms_rxint(cs)
register struct zs_chanstate *cs;
{
@@ -489,11 +489,12 @@ ms_rxint(cs)
ms = cs->cs_private;
put = ms->ms_rbput;
- /* Read the input data ASAP. */
- c = zs_read_data(cs);
-
- /* Save the status register too. */
+ /*
+ * First read the status, because reading the received char
+ * destroys the status of this char.
+ */
rr1 = zs_read_reg(cs, 1);
+ c = zs_read_data(cs);
if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
/* Clear the receive error. */
@@ -516,29 +517,24 @@ ms_rxint(cs)
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return(1);
}
-static int
+static void
ms_txint(cs)
register struct zs_chanstate *cs;
{
register struct ms_softc *ms;
- register int count, rval;
ms = cs->cs_private;
-
zs_write_csr(cs, ZSWR0_RESET_TXINT);
-
ms->ms_intr_flags |= INTR_TX_EMPTY;
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return (1);
}
-static int
+static void
ms_stint(cs)
register struct zs_chanstate *cs;
{
@@ -547,17 +543,16 @@ ms_stint(cs)
ms = cs->cs_private;
- rr0 = zs_read_csr(cs);
+ cs->cs_rr0_new = zs_read_csr(cs);
zs_write_csr(cs, ZSWR0_RESET_STATUS);
ms->ms_intr_flags |= INTR_ST_CHECK;
/* Ask for softint() call. */
cs->cs_softreq = 1;
- return (1);
}
-static int
+static void
ms_softint(cs)
struct zs_chanstate *cs;
{
@@ -573,7 +568,9 @@ ms_softint(cs)
s = splzs();
intr_flags = ms->ms_intr_flags;
ms->ms_intr_flags = 0;
- splx(s);
+
+ /* Now lower to spltty for the rest. */
+ (void) spltty();
/*
* Copy data from the receive ring to the event layer.
@@ -617,9 +614,10 @@ ms_softint(cs)
*/
log(LOG_ERR, "%s: status interrupt?\n",
ms->ms_dev.dv_xname);
+ cs->cs_rr0 = cs->cs_rr0_new;
}
- return (1);
+ splx(s);
}
struct zsops zsops_ms = {