Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/luna68k/dev Implement transmitting keyboard LED and...



details:   https://anonhg.NetBSD.org/src/rev/7fff23001a2f
branches:  trunk
changeset: 1023614:7fff23001a2f
user:      tsutsui <tsutsui%NetBSD.org@localhost>
date:      Sat Sep 18 13:44:02 2021 +0000

description:
Implement transmitting keyboard LED and buzzer control commands.

- enable TX on uPD7201 for keyboard port
- prepare TX queue and handle it in hardware interrupt and softint(9)
- send proper LED commands on WSKBDIO_SETLEDS
  (XXX: KANA LED is not handled in wscons)
- return current LED settings on WSKBDIO_GETLEDS
- implement WSKBDIO_COMPLEXBELL by parsing struct wskbd_bell_data and
  send proper buzzer commands
- handle pitch, period, and volume in cnbell(9)
  (XXX: no description in cnbell(9) man pages)
- use proper queued TX function for omms_enable() and omms_disable()
- add DPRINTF()s for debug
- use C99 designated initializer and misc cosmetics

Tested on LUNA and its keyboard (3W4SD-098NDT).

diffstat:

 sys/arch/luna68k/dev/lunaws.c |  321 ++++++++++++++++++++++++++++++++++++-----
 1 files changed, 278 insertions(+), 43 deletions(-)

diffs (truncated from 507 to 300 lines):

diff -r a65859905f88 -r 7fff23001a2f sys/arch/luna68k/dev/lunaws.c
--- a/sys/arch/luna68k/dev/lunaws.c     Sat Sep 18 12:25:06 2021 +0000
+++ b/sys/arch/luna68k/dev/lunaws.c     Sat Sep 18 13:44:02 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lunaws.c,v 1.34 2021/09/04 18:38:03 tsutsui Exp $ */
+/* $NetBSD: lunaws.c,v 1.35 2021/09/18 13:44:02 tsutsui Exp $ */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>                 /* RCS ID & Copyright macro defns */
 
-__KERNEL_RCSID(0, "$NetBSD: lunaws.c,v 1.34 2021/09/04 18:38:03 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: lunaws.c,v 1.35 2021/09/18 13:44:02 tsutsui Exp $");
 
 #include "opt_wsdisplay_compat.h"
 #include "wsmouse.h"
@@ -57,10 +57,43 @@
 #define OMKBD_RXQ_LEN          64
 #define OMKBD_RXQ_LEN_MASK     (OMKBD_RXQ_LEN - 1)
 #define OMKBD_NEXTRXQ(x)       (((x) + 1) & OMKBD_RXQ_LEN_MASK)
+#define OMKBD_TXQ_LEN          16
+#define OMKBD_TXQ_LEN_MASK     (OMKBD_TXQ_LEN - 1)
+#define OMKBD_NEXTTXQ(x)       (((x) + 1) & OMKBD_TXQ_LEN_MASK)
+
+/* Keyboard commands */
+/*  000XXXXXb : LED commands */
+#define OMKBD_LED_ON_KANA      0x10    /* kana LED on */
+#define OMKBD_LED_OFF_KANA     0x00    /* kana LED off */
+#define OMKBD_LED_ON_CAPS      0x11    /* caps LED on */
+#define OMKBD_LED_OFF_CAPS     0x01    /* caps LED off */
+/*  010XXXXXb : buzzer commands */
+#define OMKBD_BUZZER           0x40
+#define OMKBD_BUZZER_PERIOD    0x18
+#define OMKBD_BUZZER_40MS      0x00
+#define OMKBD_BUZZER_150MS     0x08
+#define OMKBD_BUZZER_400MS     0x10
+#define OMKBD_BUZZER_700MS     0x18
+#define OMKBD_BUZZER_PITCH     0x07
+#define OMKBD_BUZZER_6000HZ    0x00
+#define OMKBD_BUZZER_3000HZ    0x01
+#define OMKBD_BUZZER_1500HZ    0x02
+#define OMKBD_BUZZER_1000HZ    0x03
+#define OMKBD_BUZZER_600HZ     0x04
+#define OMKBD_BUZZER_300HZ     0x05
+#define OMKBD_BUZZER_150HZ     0x06
+#define OMKBD_BUZZER_100HZ     0x07
+/*  011XXXXXb : mouse on command */
+#define OMKBD_MOUSE_ON         0x60
+/*  001XXXXXb : mouse off command */
+#define OMKBD_MOUSE_OFF                0x20
+
+#define OMKBD_BUZZER_DEFAULT   \
+       (OMKBD_BUZZER | OMKBD_BUZZER_40MS | OMKBD_BUZZER_1500HZ)
 
 static const uint8_t ch1_regs[6] = {
        WR0_RSTINT,                             /* Reset E/S Interrupt */
-       WR1_RXALLS,                             /* Rx per char, No Tx */
+       WR1_RXALLS | WR1_TXENBL,                /* Rx per char, Tx */
        0,                                      /* */
        WR3_RX8BIT | WR3_RXENBL,                /* Rx */
        WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY,   /* Tx/Rx */
@@ -75,6 +108,12 @@
        uint8_t         sc_rxq[OMKBD_RXQ_LEN];
        u_int           sc_rxqhead;
        u_int           sc_rxqtail;
+       uint8_t         sc_txq[OMKBD_TXQ_LEN];
+       u_int           sc_txqhead;
+       u_int           sc_txqtail;
+       bool            sc_tx_busy;
+       bool            sc_tx_done;
+       int             sc_leds;
 #if NWSMOUSE > 0
        device_t        sc_wsmousedev;
        int             sc_msbuttons, sc_msdx, sc_msdy;
@@ -84,28 +123,36 @@
        int             sc_rawkbd;
 };
 
