1*aec26569Stsutsui /* $NetBSD: dzkbd.c,v 1.32 2024/02/14 12:49:47 tsutsui Exp $ */
247dabcfcSragge
347dabcfcSragge /*
447dabcfcSragge * Copyright (c) 1992, 1993
547dabcfcSragge * The Regents of the University of California. All rights reserved.
647dabcfcSragge *
747dabcfcSragge * This software was developed by the Computer Systems Engineering group
847dabcfcSragge * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
947dabcfcSragge * contributed to Berkeley.
1047dabcfcSragge *
1147dabcfcSragge * All advertising materials mentioning features or use of this software
1247dabcfcSragge * must display the following acknowledgement:
1347dabcfcSragge * This product includes software developed by the University of
1447dabcfcSragge * California, Lawrence Berkeley Laboratory.
1547dabcfcSragge *
1647dabcfcSragge * Redistribution and use in source and binary forms, with or without
1747dabcfcSragge * modification, are permitted provided that the following conditions
1847dabcfcSragge * are met:
1947dabcfcSragge * 1. Redistributions of source code must retain the above copyright
2047dabcfcSragge * notice, this list of conditions and the following disclaimer.
2147dabcfcSragge * 2. Redistributions in binary form must reproduce the above copyright
2247dabcfcSragge * notice, this list of conditions and the following disclaimer in the
2347dabcfcSragge * documentation and/or other materials provided with the distribution.
24aad01611Sagc * 3. Neither the name of the University nor the names of its contributors
2547dabcfcSragge * may be used to endorse or promote products derived from this software
2647dabcfcSragge * without specific prior written permission.
2747dabcfcSragge *
2847dabcfcSragge * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2947dabcfcSragge * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3047dabcfcSragge * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3147dabcfcSragge * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3247dabcfcSragge * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3347dabcfcSragge * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3447dabcfcSragge * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3547dabcfcSragge * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3647dabcfcSragge * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3747dabcfcSragge * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3847dabcfcSragge * SUCH DAMAGE.
3947dabcfcSragge *
4047dabcfcSragge * @(#)kbd.c 8.2 (Berkeley) 10/30/93
4147dabcfcSragge */
4247dabcfcSragge
4347dabcfcSragge /*
4447dabcfcSragge * LK200/LK400 keyboard attached to line 0 of the DZ*-11
4547dabcfcSragge */
4647dabcfcSragge
47dca6ccc8Slukem #include <sys/cdefs.h>
48*aec26569Stsutsui __KERNEL_RCSID(0, "$NetBSD: dzkbd.c,v 1.32 2024/02/14 12:49:47 tsutsui Exp $");
49dca6ccc8Slukem
5047dabcfcSragge #include <sys/param.h>
5147dabcfcSragge #include <sys/systm.h>
5247dabcfcSragge #include <sys/device.h>
5347dabcfcSragge #include <sys/ioctl.h>
5447dabcfcSragge #include <sys/syslog.h>
5547dabcfcSragge #include <sys/malloc.h>
564b293a84Sad #include <sys/intr.h>
5747dabcfcSragge
5847dabcfcSragge #include <dev/wscons/wsconsio.h>
5947dabcfcSragge #include <dev/wscons/wskbdvar.h>
6047dabcfcSragge #include <dev/wscons/wsksymdef.h>
6147dabcfcSragge #include <dev/wscons/wsksymvar.h>
6247dabcfcSragge #include <dev/dec/wskbdmap_lk201.h>
6347dabcfcSragge
64a2a38285Sad #include <sys/bus.h>
6547dabcfcSragge
66f89bb306Sad #include <dev/dec/dzreg.h>
67f89bb306Sad #include <dev/dec/dzvar.h>
6847dabcfcSragge #include <dev/dec/dzkbdvar.h>
6947dabcfcSragge #include <dev/dec/lk201reg.h>
7047dabcfcSragge #include <dev/dec/lk201var.h>
7147dabcfcSragge
7247dabcfcSragge #include "locators.h"
7347dabcfcSragge
7447dabcfcSragge struct dzkbd_internal {
7547dabcfcSragge struct dz_linestate *dzi_ls;
7647dabcfcSragge struct lk201_state dzi_ks;
7747dabcfcSragge };
7847dabcfcSragge
7947dabcfcSragge struct dzkbd_internal dzkbd_console_internal;
8047dabcfcSragge
8147dabcfcSragge struct dzkbd_softc {
8247dabcfcSragge struct dzkbd_internal *sc_itl;
8347dabcfcSragge
8447dabcfcSragge int sc_enabled;
8547dabcfcSragge int kbd_type;
8647dabcfcSragge
87529e91fcScegger device_t sc_wskbddev;
8847dabcfcSragge };
8947dabcfcSragge
9018db93c7Sperry static int dzkbd_input(void *, int);
9147dabcfcSragge
92529e91fcScegger static int dzkbd_match(device_t, cfdata_t, void *);
93529e91fcScegger static void dzkbd_attach(device_t, device_t, void *);
9447dabcfcSragge
95cbab9cadSchs CFATTACH_DECL_NEW(dzkbd, sizeof(struct dzkbd_softc),
96c9b3657cSthorpej dzkbd_match, dzkbd_attach, NULL, NULL);
9747dabcfcSragge
9818db93c7Sperry static int dzkbd_enable(void *, int);
9918db93c7Sperry static void dzkbd_set_leds(void *, int);
10053524e44Schristos static int dzkbd_ioctl(void *, u_long, void *, int, struct lwp *);
10147dabcfcSragge
10247dabcfcSragge const struct wskbd_accessops dzkbd_accessops = {
10347dabcfcSragge dzkbd_enable,
10447dabcfcSragge dzkbd_set_leds,
10547dabcfcSragge dzkbd_ioctl,
10647dabcfcSragge };
10747dabcfcSragge
10847dabcfcSragge static void dzkbd_cngetc(void *, u_int *, int *);
10947dabcfcSragge static void dzkbd_cnpollc(void *, int);
11047dabcfcSragge
11147dabcfcSragge const struct wskbd_consops dzkbd_consops = {
11247dabcfcSragge dzkbd_cngetc,
11347dabcfcSragge dzkbd_cnpollc,
11447dabcfcSragge };
11547dabcfcSragge
11618db93c7Sperry static int dzkbd_sendchar(void *, u_char);
11747dabcfcSragge
11847dabcfcSragge const struct wskbd_mapdata dzkbd_keymapdata = {
1190cf4c60bSad lkkbd_keydesctab,
12047dabcfcSragge #ifdef DZKBD_LAYOUT
12147dabcfcSragge DZKBD_LAYOUT,
12247dabcfcSragge #else
12347dabcfcSragge KB_US | KB_LK401,
12447dabcfcSragge #endif
12547dabcfcSragge };
12647dabcfcSragge
12747dabcfcSragge /*
12847dabcfcSragge * kbd_match: how is this dz line configured?
12947dabcfcSragge */
13047dabcfcSragge static int
dzkbd_match(device_t parent,cfdata_t cf,void * aux)131529e91fcScegger dzkbd_match(device_t parent, cfdata_t cf, void *aux)
13247dabcfcSragge {
13347dabcfcSragge struct dzkm_attach_args *daa = aux;
13447dabcfcSragge
13547dabcfcSragge /* Exact match is better than wildcard. */
13647dabcfcSragge if (cf->cf_loc[DZCF_LINE] == daa->daa_line)
13747dabcfcSragge return 2;
13847dabcfcSragge
13947dabcfcSragge /* This driver accepts wildcard. */
14047dabcfcSragge if (cf->cf_loc[DZCF_LINE] == DZCF_LINE_DEFAULT)
14147dabcfcSragge return 1;
14247dabcfcSragge
14347dabcfcSragge return 0;
14447dabcfcSragge }
14547dabcfcSragge
14647dabcfcSragge static void
dzkbd_attach(device_t parent,device_t self,void * aux)147529e91fcScegger dzkbd_attach(device_t parent, device_t self, void *aux)
14847dabcfcSragge {
14992c7bba3Sthorpej struct dz_softc *dz = device_private(parent);
15092c7bba3Sthorpej struct dzkbd_softc *dzkbd = device_private(self);
15147dabcfcSragge struct dzkm_attach_args *daa = aux;
15247dabcfcSragge struct dz_linestate *ls;
15347dabcfcSragge struct dzkbd_internal *dzi;
15447dabcfcSragge struct wskbddev_attach_args a;
15547dabcfcSragge int isconsole;
15647dabcfcSragge
15747dabcfcSragge dz->sc_dz[daa->daa_line].dz_catch = dzkbd_input;
15847dabcfcSragge dz->sc_dz[daa->daa_line].dz_private = dzkbd;
15947dabcfcSragge ls = &dz->sc_dz[daa->daa_line];
16047dabcfcSragge
16147dabcfcSragge isconsole = (daa->daa_flags & DZKBD_CONSOLE);
16247dabcfcSragge
16347dabcfcSragge if (isconsole) {
16447dabcfcSragge dzi = &dzkbd_console_internal;
16547dabcfcSragge } else {
16647dabcfcSragge dzi = malloc(sizeof(struct dzkbd_internal),
167d47bcd29Schs M_DEVBUF, M_WAITOK);
16847dabcfcSragge dzi->dzi_ks.attmt.sendchar = dzkbd_sendchar;
16947dabcfcSragge dzi->dzi_ks.attmt.cookie = ls;
17047dabcfcSragge }
17191d54c75Sad dzi->dzi_ls = ls;
17247dabcfcSragge dzkbd->sc_itl = dzi;
17347dabcfcSragge
17414b54388Stsutsui aprint_normal("\n");
17547dabcfcSragge
176fc047e36Sad if (!isconsole) {
177fc047e36Sad DELAY(100000);
17847dabcfcSragge lk201_init(&dzi->dzi_ks);
179fc047e36Sad }
18047dabcfcSragge
18147dabcfcSragge /* XXX should identify keyboard ID here XXX */
18247dabcfcSragge /* XXX layout and the number of LED is varying XXX */
18347dabcfcSragge
18447dabcfcSragge dzkbd->kbd_type = WSKBD_TYPE_LK201;
18547dabcfcSragge
18647dabcfcSragge dzkbd->sc_enabled = 1;
18747dabcfcSragge
18847dabcfcSragge a.console = isconsole;
18947dabcfcSragge a.keymap = &dzkbd_keymapdata;
19047dabcfcSragge a.accessops = &dzkbd_accessops;
19147dabcfcSragge a.accesscookie = dzkbd;
19247dabcfcSragge
193c7fb772bSthorpej dzkbd->sc_wskbddev = config_found(self, &a, wskbddevprint, CFARGS_NONE);
19447dabcfcSragge }
19547dabcfcSragge
19647dabcfcSragge int
dzkbd_cnattach(struct dz_linestate * ls)197454af1c0Sdsl dzkbd_cnattach(struct dz_linestate *ls)
19847dabcfcSragge {
19947dabcfcSragge
20047dabcfcSragge dzkbd_console_internal.dzi_ks.attmt.sendchar = dzkbd_sendchar;
20147dabcfcSragge dzkbd_console_internal.dzi_ks.attmt.cookie = ls;
20247dabcfcSragge lk201_init(&dzkbd_console_internal.dzi_ks);
20347dabcfcSragge dzkbd_console_internal.dzi_ls = ls;
20447dabcfcSragge
20547dabcfcSragge wskbd_cnattach(&dzkbd_consops, &dzkbd_console_internal,
20647dabcfcSragge &dzkbd_keymapdata);
20747dabcfcSragge
20847dabcfcSragge return 0;
20947dabcfcSragge }
21047dabcfcSragge
21147dabcfcSragge static int
dzkbd_enable(void * v,int on)212454af1c0Sdsl dzkbd_enable(void *v, int on)
21347dabcfcSragge {
21447dabcfcSragge struct dzkbd_softc *sc = v;
21547dabcfcSragge
21647dabcfcSragge sc->sc_enabled = on;
21747dabcfcSragge return 0;
21847dabcfcSragge }
21947dabcfcSragge
22047dabcfcSragge static int
dzkbd_sendchar(void * v,u_char c)221454af1c0Sdsl dzkbd_sendchar(void *v, u_char c)
22247dabcfcSragge {
22347dabcfcSragge struct dz_linestate *ls = v;
22447dabcfcSragge int s;
22547dabcfcSragge
22647dabcfcSragge s = spltty();
22747dabcfcSragge dzputc(ls, c);
22847dabcfcSragge splx(s);
22947dabcfcSragge return (0);
23047dabcfcSragge }
23147dabcfcSragge
23247dabcfcSragge static void
dzkbd_cngetc(void * v,u_int * type,int * data)233454af1c0Sdsl dzkbd_cngetc(void *v, u_int *type, int *data)
23447dabcfcSragge {
23547dabcfcSragge struct dzkbd_internal *dzi = v;
23647dabcfcSragge int c;
23747dabcfcSragge
23847dabcfcSragge do {
23947dabcfcSragge c = dzgetc(dzi->dzi_ls);
240*aec26569Stsutsui } while (lk201_decode(&dzi->dzi_ks, 0, c, type, data) == LKD_NODATA);
24147dabcfcSragge }
24247dabcfcSragge
24347dabcfcSragge static void
dzkbd_cnpollc(void * v,int on)244454af1c0Sdsl dzkbd_cnpollc(void *v, int on)
24547dabcfcSragge {
24647dabcfcSragge #if 0
24747dabcfcSragge struct dzkbd_internal *dzi = v;
24847dabcfcSragge #endif
24947dabcfcSragge }
25047dabcfcSragge
25147dabcfcSragge static void
dzkbd_set_leds(void * v,int leds)252454af1c0Sdsl dzkbd_set_leds(void *v, int leds)
25347dabcfcSragge {
25447dabcfcSragge struct dzkbd_softc *sc = (struct dzkbd_softc *)v;
25547dabcfcSragge
25647dabcfcSragge //printf("dzkbd_set_leds\n");
25747dabcfcSragge lk201_set_leds(&sc->sc_itl->dzi_ks, leds);
25847dabcfcSragge }
25947dabcfcSragge
26047dabcfcSragge static int
dzkbd_ioctl(void * v,u_long cmd,void * data,int flag,struct lwp * l)261454af1c0Sdsl dzkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
26247dabcfcSragge {
26347dabcfcSragge struct dzkbd_softc *sc = (struct dzkbd_softc *)v;
26447dabcfcSragge
26547dabcfcSragge switch (cmd) {
26647dabcfcSragge case WSKBDIO_GTYPE:
26747dabcfcSragge *(int *)data = sc->kbd_type;
26847dabcfcSragge return 0;
26947dabcfcSragge case WSKBDIO_SETLEDS:
27047dabcfcSragge lk201_set_leds(&sc->sc_itl->dzi_ks, *(int *)data);
27147dabcfcSragge return 0;
27247dabcfcSragge case WSKBDIO_GETLEDS:
27347dabcfcSragge /* XXX don't dig in kbd internals */
27447dabcfcSragge *(int *)data = sc->sc_itl->dzi_ks.leds_state;
27547dabcfcSragge return 0;
27647dabcfcSragge case WSKBDIO_COMPLEXBELL:
27747dabcfcSragge lk201_bell(&sc->sc_itl->dzi_ks,
27847dabcfcSragge (struct wskbd_bell_data *)data);
27947dabcfcSragge return 0;
28021787ea4Sad case WSKBDIO_SETKEYCLICK:
281fd3414abSchs lk201_set_keyclick(&sc->sc_itl->dzi_ks, *(int *)data);
28221787ea4Sad return 0;
28321787ea4Sad case WSKBDIO_GETKEYCLICK:
28421787ea4Sad /* XXX don't dig in kbd internals */
28521787ea4Sad *(int *)data = sc->sc_itl->dzi_ks.kcvol;
28621787ea4Sad return 0;
28747dabcfcSragge }
28831144d99Satatat return (EPASSTHROUGH);
28947dabcfcSragge }
29047dabcfcSragge
29147dabcfcSragge static int
dzkbd_input(void * v,int data)292454af1c0Sdsl dzkbd_input(void *v, int data)
29347dabcfcSragge {
29447dabcfcSragge struct dzkbd_softc *sc = (struct dzkbd_softc *)v;
29547dabcfcSragge u_int type;
29647dabcfcSragge int val;
2972d49a0d6Sjklos int decode;
29847dabcfcSragge
2992d49a0d6Sjklos do {
3002d49a0d6Sjklos decode = lk201_decode(&sc->sc_itl->dzi_ks, 1,
3012d49a0d6Sjklos data, &type, &val);
3022d49a0d6Sjklos if (decode != LKD_NODATA)
30347dabcfcSragge wskbd_input(sc->sc_wskbddev, type, val);
3042d49a0d6Sjklos } while (decode == LKD_MORE);
3052d49a0d6Sjklos
30647dabcfcSragge return(1);
30747dabcfcSragge }
308