Home | History | Annotate | Line # | Download | only in uba
      1 /*	$NetBSD: qvkbd.c,v 1.6 2022/02/12 17:09:43 riastradh Exp $	*/
      2 
      3 /* Copyright (c) 2015 Charles H. Dickman. All rights reserved.
      4  * Derived from dzkbd.c
      5  *
      6  * Copyright (c) 1992, 1993
      7  *	The Regents of the University of California.  All rights reserved.
      8  *
      9  * This software was developed by the Computer Systems Engineering group
     10  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
     11  * contributed to Berkeley.
     12  *
     13  * All advertising materials mentioning features or use of this software
     14  * must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Lawrence Berkeley Laboratory.
     17  *
     18  * Redistribution and use in source and binary forms, with or without
     19  * modification, are permitted provided that the following conditions
     20  * are met:
     21  * 1. Redistributions of source code must retain the above copyright
     22  *    notice, this list of conditions and the following disclaimer.
     23  * 2. Redistributions in binary form must reproduce the above copyright
     24  *    notice, this list of conditions and the following disclaimer in the
     25  *    documentation and/or other materials provided with the distribution.
     26  * 3. Neither the name of the University nor the names of its contributors
     27  *    may be used to endorse or promote products derived from this software
     28  *    without specific prior written permission.
     29  *
     30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     40  * SUCH DAMAGE.
     41  *
     42  *	@(#)kbd.c	8.2 (Berkeley) 10/30/93
     43  */
     44 
     45 /*
     46  * LK200/LK400 keyboard attached to line 0 of the QVSS aux port
     47  */
     48 
     49 #include <sys/cdefs.h>
     50 __KERNEL_RCSID(0, "$$");
     51 
     52 #include <sys/param.h>
     53 #include <sys/systm.h>
     54 #include <sys/device.h>
     55 #include <sys/ioctl.h>
     56 #include <sys/syslog.h>
     57 #include <sys/kmem.h>
     58 #include <sys/intr.h>
     59 
     60 #include <dev/wscons/wsconsio.h>
     61 #include <dev/wscons/wskbdvar.h>
     62 #include <dev/wscons/wsksymdef.h>
     63 #include <dev/wscons/wsksymvar.h>
     64 #include <dev/dec/wskbdmap_lk201.h>
     65 
     66 #include <sys/bus.h>
     67 
     68 #include <vax/uba/qvareg.h>
     69 #include <vax/uba/qvavar.h>
     70 #include <vax/uba/qvkbdvar.h>
     71 #include <dev/dec/lk201reg.h>
     72 #include <dev/dec/lk201var.h>
     73 
     74 #include "locators.h"
     75 
     76 struct qvkbd_internal {
     77 	struct qvaux_linestate *qvi_ls;
     78 	struct lk201_state qvi_ks;
     79 };
     80 
     81 struct qvkbd_internal qvkbd_console_internal;
     82 
     83 struct qvkbd_softc {
     84 	struct qvkbd_internal *sc_itl;
     85 
     86 	int sc_enabled;
     87 	int kbd_type;
     88 
     89 	device_t sc_wskbddev;
     90 };
     91 
     92 static int	qvkbd_input(void *, int);
     93 
     94 static int	qvkbd_match(device_t, cfdata_t, void *);
     95 static void	qvkbd_attach(device_t, device_t, void *);
     96 
     97 CFATTACH_DECL_NEW(qvkbd, sizeof(struct qvkbd_softc),
     98     qvkbd_match, qvkbd_attach, NULL, NULL);
     99 
    100 static int	qvkbd_enable(void *, int);
    101 static void	qvkbd_set_leds(void *, int);
    102 static int	qvkbd_ioctl(void *, u_long, void *, int, struct lwp *);
    103 
    104 const struct wskbd_accessops qvkbd_accessops = {
    105 	qvkbd_enable,
    106 	qvkbd_set_leds,
    107 	qvkbd_ioctl,
    108 };
    109 
    110 static void	qvkbd_cngetc(void *, u_int *, int *);
    111 static void	qvkbd_cnpollc(void *, int);
    112 int             qvkbd_cnattach(struct qvaux_linestate *);
    113 
    114 const struct wskbd_consops qvkbd_consops = {
    115 	qvkbd_cngetc,
    116 	qvkbd_cnpollc,
    117 };
    118 
    119 static int qvkbd_sendchar(void *, u_char);
    120 
    121 const struct wskbd_mapdata qvkbd_keymapdata = {
    122 	lkkbd_keydesctab,
    123 #ifdef DZKBD_LAYOUT
    124 	DZKBD_LAYOUT,
    125 #else
    126 	KB_US | KB_LK401,
    127 #endif
    128 };
    129 
    130 /*
    131  * kbd_match: how is this qvaux line configured?
    132  */
    133 static int
    134 qvkbd_match(device_t parent, cfdata_t cf, void *aux)
    135 {
    136 	struct qvauxkm_attach_args *daa = aux;
    137 
    138 	/* Exact match is better than wildcard. */
    139 	if (cf->cf_loc[QVAUXCF_LINE] == daa->daa_line) {
    140 	        //printf("qvkbd_match: return 2\n");
    141 		return 2;
    142         }
    143 	/* This driver accepts wildcard. */
    144 	if (cf->cf_loc[QVAUXCF_LINE] == QVAUXCF_LINE_DEFAULT) {
    145 	        //printf("qvkbd_match: return 1\n");
    146  		return 1;
    147        }
    148         //printf("qvkbd_match: return 0\n");
    149 	return 0;
    150 }
    151 
    152 static void
    153 qvkbd_attach(device_t parent, device_t self, void *aux)
    154 {
    155 	struct qvaux_softc *qvaux = device_private(parent);
    156 	struct qvkbd_softc *qvkbd = device_private(self);
    157 	struct qvauxkm_attach_args *daa = aux;
    158 	struct qvaux_linestate *ls;
    159 	struct qvkbd_internal *qvi;
    160 	struct wskbddev_attach_args a;
    161 	int isconsole;
    162 
    163 	qvaux->sc_qvaux[daa->daa_line].qvaux_catch = qvkbd_input;
    164 	qvaux->sc_qvaux[daa->daa_line].qvaux_private = qvkbd;
    165 	ls = &qvaux->sc_qvaux[daa->daa_line];
    166 
    167 	isconsole = (daa->daa_flags & QVAUXKBD_CONSOLE);
    168 
    169 	if (isconsole) {
    170 		qvi = &qvkbd_console_internal;
    171 	} else {
    172 		qvi = kmem_alloc(sizeof(struct qvkbd_internal), KM_SLEEP);
    173 		qvi->qvi_ks.attmt.sendchar = qvkbd_sendchar;
    174 		qvi->qvi_ks.attmt.cookie = ls;
    175 	}
    176 	qvi->qvi_ls = ls;
    177 	qvkbd->sc_itl = qvi;
    178 
    179 	printf("\n");
    180 
    181 	if (!isconsole) {
    182 		DELAY(100000);
    183 		lk201_init(&qvi->qvi_ks);
    184 	}
    185 
    186 	/* XXX should identify keyboard ID here XXX */
    187 	/* XXX layout and the number of LED is varying XXX */
    188         /* XXX ID done during kb init XXX */
    189 
    190 	// qvkbd->kbd_type = WSKBD_TYPE_LK201;
    191 
    192 	qvkbd->sc_enabled = 1;
    193 
    194 	a.console = isconsole;
    195 	a.keymap = &qvkbd_keymapdata;
    196 	a.accessops = &qvkbd_accessops;
    197 	a.accesscookie = qvkbd;
    198 
    199 	qvkbd->sc_wskbddev = config_found(self, &a, wskbddevprint, CFARGS_NONE);
    200 }
    201 
    202 int
    203 qvkbd_cnattach(struct qvaux_linestate *ls)
    204 {
    205 
    206 	qvkbd_console_internal.qvi_ks.attmt.sendchar = qvkbd_sendchar;
    207 	qvkbd_console_internal.qvi_ks.attmt.cookie = ls;
    208 	lk201_init(&qvkbd_console_internal.qvi_ks);
    209 	qvkbd_console_internal.qvi_ls = ls;
    210 
    211 	wskbd_cnattach(&qvkbd_consops, &qvkbd_console_internal,
    212 		       &qvkbd_keymapdata);
    213 
    214 	return 0;
    215 }
    216 
    217 static int
    218 qvkbd_enable(void *v, int on)
    219 {
    220 	struct qvkbd_softc *sc = v;
    221 
    222 	sc->sc_enabled = on;
    223 	return 0;
    224 }
    225 
    226 static int
    227 qvkbd_sendchar(void *v, u_char c)
    228 {
    229 	struct qvaux_linestate *ls = v;
    230 	int s;
    231 
    232 	s = spltty();
    233 	qvauxputc(ls, c);
    234 	splx(s);
    235 	return (0);
    236 }
    237 
    238 static void
    239 qvkbd_cngetc(void *v, u_int *type, int *data)
    240 {
    241 	struct qvkbd_internal *qvi = v;
    242 	int c;
    243 
    244 	do {
    245 		c = qvauxgetc(qvi->qvi_ls);
    246 	} while (!lk201_decode(&qvi->qvi_ks, 0, c, type, data));
    247 }
    248 
    249 static void
    250 qvkbd_cnpollc(void *v, int on)
    251 {
    252 #if 0
    253 	struct qvkbd_internal *qvi = v;
    254 #endif
    255 }
    256 
    257 static void
    258 qvkbd_set_leds(void *v, int leds)
    259 {
    260 	struct qvkbd_softc *sc = (struct qvkbd_softc *)v;
    261 
    262 	lk201_set_leds(&sc->sc_itl->qvi_ks, leds);
    263 }
    264 
    265 static int
    266 qvkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
    267 {
    268 	struct qvkbd_softc *sc = (struct qvkbd_softc *)v;
    269 
    270 	switch (cmd) {
    271 	case WSKBDIO_GTYPE:
    272 		*(int *)data = sc->kbd_type;
    273 		return 0;
    274 	case WSKBDIO_SETLEDS:
    275 		lk201_set_leds(&sc->sc_itl->qvi_ks, *(int *)data);
    276 		return 0;
    277 	case WSKBDIO_GETLEDS:
    278 		/* XXX don't dig in kbd internals */
    279 		*(int *)data = sc->sc_itl->qvi_ks.leds_state;
    280 		return 0;
    281 	case WSKBDIO_COMPLEXBELL:
    282 		lk201_bell(&sc->sc_itl->qvi_ks,
    283 			   (struct wskbd_bell_data *)data);
    284 		return 0;
    285 	case WSKBDIO_SETKEYCLICK:
    286 		lk201_set_keyclick(&sc->sc_itl->qvi_ks, *(int *)data);
    287 		return 0;
    288 	case WSKBDIO_GETKEYCLICK:
    289 		/* XXX don't dig in kbd internals */
    290 		*(int *)data = sc->sc_itl->qvi_ks.kcvol;
    291 		return 0;
    292 	}
    293 	return (EPASSTHROUGH);
    294 }
    295 
    296 static int
    297 qvkbd_input(void *v, int data)
    298 {
    299 	struct qvkbd_softc *sc = (struct qvkbd_softc *)v;
    300 	u_int type;
    301 	int val;
    302         int decode;
    303 
    304         do {
    305                 decode = lk201_decode(&sc->sc_itl->qvi_ks, 1,
    306                     data, &type, &val);
    307                 if (decode != LKD_NODATA)
    308                         wskbd_input(sc->sc_wskbddev, type, val);
    309         } while (decode == LKD_MORE);
    310 	return(1);
    311 }
    312