-static void omkbd_input(void *, int);
-static void omkbd_decode(void *, int, u_int *, int *);
+static void omkbd_input(struct ws_softc *, int);
+static void omkbd_send(struct ws_softc *, uint8_t);
+static void omkbd_decode(struct ws_softc *, int, u_int *, int *);
+
 static int  omkbd_enable(void *, int);
 static void omkbd_set_leds(void *, int);
 static int  omkbd_ioctl(void *, u_long, void *, int, struct lwp *);
 
+static void omkbd_complex_buzzer(struct ws_softc *, struct wskbd_bell_data *);
+static uint8_t omkbd_get_buzcmd(struct ws_softc *, struct wskbd_bell_data *,
+    uint8_t);
+
 static const struct wskbd_mapdata omkbd_keymapdata = {
-       omkbd_keydesctab,
-       KB_JP,
+       .keydesc = omkbd_keydesctab,
+       .layout  = KB_JP,
 };
 static const struct wskbd_accessops omkbd_accessops = {
-       omkbd_enable,
-       omkbd_set_leds,
-       omkbd_ioctl,
+       .enable   = omkbd_enable,
+       .set_leds = omkbd_set_leds,
+       .ioctl    = omkbd_ioctl,
 };
 
 void   ws_cnattach(void);
 static void ws_cngetc(void *, u_int *, int *);
 static void ws_cnpollc(void *, int);
+static void ws_cnbell(void *, u_int, u_int, u_int);
 static const struct wskbd_consops ws_consops = {
-       ws_cngetc,
-       ws_cnpollc,
+       .getc  = ws_cngetc,
+       .pollc = ws_cnpollc,
+       .bell  = ws_cnbell,
 };
 
 #if NWSMOUSE > 0
@@ -129,6 +176,18 @@
 CFATTACH_DECL_NEW(ws, sizeof(struct ws_softc),
     wsmatch, wsattach, NULL, NULL);
 
+/* #define LUNAWS_DEBUG */
+
+#ifdef LUNAWS_DEBUG
+#define DEBUG_KBDTX    0x01
+#define DEBUG_RXSOFT   0x02
+#define DEBUG_BUZZER   0x04
+uint32_t lunaws_debug = 0x00 /* | DEBUG_BUZZER | DEBUG_KBDTX | DEBUG_RXSOFT */;
+#define DPRINTF(x, y)   if (lunaws_debug & (x)) printf y
+#else
+#define DPRINTF(x, y)   __nothing
+#endif
+
 static int
 wsmatch(device_t parent, cfdata_t cf, void *aux)
 {
@@ -159,17 +218,24 @@
        setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]);
        setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]);
        setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]);
-       setsioreg(sc->sc_ctl, WR1, sc->sc_wr[WR1]);
-
-       syscnputc((dev_t)1, 0x20); /* keep quiet mouse */
 
        sc->sc_rxqhead = 0;
        sc->sc_rxqtail = 0;
+       sc->sc_txqhead = 0;
+       sc->sc_txqtail = 0;
+       sc->sc_tx_busy = false;
+       sc->sc_tx_done = false;
 
        sc->sc_si = softint_establish(SOFTINT_SERIAL, wssoftintr, sc);
 
+       /* enable interrupt */
+       setsioreg(sc->sc_ctl, WR1, sc->sc_wr[WR1]);
+
        aprint_normal("\n");
 
+       /* keep mouse quiet */
+       omkbd_send(sc, OMKBD_MOUSE_OFF);
+
        a.console = (args->hwflags == 1);
        a.keymap = &omkbd_keymapdata;
        a.accessops = &omkbd_accessops;
@@ -189,7 +255,6 @@
        sc->sc_msreport = 0;
 }
 
