diff options
| author | gwr <gwr@NetBSD.org> | 1996-04-10 21:44:35 +0000 |
|---|---|---|
| committer | gwr <gwr@NetBSD.org> | 1996-04-10 21:44:35 +0000 |
| commit | 32d12d3be499df36aa968d255ab0a9997bc0731b (patch) | |
| tree | 6e92cef7a6bb8d8f043b486545990cf8a6c6f105 /sys/dev | |
| parent | 5eb08a6790bbacb4c9443f004a009ad6e162f644 (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.c | 47 | ||||
| -rw-r--r-- | sys/dev/ic/z8530sc.h | 12 | ||||
| -rw-r--r-- | sys/dev/ic/z8530tty.c | 167 | ||||
| -rw-r--r-- | sys/dev/ic/z8530var.h | 12 | ||||
| -rw-r--r-- | sys/dev/sun/kbd.c | 252 | ||||
| -rw-r--r-- | sys/dev/sun/ms.c | 34 |
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 = { |
