xref: /netbsd-src/sys/dev/dec/dzkbd.c (revision aec2656993e63c6aede8590e26478e9e90353ad2)
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