-/*ARGSUSED*/
 static void
 wsintr(void *arg)
 {
@@ -197,6 +262,7 @@
        struct sioreg *sio = sc->sc_ctl;
        uint8_t code;
        int rr;
+       bool handled = false;
 
        rr = getsiocsr(sio);
        if ((rr & RR_RXRDY) != 0) {
@@ -209,11 +275,18 @@
                        sc->sc_rxq[sc->sc_rxqtail] = code;
                        sc->sc_rxqtail = OMKBD_NEXTRXQ(sc->sc_rxqtail);
                } while (((rr = getsiocsr(sio)) & RR_RXRDY) != 0);
-               softint_schedule(sc->sc_si);
+               handled = true;
        }
-       if ((rr & RR_TXRDY) != 0)
+       if ((rr & RR_TXRDY) != 0) {
                sio->sio_cmd = WR0_RSTPEND;
-       /* not capable of transmit, yet */
+               if (sc->sc_tx_busy) {
+                       sc->sc_tx_busy = false;
+                       sc->sc_tx_done = true;
+                       handled = true;
+               }
+       }
+       if (handled)
+               softint_schedule(sc->sc_si);
 }
 
 static void
@@ -222,8 +295,32 @@
        struct ws_softc *sc = arg;
        uint8_t code;
 
+       /* handle pending keyboard commands */
+       if (sc->sc_tx_done) {
+               int s;
+
+               s = splserial();
+               sc->sc_tx_done = false;
+               DPRINTF(DEBUG_KBDTX, ("%s: tx complete\n", __func__));
+               if (sc->sc_txqhead != sc->sc_txqtail) {
+                       struct sioreg *sio = sc->sc_ctl;
+
+                       sc->sc_tx_busy = true;
+                       sio->sio_data = sc->sc_txq[sc->sc_txqhead];
+                       DPRINTF(DEBUG_KBDTX,
+                           ("%s: sio_data <- txq[%2d] (%02x)\n", __func__,
+                           sc->sc_txqhead, sc->sc_txq[sc->sc_txqhead]));
+
+                       sc->sc_txqhead = OMKBD_NEXTTXQ(sc->sc_txqhead);
+               }
+               splx(s);
+       }
+
+       /* handle received keyboard and mouse data */
        while (sc->sc_rxqhead != sc->sc_rxqtail) {
                code = sc->sc_rxq[sc->sc_rxqhead];
+               DPRINTF(DEBUG_RXSOFT, ("%s: %02x <- rxq[%2d]\n", __func__,
+                   code, sc->sc_rxqhead));
                sc->sc_rxqhead = OMKBD_NEXTRXQ(sc->sc_rxqhead);
                /*
                 * if (code >= 0x80 && code <= 0x87), i.e.
@@ -265,13 +362,38 @@
 }
 
 static void
-omkbd_input(void *v, int data)
+omkbd_send(struct ws_softc *sc, uint8_t txdata)
 {
-       struct ws_softc *sc = v;
+       int s;
+
+       if (!sc->sc_tx_busy) {
+               struct sioreg *sio = sc->sc_ctl;
+
+               DPRINTF(DEBUG_KBDTX,
+                   ("%s: sio_data <- %02x\n", __func__, txdata));
+               s = splserial();
+               sc->sc_tx_busy = true;
+               sio->sio_data = txdata;
+               splx(s);
+       } else {
+               s = splsoftserial();
+               sc->sc_txq[sc->sc_txqtail] = txdata;
+               DPRINTF(DEBUG_KBDTX,
+                   ("%s: txq[%2d] <- %02x\n", __func__,
+                   sc->sc_txqtail, sc->sc_txq[sc->sc_txqtail]));
+               sc->sc_txqtail = OMKBD_NEXTTXQ(sc->sc_txqtail);
+               splx(s);
+               softint_schedule(sc->sc_si);
+       }
+}
+
+static void
+omkbd_input(struct ws_softc *sc, int data)
+{
        u_int type;
        int key;
 
-       omkbd_decode(v, data, &type, &key);
+       omkbd_decode(sc, data, &type, &key);
 
 #ifdef WSDISPLAY_COMPAT_RAWKBD
        if (sc->sc_rawkbd) {
@@ -299,7 +421,7 @@
 }
 
 static void
-omkbd_decode(void *v, int datain, u_int *type, int *dataout)
+omkbd_decode(struct ws_softc *sc, int datain, u_int *type, int *dataout)
 {
 
        *type = (datain & 0x80) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
@@ -307,17 +429,96 @@
 }
 
 static void
-ws_cngetc(void *v, u_int *type, int *data)
+omkbd_complex_buzzer(struct ws_softc *sc, struct wskbd_bell_data *wbd)
+{
+       uint8_t buzcmd;
+



Home | Main Index | Thread Index | Old Index